PageRenderTime 44ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/bitrix/modules/main/classes/general/component_engine.php

https://gitlab.com/Rad1calDreamer/honey
PHP | 358 lines | 241 code | 17 blank | 100 comment | 38 complexity | 04b85a06bc654a7069be6ace1ccecd31 MD5 | raw file
  1. <?php
  2. /**
  3. * Bitrix Framework
  4. * @package bitrix
  5. * @subpackage main
  6. * @copyright 2001-2013 Bitrix
  7. */
  8. class CComponentEngine
  9. {
  10. private $component = null;
  11. private $greedyParts = array();
  12. private $resolveCallback = false;
  13. /**
  14. * Constructor.
  15. *
  16. * <p>Takes component as parameter and initializing the object.</p>
  17. * @param CBitrixComponent $component
  18. */
  19. function __construct($component = null)
  20. {
  21. if ($component instanceof CBitrixComponent)
  22. $this->component = $component;
  23. }
  24. /**
  25. * Returns associated component.
  26. *
  27. * @return CBitrixComponent
  28. *
  29. */
  30. public function getComponent()
  31. {
  32. return $this->component;
  33. }
  34. /**
  35. * Marks one of the page templates parts as greedy (may contain "/" separator).
  36. *
  37. * @param string $part
  38. * @return void
  39. *
  40. */
  41. public function addGreedyPart($part)
  42. {
  43. $part = trim($part, " \t\n\r#");
  44. if ($part != "")
  45. $this->greedyParts[$part] = preg_quote($part, "'");
  46. }
  47. /**
  48. * Registers callback with will be called on page indetermination.
  49. *
  50. * @param callback $resolveCallback
  51. * @return void
  52. *
  53. */
  54. public function setResolveCallback($resolveCallback)
  55. {
  56. if (is_callable($resolveCallback))
  57. $this->resolveCallback = $resolveCallback;
  58. }
  59. /**
  60. * Checks if component name is valid.
  61. *
  62. * <p>Component name consists of namespace part, separator and name. Example: bitrix:news.list</p>
  63. * @param string $componentName
  64. * @return bool
  65. *
  66. */
  67. public static function checkComponentName($componentName)
  68. {
  69. return ($componentName <> '' && preg_match("#^([A-Za-z0-9_.-]+:)?([A-Za-z0-9_-]+\\.)*([A-Za-z0-9_-]+)$#i", $componentName));
  70. }
  71. /**
  72. * Makes filesystem relative path out of com name.
  73. *
  74. * @param string $componentName
  75. * @return string
  76. *
  77. */
  78. public static function makeComponentPath($componentName)
  79. {
  80. if(!CComponentEngine::checkComponentName($componentName))
  81. return "";
  82. return "/".str_replace(":", "/", $componentName);
  83. }
  84. /**
  85. * Checks if page template has templates in it.
  86. *
  87. * @param string $pageTemplate
  88. * @return bool
  89. *
  90. */
  91. public function hasNoVariables($pageTemplate)
  92. {
  93. return strpos($pageTemplate, "#") === false;
  94. }
  95. /**
  96. * Checks if page template.has greedy templates it it.
  97. *
  98. * @param string $pageTemplate
  99. * @return bool
  100. *
  101. */
  102. public function hasGreedyParts($pageTemplate)
  103. {
  104. if (
  105. !empty($this->greedyParts)
  106. && preg_match("'#(?:".implode("|", $this->greedyParts).")#'", $pageTemplate)
  107. )
  108. return true;
  109. else
  110. return false;
  111. }
  112. /**
  113. * Sorts templates for inspection.
  114. *
  115. * <p>First will be templates without any variables. Then templates without greedy parts. Then greedy ones.</p>
  116. * @param array[string]string $arUrlTemplates
  117. * @param bool &$bHasGreedyPartsInTemplates
  118. * @return array[string]string
  119. *
  120. */
  121. protected function sortUrlTemplates($arUrlTemplates, &$bHasGreedyPartsInTemplates)
  122. {
  123. $resultNoHash = array();
  124. $resultWithHash = array();
  125. $resultWithGreedy = array();
  126. foreach ($arUrlTemplates as $pageID => $pageTemplate)
  127. {
  128. $pos = strpos($pageTemplate, "?");
  129. if ($pos !== false)
  130. $pageTemplate = substr($pageTemplate, 0, $pos);
  131. if ($this->hasNoVariables($pageTemplate))
  132. $resultNoHash[$pageID] = $pageTemplate;
  133. elseif ($this->hasGreedyParts($pageTemplate))
  134. $resultWithGreedy[$pageID] = $pageTemplate;
  135. else
  136. $resultWithHash[$pageID] = $pageTemplate;
  137. }
  138. $bHasGreedyPartsInTemplates = !empty($resultWithGreedy);
  139. return array_merge($resultNoHash, $resultWithHash, $resultWithGreedy);
  140. }
  141. /**
  142. * Checks if page template matches current URL.
  143. *
  144. * <p>In case of succsessful match fills in parsed variables.</p>
  145. * @param string $pageTemplate
  146. * @param string $currentPageUrl
  147. * @param array[string]string &$arVariables
  148. * @return bool
  149. *
  150. */
  151. protected function __checkPath4Template($pageTemplate, $currentPageUrl, &$arVariables)
  152. {
  153. if (!empty($this->greedyParts))
  154. {
  155. $pageTemplateReg = preg_replace("'#(?:".implode("|", $this->greedyParts).")#'", "(.+?)", $pageTemplate);
  156. $pageTemplateReg = preg_replace("'#[^#]+?#'", "([^/]+?)", $pageTemplateReg);
  157. }
  158. else
  159. {
  160. $pageTemplateReg = preg_replace("'#[^#]+?#'", "([^/]+?)", $pageTemplate);
  161. }
  162. if (substr($pageTemplateReg, -1, 1) == "/")
  163. $pageTemplateReg .= "index\\.php";
  164. $arValues = array();
  165. if (preg_match("'^".$pageTemplateReg."$'", $currentPageUrl, $arValues))
  166. {
  167. $arMatches = array();
  168. if (preg_match_all("'#([^#]+?)#'", $pageTemplate, $arMatches))
  169. {
  170. for ($i = 0, $cnt = count($arMatches[1]); $i < $cnt; $i++)
  171. $arVariables[$arMatches[1][$i]] = $arValues[$i + 1];
  172. }
  173. return true;
  174. }
  175. return false;
  176. }
  177. /**
  178. * Finds match between requestURL and on of the url templates.
  179. *
  180. * @param string $folder404
  181. * @param array[string]string $arUrlTemplates
  182. * @param array[string]string &$arVariables
  183. * @param string|bool $requestURL
  184. * @return string
  185. *
  186. */
  187. public static function parseComponentPath($folder404, $arUrlTemplates, &$arVariables, $requestURL = false)
  188. {
  189. $engine = new CComponentEngine();
  190. return $engine->guessComponentPath($folder404, $arUrlTemplates, $arVariables, $requestURL);
  191. }
  192. /**
  193. * Finds match between requestURL and on of the url templates.
  194. *
  195. * <p>Lets using the engine object and greedy templates.</p>
  196. * @param string $folder404
  197. * @param array[string]string $arUrlTemplates
  198. * @param array[string]string &$arVariables
  199. * @param string|bool $requestURL
  200. * @return string
  201. *
  202. */
  203. public function guessComponentPath($folder404, $arUrlTemplates, &$arVariables, $requestURL = false)
  204. {
  205. if (!isset($arVariables) || !is_array($arVariables))
  206. $arVariables = array();
  207. if ($requestURL === false)
  208. $requestURL = Bitrix\Main\Context::getCurrent()->getRequest()->getRequestedPage();
  209. $folder404 = str_replace("\\", "/", $folder404);
  210. if ($folder404 != "/")
  211. $folder404 = "/".trim($folder404, "/ \t\n\r\0\x0B")."/";
  212. //SEF base URL must match curent URL (several components on the same page)
  213. if(strpos($requestURL, $folder404) !== 0)
  214. return false;
  215. $currentPageUrl = substr($requestURL, strlen($folder404));
  216. $pageCandidates = array();
  217. $arUrlTemplates = $this->sortUrlTemplates($arUrlTemplates, $bHasGreedyPartsInTemplates);
  218. if (
  219. $bHasGreedyPartsInTemplates
  220. && is_callable($this->resolveCallback)
  221. )
  222. {
  223. foreach ($arUrlTemplates as $pageID => $pageTemplate)
  224. {
  225. $arVariablesTmp = $arVariables;
  226. if ($this->__CheckPath4Template($pageTemplate, $currentPageUrl, $arVariablesTmp))
  227. {
  228. if ($this->hasNoVariables($pageTemplate))
  229. {
  230. $arVariables = $arVariablesTmp;
  231. return $pageID;
  232. }
  233. else
  234. {
  235. $pageCandidates[$pageID] = $arVariablesTmp;
  236. }
  237. }
  238. }
  239. }
  240. else
  241. {
  242. foreach ($arUrlTemplates as $pageID => $pageTemplate)
  243. {
  244. if ($this->__CheckPath4Template($pageTemplate, $currentPageUrl, $arVariables))
  245. {
  246. return $pageID;
  247. }
  248. }
  249. }
  250. if (!empty($pageCandidates) && is_callable($this->resolveCallback))
  251. {
  252. return call_user_func_array($this->resolveCallback, array($this, $pageCandidates, &$arVariables));
  253. }
  254. return false;
  255. }
  256. /**
  257. * Initializes component variables from $_REQUEST based on component page selected.
  258. *
  259. * @param string $componentPage
  260. * @param array[string]string $arComponentVariables
  261. * @param array[string]string $arVariableAliases
  262. * @param array[string]string &$arVariables
  263. * @return void
  264. *
  265. */
  266. public static function initComponentVariables($componentPage, $arComponentVariables, $arVariableAliases, &$arVariables)
  267. {
  268. if (!isset($arVariables) || !is_array($arVariables))
  269. $arVariables = array();
  270. if ($componentPage)
  271. {
  272. if (array_key_exists($componentPage, $arVariableAliases) && is_array($arVariableAliases[$componentPage]))
  273. {
  274. foreach ($arVariableAliases[$componentPage] as $variableName => $aliasName)
  275. if (!array_key_exists($variableName, $arVariables))
  276. $arVariables[$variableName] = $_REQUEST[$aliasName];
  277. }
  278. }
  279. else
  280. {
  281. foreach ($arVariableAliases as $variableName => $aliasName)
  282. if (!array_key_exists($variableName, $arVariables))
  283. if (is_string($aliasName) && array_key_exists($aliasName, $_REQUEST))
  284. $arVariables[$variableName] = $_REQUEST[$aliasName];
  285. }
  286. for ($i = 0, $cnt = count($arComponentVariables); $i < $cnt; $i++)
  287. if (!array_key_exists($arComponentVariables[$i], $arVariables)
  288. && array_key_exists($arComponentVariables[$i], $_REQUEST))
  289. {
  290. $arVariables[$arComponentVariables[$i]] = $_REQUEST[$arComponentVariables[$i]];
  291. }
  292. }
  293. /**
  294. * Prepares templates based on default and provided.
  295. *
  296. * @param array[string]string $arDefaultUrlTemplates
  297. * @param array[string]string $arCustomUrlTemplates
  298. * @return array[string]string
  299. *
  300. */
  301. public static function makeComponentUrlTemplates($arDefaultUrlTemplates, $arCustomUrlTemplates)
  302. {
  303. if (!is_array($arCustomUrlTemplates))
  304. $arCustomUrlTemplates = array();
  305. return array_merge($arDefaultUrlTemplates, $arCustomUrlTemplates);
  306. }
  307. /**
  308. * Prepares variables based on default and provided.
  309. *
  310. * @param array[string]string $arDefaultVariableAliases
  311. * @param array[string]string $arCustomVariableAliases
  312. * @return array[string]string
  313. *
  314. */
  315. public static function makeComponentVariableAliases($arDefaultVariableAliases, $arCustomVariableAliases)
  316. {
  317. if (!is_array($arCustomVariableAliases))
  318. $arCustomVariableAliases = array();
  319. return array_merge($arDefaultVariableAliases, $arCustomVariableAliases);
  320. }
  321. /**
  322. * Replaces templates in provided string based on parameters
  323. *
  324. * @param string $template
  325. * @param array[string]string $arParams
  326. * @return string
  327. *
  328. */
  329. public static function makePathFromTemplate($template, $arParams = array())
  330. {
  331. $arPatterns = array("#SITE_DIR#", "#SITE#", "#SERVER_NAME#");
  332. $arReplace = array(SITE_DIR, SITE_ID, SITE_SERVER_NAME);
  333. foreach ($arParams as $key => $value)
  334. {
  335. $arPatterns[] = "#".$key."#";
  336. $arReplace[] = $value;
  337. }
  338. return str_replace($arPatterns, $arReplace, $template);
  339. }
  340. }