PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/core/loader.php

https://github.com/GinoPane/fantasia
PHP | 984 lines | 608 code | 138 blank | 238 comment | 96 complexity | ba673f2b04bf2773cd189e386f604613 MD5 | raw file
  1. <?php
  2. include_once(Loader::getDirectPath('{core}/{classes}/{framework}/cache/cache.{class_ext}'));
  3. class Loader {
  4. /**
  5. *
  6. * Are used for straight lookup files
  7. *
  8. * @var array
  9. */
  10. private static $_lookupDirs = array();
  11. /**
  12. *
  13. * @var CacheInterface
  14. */
  15. private static $_cache = null;
  16. /**
  17. *
  18. * @var array
  19. */
  20. private static $_cacheData = array();
  21. /**
  22. * @var int $pathsKey is unique identifier for paths combination
  23. */
  24. private static $_pathsKey = 0;
  25. /**
  26. *
  27. * Used for directories for recursive searching
  28. *
  29. * @var array
  30. */
  31. private static $_paths = array();
  32. /**
  33. *
  34. * Store replacement data for main configuration
  35. *
  36. * @var array
  37. */
  38. private static $_replacement = array();
  39. /**
  40. *
  41. * Returns absolute path from given related
  42. *
  43. * @param string|array $filepath relative path as string or array parts
  44. * @param array $options set of options if needed
  45. * @return string
  46. */
  47. public static function getDirectPath($filePath, $options = array())
  48. {
  49. if (is_array($filePath))
  50. {
  51. $filePath = self::arrayToPath($filePath);
  52. }
  53. $filePath = self::replaceCfgPlaceholders($filePath, $options);
  54. return Cfg_App::$DOCUMENT_ROOT . $filePath;
  55. }
  56. public static function getPackTplFilePath($template, $options = array())
  57. {
  58. $packName = App::getCurrentRoute()->getPackName();
  59. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  60. return self::getDirectPath("{packs}/{pack_name}/{media}/{tpl}/{$template}.{tpl_ext}", array('packName' => $packName));
  61. }
  62. public static function getComponentTplFilePath($template, $options = array())
  63. {
  64. $packName = App::getCurrentRoute()->getPackName();
  65. $componentName = App::getCurrentRoute()->getComponentName();
  66. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  67. return self::getDirectPath("{packs}/{pack_name}/{components}/{component_name}/{media}/{tpl}/{$template}.{tpl_ext}",
  68. array('packName' => $packName, 'componentName' => $componentName));
  69. }
  70. public static function getSystemTplFilePath($template)
  71. {
  72. return self::getDirectPath("{media}/{tpl}/{$template}.{tpl_ext}");
  73. }
  74. /**
  75. *
  76. * Returns file path of the pack controller
  77. *
  78. * @param string $packName
  79. * @param array $options
  80. * @return string
  81. */
  82. public static function getPackControllerFilePath($packName, $options = array())
  83. {
  84. $controllerName = Cfg_App::getPackOption(Cfg_App::KEY_DEFAULT_CONTROLLER_NAME, $packName);
  85. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  86. return self::getDirectPath("{packs}/{pack_name}/{controllers}/{$controllerName}.{class_ext}", array('packName' => $packName));
  87. }
  88. /**
  89. *
  90. * Returns file path of the component controller
  91. *
  92. * @param string $componentName
  93. * @param array $options
  94. * @return string
  95. */
  96. public static function getComponentControllerFilePath($componentName, $options = array())
  97. {
  98. $packName = App::getCurrentRoute()->getPackName();
  99. $controllerName = Cfg_App::getPackOption(Cfg_App::KEY_DEFAULT_CONTROLLER_NAME, $packName);
  100. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  101. return self::getDirectPath("{packs}/{pack_name}/{components}/{component_name}/{controllers}/{$controllerName}.{class_ext}",
  102. array('packName' => $packName, 'componentName' => $componentName));
  103. }
  104. /**
  105. *
  106. * Returns file path of the module controller
  107. *
  108. * @param string $moduleName
  109. * @param array $options
  110. * @return string
  111. */
  112. public static function getModuleControllerFilePath($moduleName, $options = array())
  113. {
  114. $packName = App::getCurrentRoute()->getPackName();
  115. $controllerName = Cfg_App::getPackOption(Cfg_App::KEY_DEFAULT_CONTROLLER_NAME, $packName);
  116. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  117. return self::getDirectPath("{packs}/{pack_name}/{modules}/{module_name}/{controllers}/{$controllerName}.{class_ext}",
  118. array('packName' => $packName, 'moduleName' => $moduleName));
  119. }
  120. public static function getCacheDirectoryPath($subDirectory = "")
  121. {
  122. if (!$subDirectory)
  123. $subDirectory = Cfg_App::_(Cfg_App::KEY_APP_SUBDIR);
  124. return self::getDirectPath("{core}/{cache}/{$subDirectory}");
  125. }
  126. public static function loadConfigurationFromFile($configFileName)
  127. {
  128. if (is_file($configFileName) && is_readable($configFileName))
  129. {
  130. $cfgData = include($configFileName);
  131. if (is_array($cfgData))
  132. {
  133. return $cfgData;
  134. }
  135. else
  136. {
  137. trigger_error("File \"{$configFileName}\" should return array as configuration settings!", E_USER_WARNING);
  138. }
  139. }
  140. else
  141. {
  142. return array();
  143. }
  144. }
  145. /**
  146. *
  147. * Returns configuration file path for the pack
  148. *
  149. * @param stirng $packName
  150. * @return string
  151. */
  152. public static function getPackConfigurationFilePath($packName)
  153. {
  154. return self::getDirectPath("packs/{$packName}/{cfg_dir}/{cfg_pack_file}");
  155. }
  156. /**
  157. *
  158. * Returns db configuration file path for the pack
  159. *
  160. * @param stirng $packName
  161. * @return string
  162. */
  163. public static function getPackDbConfigurationFilePath($packName)
  164. {
  165. return self::getDirectPath("packs/{$packName}/{cfg_dir}/{cfg_db_file}");
  166. }
  167. /**
  168. *
  169. * Returns data from pack config
  170. *
  171. * @param string $packName
  172. * @return array
  173. */
  174. public static function getPackConfiguration($packName)
  175. {
  176. $configFileName = self::getPackConfigurationFilePath($packName);
  177. return self::loadConfigurationFromFile($configFileName);
  178. }
  179. /**
  180. *
  181. * Returns data from pack db config
  182. *
  183. * @param string $packName
  184. * @return array
  185. */
  186. public static function getPackDbConfiguration($packName)
  187. {
  188. $configFileName = self::getPackDbConfigurationFilePath($packName);
  189. return self::loadConfigurationFromFile($configFileName);
  190. }
  191. /**
  192. *
  193. * @param string $className class name to be loaded
  194. * @param string $options
  195. *
  196. * @return bool
  197. */
  198. public static function loadClass($className, $options = array())
  199. {
  200. $fileToInclude = "";
  201. $packName = App::getCurrentRoute() ? App::getCurrentRoute()->getPackName() : "";
  202. $componentName = App::getCurrentRoute() ? App::getCurrentRoute()->getComponentName() : "";
  203. $searchInPackOnly = false;
  204. $searchInComponentOnly = false;
  205. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  206. $options['packName'] = $packName;
  207. $options['componentName'] = $componentName;
  208. if (Cfg_App::$AUTOLOADER_CACHE_ENABLED)
  209. {
  210. $fileToInclude = self::classFileCacheLookup($className, array('pathsKey' => self::_getCustomPathsKey($options)));
  211. $options['fromCache'] = (bool)$fileToInclude;
  212. }
  213. if (!$fileToInclude)
  214. {
  215. if (false == ($fileToInclude = self::classFileStraightLookupTest($className,
  216. self::_getFilePathPartByClassName($className, $packName),
  217. $options)))
  218. {
  219. if (!($searchInPackOnly || $searchInComponentOnly))
  220. {
  221. $fileToInclude = self::classFileRecursiveLookup(self::_getFilePathPartByClassName($className),
  222. $options);
  223. }
  224. }
  225. }
  226. return self::checkIncludeClassFile($className, $fileToInclude, $options);
  227. }
  228. /**
  229. *
  230. * @param string $className
  231. * @param string $packName
  232. * @param bool $throws
  233. * @return bool
  234. */
  235. public static function loadPackClass($className, $packName, $throws = false)
  236. {
  237. return self::loadClass($className, array(
  238. 'packName' => $packName,
  239. 'searchInPackOnly' => true,
  240. 'throws' => $throws
  241. ));
  242. }
  243. /**
  244. *
  245. * @param string $className
  246. * @param string $packName
  247. * @param bool $throws
  248. * @return bool
  249. */
  250. public static function loadComponentClass($className, $componentName, $packName, $throws = false)
  251. {
  252. return self::loadClass($className, array(
  253. 'packName' => $packName,
  254. 'componentName' => $componentName,
  255. 'searchInComponentOnly' => true,
  256. 'throws' => $throws
  257. ));
  258. }
  259. /**
  260. *
  261. * @param Cache_Interface $cache instance of your caching object for autoloader
  262. */
  263. public static function setCache(Cache_Interface $cache)
  264. {
  265. self::$_cache = $cache;
  266. self::$_cacheData = $cache->get(Cfg_App::_(Cfg_App::KEY_AUTOLOADER_CACHE));
  267. }
  268. /**
  269. *
  270. * @param string $className
  271. * @param string $fileToInclude
  272. * @param string $pathsKey practically unique identifier
  273. */
  274. public static function cacheFilePath($className, $fileToInclude, $pathsKey = "")
  275. {
  276. if (!$pathsKey)
  277. $pathsKey = self::$_pathsKey;
  278. if (Cfg_App::$AUTOLOADER_CACHE_ENABLED && self::$_cache)
  279. {
  280. if (!isset(self::$_cacheData[$className]) || !is_array(self::$_cacheData[$className]))
  281. {
  282. self::$_cacheData[$className] = array();
  283. }
  284. self::$_cacheData[$className][$pathsKey] = $fileToInclude;
  285. self::flushCache();
  286. }
  287. }
  288. private static function _getCustomPathsKey($options)
  289. {
  290. $componentName = "";
  291. $packName = "";
  292. $searchInPackOnly = false;
  293. $searchInComponentOnly = false;
  294. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  295. if ($searchInComponentOnly)
  296. {
  297. return self::_getStringIdentifier(self::$_pathsKey . $componentName);
  298. }
  299. elseif($searchInPackOnly)
  300. {
  301. return self::_getStringIdentifier(self::$_pathsKey . $packName);
  302. }
  303. else
  304. {
  305. return self::$_pathsKey;
  306. }
  307. }
  308. /**
  309. *
  310. * Saves cache data
  311. *
  312. * @return bool true on success, false otherwise
  313. */
  314. public static function flushCache()
  315. {
  316. if (self::$_cache)
  317. {
  318. $data = self::_arrayMergeRecursiveDistinct((array)self::$_cache->get(Cfg_App::_(Cfg_App::KEY_AUTOLOADER_CACHE)), (array)self::$_cacheData);
  319. return self::$_cache->set(Cfg_App::_(Cfg_App::KEY_AUTOLOADER_CACHE), $data);
  320. }
  321. }
  322. /**
  323. *
  324. * Adds a path to the path collection to perform searching in
  325. *
  326. * @param string|array $paths realtive paths to directory
  327. */
  328. public static function setIncludePaths($paths)
  329. {
  330. if (!is_array($paths))
  331. $paths = (array)$paths;
  332. foreach($paths as $path)
  333. {
  334. array_push(self::$_paths, self::getDirectPath($path));
  335. }
  336. $tmpPaths = self::$_paths;
  337. sort($tmpPaths, SORT_STRING);
  338. self::$_pathsKey = self::_getStringIdentifier(implode(",", $tmpPaths));
  339. }
  340. public static function getIncludePaths()
  341. {
  342. return self::$_paths;
  343. }
  344. public static function clearIncludePaths()
  345. {
  346. self::$_paths = array();
  347. self::$_pathsKey = self::_getStringIdentifier("");
  348. }
  349. /**
  350. *
  351. * Performs lookup of file to include in the file cache
  352. *
  353. * @param string $className Class name to look for
  354. * @param array $options Some options to perform searching. 'pathsKey' - define this key
  355. * as unique identifier for current class
  356. *
  357. * @return string path to included file
  358. */
  359. public static function classFileCacheLookup($className, $options = array())
  360. {
  361. $pathsKey = self::$_pathsKey;
  362. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  363. if (self::$_cache && self::$_cacheData)
  364. {
  365. return isset(self::$_cacheData[$className][$pathsKey]) ? self::$_cacheData[$className][$pathsKey] : "";
  366. }
  367. else
  368. {
  369. return "";
  370. }
  371. }
  372. /**
  373. *
  374. * @param string $className File name to be look for
  375. * @param string $classFile
  376. * @param array $options
  377. * @return string
  378. */
  379. public static function classFileStraightLookup($className, $classFile, $options = array())
  380. {
  381. $packName = "";
  382. $componentName = "";
  383. $searchInPackOnly = "";
  384. $searchInComponentOnly = "";
  385. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  386. if (!preg_match('/table$/i', $className))
  387. {
  388. $classesPath = Cfg_App::_(Cfg_App::KEY_CLASSES_PATH);
  389. $packClassesPath = Cfg_Pack::_(Cfg_App::KEY_CLASSES_PATH);
  390. }
  391. else
  392. {
  393. $classesPath = Cfg_App::_(Cfg_App::KEY_DATA_CLASSES_PATH);
  394. $packClassesPath = Cfg_Pack::_(Cfg_App::KEY_DATA_CLASSES_PATH);
  395. }
  396. $toRequire = "";
  397. if($searchInComponentOnly && !$searchInPackOnly)
  398. {
  399. if ($componentName && $packName)
  400. {
  401. $componentClassNameFile = self::getDirectPath(array(
  402. Cfg_App::_(Cfg_App::KEY_PACKS_PATH),
  403. $packName,
  404. Cfg_App::_(Cfg_App::KEY_COMPONENTS),
  405. $componentName,
  406. $packClassesPath,
  407. $classFile
  408. ));
  409. }
  410. if (isset($componentClassNameFile) && is_file($componentClassNameFile) && is_readable($componentClassNameFile))
  411. {
  412. $toRequire = $componentClassNameFile;
  413. }
  414. }
  415. elseif($searchInPackOnly && !$searchInComponentOnly)
  416. {
  417. if ($packName)
  418. {
  419. $packClassNameFile = self::getDirectPath(array(
  420. Cfg_App::_(Cfg_App::KEY_PACKS_PATH),
  421. $packName,
  422. $packClassesPath,
  423. $classFile
  424. ));
  425. }
  426. if (isset($packClassNameFile) && is_file($packClassNameFile) && is_readable($packClassNameFile))
  427. {
  428. $toRequire = $packClassNameFile;
  429. }
  430. }
  431. else
  432. {
  433. if ($componentName && $packName)
  434. {
  435. $componentClassNameFile = self::getDirectPath(array(
  436. Cfg_App::_(Cfg_App::KEY_PACKS_PATH),
  437. $packName,
  438. Cfg_App::_(Cfg_App::KEY_COMPONENTS),
  439. $componentName,
  440. $packClassesPath,
  441. $classFile
  442. ));
  443. }
  444. if(isset($componentClassNameFile) && is_file($componentClassNameFile) && is_readable($componentClassNameFile))
  445. {
  446. $toRequire = $componentClassNameFile;
  447. }
  448. else
  449. {
  450. if ($packName)
  451. {
  452. $packClassNameFile = self::getDirectPath(array(
  453. Cfg_App::_(Cfg_App::KEY_PACKS_PATH),
  454. $packName,
  455. $packClassesPath,
  456. $classFile
  457. ));
  458. }
  459. if (isset($packClassNameFile) && is_file($packClassNameFile) && is_readable($packClassNameFile))
  460. {
  461. $toRequire = $packClassNameFile;
  462. }
  463. else
  464. {
  465. $customClassNameFile = self::getDirectPath(array(
  466. Cfg_App::_(Cfg_App::KEY_CORE_PATH),
  467. $classesPath,
  468. Cfg_App::_(Cfg_App::KEY_USER_CLASSES),
  469. $classFile));
  470. if (is_file($customClassNameFile) && is_readable($customClassNameFile))
  471. {
  472. $toRequire = $customClassNameFile;
  473. }
  474. else
  475. {
  476. $classNameFile = self::getDirectPath(array(
  477. Cfg_App::_(Cfg_App::KEY_CORE_PATH),
  478. $classesPath,
  479. Cfg_App::_(Cfg_App::KEY_FRAMEWORK_CLASSES),
  480. $classFile));
  481. if(is_file($classNameFile) && is_readable($classNameFile))
  482. {
  483. $toRequire = $classNameFile;
  484. }
  485. }
  486. }
  487. }
  488. }
  489. return $toRequire;
  490. }
  491. /**
  492. *
  493. * @param string $className File name to be look for
  494. * @param string $classFile
  495. * @param array $options
  496. * @return string
  497. */
  498. public static function classFileStraightLookupTest($className, $classFile, $options = array())
  499. {
  500. // $packName = "";
  501. // $componentName = "";
  502. //
  503. $searchInPackOnly = "";
  504. $searchInComponentOnly = "";
  505. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  506. $options['classDirType'] = self::_getClassDirType($className);
  507. $toRequire = "";
  508. $dirs = array();
  509. if($searchInComponentOnly && !$searchInPackOnly)
  510. {
  511. $dirs = array_merge($dirs, array_values(self::$_lookupDirs[Cfg_App::COMPONENT_LOOKUP_PATHS]));
  512. }
  513. elseif($searchInPackOnly && !$searchInComponentOnly)
  514. {
  515. $dirs = array_merge($dirs, array_values(self::$_lookupDirs[Cfg_App::PACK_LOOKUP_PATHS]));
  516. }
  517. else
  518. {
  519. $dirs = array_merge($dirs, array_values(self::$_lookupDirs[Cfg_App::COMPONENT_LOOKUP_PATHS]),
  520. array_values(self::$_lookupDirs[Cfg_App::PACK_LOOKUP_PATHS]),
  521. array_values(self::$_lookupDirs[Cfg_App::SYSTEM_LOOKUP_PATHS]));
  522. }
  523. foreach($dirs as $dir)
  524. {
  525. $classNameFile = self::getDirectPath(array($dir, $classFile), $options);
  526. if(is_file($classNameFile))
  527. {
  528. $toRequire = $classNameFile;
  529. break;
  530. }
  531. }
  532. return $toRequire;
  533. }
  534. public static function classFileRecursiveLookup($className, $options)
  535. {
  536. foreach(self::$_paths as $path) {
  537. if (true == ($toInclude = self::_fileRecursiveLookup($className, $path)))
  538. {
  539. return $toInclude;
  540. }
  541. }
  542. }
  543. private static function _fileRecursiveLookup($searchFilePath, $directory)
  544. {
  545. if (is_dir($directory) && is_readable($directory))
  546. {
  547. if (true == ($handle = opendir($directory))) {
  548. while (false !== ($entry = readdir($handle))) {
  549. if ($entry !== "." && $entry !== "..")
  550. {
  551. $subPath = $directory . Cfg_App::DS . $entry;
  552. if (is_dir($subPath))
  553. {
  554. $filePath = $subPath . Cfg_App::DS . $searchFilePath;
  555. if (is_readable($filePath))
  556. {
  557. return $filePath;
  558. }
  559. else
  560. {
  561. if(true == ($filePath = self::_fileRecursiveLookup($searchFilePath, $subPath)))
  562. {
  563. return $filePath;
  564. }
  565. }
  566. }
  567. }
  568. }
  569. closedir($handle);
  570. }
  571. }
  572. else
  573. {
  574. return false;
  575. }
  576. }
  577. public static function checkIncludeClassFile($className, $fileToInclude, $options)
  578. {
  579. $fromCache = false;
  580. $throws = false;
  581. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  582. if ($fileToInclude && is_readable($fileToInclude) && include_once($fileToInclude))
  583. {
  584. if (!class_exists($className, false)
  585. && !interface_exists($className, false)
  586. && (!function_exists('trait_exists') || !trait_exists($className, false)))
  587. {
  588. if ($throws)
  589. {
  590. throw new Exception(
  591. sprintf('The autoloader expected class "%s" to be
  592. defined in file "%s". The file was found but
  593. the class was not in it.', $className, $fileToInclude));
  594. }
  595. else
  596. {
  597. trigger_error(
  598. sprintf('The autoloader expected class "%s" to be
  599. defined in file "%s". The file was found but
  600. the class was not in it.', $className, $fileToInclude), E_USER_ERROR);
  601. }
  602. }
  603. else
  604. {
  605. if (!$fromCache)
  606. {
  607. self::cacheFilePath($className, $fileToInclude, self::_getCustomPathsKey($options));
  608. }
  609. }
  610. }
  611. else
  612. {
  613. if ($throws)
  614. {
  615. throw new Exception(
  616. sprintf('The autoloader could not find class "%s"', $className));
  617. }
  618. else
  619. {
  620. trigger_error(
  621. sprintf('The autoloader could not find class "%s"', $className), E_USER_ERROR);
  622. }
  623. }
  624. }
  625. public static function registerAutoloader()
  626. {
  627. if (Cfg_App::$AUTOLOADER_CACHE_ENABLED){
  628. self::setCache(Cache::getFileBasedCache());
  629. }
  630. return spl_autoload_register(array('Loader', 'loadClass'), true);
  631. }
  632. /**
  633. *
  634. * @param array $parts
  635. * @return string concatenated with directory separator path parts
  636. */
  637. public static function arrayToPath($parts)
  638. {
  639. return implode(Cfg_App::DS, $parts);
  640. }
  641. /**
  642. *
  643. * Replaces config placeholders in the string
  644. * available placeholders are:
  645. * '/' => ,
  646. * '{core}' => ,
  647. * '{classes}' => ,
  648. * '{dataclasses}' => ,
  649. * '{interfaces}' => ,
  650. * '{framework}' => ,
  651. * '{custom}' => ,
  652. * '{controllers}' => ,
  653. * '{components}' => ,
  654. * '{packs}' => ,
  655. * '{modules}' => ,
  656. * '{router_file}' => ,
  657. * '{cfg_dir}' => ,
  658. * '{cfg_pack_file}' => ,
  659. * '{cfg_app_file}' => ,
  660. * '{cfg_db_file}' => ,
  661. * '{class_ext}' => ,
  662. * '{media}' => ,
  663. * '{tpl}' => ,
  664. * '{tpl_ext}' => ,
  665. * '{pack_name}' => ,
  666. * '{component_name}' => ,
  667. * '{module_name}' => ,
  668. * '{class_dir_type}' => ,
  669. * '{owner}' =>
  670. *
  671. * @param string $str string to find placeholders in it
  672. * @param array $options provide options if you want to use specific behavior
  673. *
  674. * @return string string with replaced values
  675. */
  676. public static function replaceCfgPlaceholders($str, $options = array())
  677. {
  678. $packName = "";
  679. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  680. if ($packName || (!self::$_replacement))
  681. {
  682. $cfg = Cfg_App::getPackOptions($packName);
  683. $replacement = array(
  684. '/' => Cfg_App::DS,
  685. '{core}' => $cfg[Cfg_App::KEY_CORE_PATH],
  686. '{cache}' => $cfg[Cfg_App::KEY_CACHE],
  687. '{classes}' => $cfg[Cfg_App::KEY_CLASSES_PATH],
  688. '{dataclasses}' => $cfg[Cfg_App::KEY_DATA_CLASSES_PATH],
  689. '{interfaces}' => $cfg[Cfg_App::KEY_INTERFACES_PATH],
  690. '{framework}' => $cfg[Cfg_App::KEY_FRAMEWORK_CLASSES],
  691. '{user}' => $cfg[Cfg_App::KEY_USER_CLASSES],
  692. '{controllers}' => $cfg[Cfg_App::KEY_CONTROLLERS],
  693. '{components}' => $cfg[Cfg_App::KEY_COMPONENTS],
  694. '{packs}' => $cfg[Cfg_App::KEY_PACKS_PATH],
  695. '{modules}' => $cfg[Cfg_App::KEY_MODULES],
  696. '{router_file}' => $cfg[Cfg_App::KEY_ROUTER_FILE_NAME],
  697. '{cfg_dir}' => $cfg[Cfg_App::KEY_CONFIG],
  698. '{cfg_pack_file}' => $cfg[Cfg_App::KEY_CONFIG_PACK],
  699. '{cfg_app_file}' => $cfg[Cfg_App::KEY_CONFIG_APP],
  700. '{cfg_db_file}' => $cfg[Cfg_App::KEY_CONFIG_DB],
  701. '{class_ext}' => $cfg[Cfg_App::KEY_CLASS_FILE_EXT],
  702. '{media}' => $cfg[Cfg_App::KEY_MEDIA_PATH],
  703. '{tpl}' => $cfg[Cfg_App::KEY_TEMPLATES],
  704. '{tpl_ext}' => $cfg[Cfg_App::KEY_TEMPLATE_EXT]
  705. );
  706. if (!self::$_replacement && !$packName)
  707. {
  708. self::$_replacement = $replacement;
  709. }
  710. }
  711. elseif (self::$_replacement)
  712. {
  713. $replacement = self::$_replacement;
  714. }
  715. if (($packName && count($options) > 1) || $options)
  716. {
  717. $packName = "";
  718. $componentName = "";
  719. $moduleName = "";
  720. $classDirType = "";
  721. $owner = "";
  722. extract($options, EXTR_IF_EXISTS | EXTR_OVERWRITE);
  723. $additionalReplacements = array(
  724. '{pack_name}' => $packName,
  725. '{component_name}' => $componentName,
  726. '{module_name}' => $moduleName,
  727. '{class_dir_type}' => Cfg_App::getPackOption($classDirType, $packName),
  728. '{owner}' => $owner
  729. );
  730. $replacement = array_merge($replacement, $additionalReplacements);
  731. }
  732. return str_replace(array_keys($replacement), array_values($replacement), $str);
  733. }
  734. /**
  735. *
  736. * Sets directories for lookup purposes of autoloader
  737. * use SYSTEM_LOOKUP_PATHS, PACK_LOOKUP_PATHS, COMPONENT_LOOKUP_PATHS constants of Loader
  738. * as $dirs array keys
  739. * If $merge is set to 'true', new directories will be merged with previous,
  740. * they will be replaced otherwise
  741. *
  742. * @param array $dirs
  743. * @param bool $merge
  744. */
  745. public static function setLookupDirectories($dirs, $merge = true)
  746. {
  747. $keys = array_keys($dirs);
  748. foreach($keys as $dirKey)
  749. {
  750. if (in_array($dirKey, Cfg_App::getLookupDirKeys()))
  751. {
  752. if ($merge)
  753. {
  754. if (!isset(self::$_lookupDirs[$dirKey]))
  755. self::$_lookupDirs[$dirKey] = array();
  756. self::$_lookupDirs[$dirKey] =
  757. array_merge(self::$_lookupDirs[$dirKey],
  758. $dirs[$dirKey]);
  759. }
  760. else
  761. {
  762. self::$_lookupDirs[$dirKey] = $dirs[$dirKey];
  763. }
  764. }
  765. }
  766. }
  767. /**
  768. *
  769. * Calculates simple numeric identifier for string
  770. *
  771. * @param string $string
  772. * @return string
  773. */
  774. private static function _getStringIdentifier($string)
  775. {
  776. return sprintf("%u", crc32($string));
  777. }
  778. /**
  779. *
  780. * Returns string key of the value from the configuration array
  781. *
  782. * @param string $className
  783. * @return string string key from the configuration array
  784. */
  785. private static function _getClassDirType($className)
  786. {
  787. $dirType = Cfg_App::KEY_CLASSES_PATH;
  788. if (preg_match('/(table|interface|plugin|view)$/', strtolower($className), $matches))
  789. {
  790. switch($matches[0]){
  791. case "table" :
  792. $dirType = Cfg_App::KEY_DATA_CLASSES_PATH;
  793. break;
  794. case "interface" :
  795. $dirType = Cfg_App::KEY_INTERFACES_PATH;
  796. break;
  797. case "plugin":
  798. $dirType = Cfg_App::KEY_PLUGINS_PATH;
  799. break;
  800. // case "view":
  801. // $dirType = Cfg_App::KEY_VIEWS_PATH;
  802. }
  803. }
  804. return $dirType;
  805. }
  806. /**
  807. *
  808. * @param string $className
  809. * @param string $packName
  810. * @return string
  811. */
  812. private static function _getFilePathPartByClassName($className, $packName = "")
  813. {
  814. $className = strtolower($className);
  815. $classFileExt = Cfg_App::_(Cfg_App::KEY_CLASS_FILE_EXT);
  816. if ($packName)
  817. {
  818. $classFileExt = Cfg_App::getPackOption(Cfg_App::KEY_CLASS_FILE_EXT, $packName);
  819. }
  820. return (!strpos($className, '_') ?
  821. $className . Cfg_App::DS . $className :
  822. str_replace('_', Cfg_App::DS, $className)) . '.' . $classFileExt;
  823. }
  824. /**
  825. *
  826. * @param array $array1
  827. * @param array $array2
  828. * @return array
  829. */
  830. private static function _arrayMergeRecursiveDistinct(array $array1, array $array2)
  831. {
  832. $merged = $array1;
  833. foreach ($array2 as $key => $value)
  834. {
  835. if (is_array($value) && isset($merged[$key]) && is_array($merged[$key]))
  836. {
  837. $merged[$key] = self::_arrayMergeRecursiveDistinct($merged[$key], $value);
  838. }
  839. else
  840. {
  841. $merged[$key] = $value;
  842. }
  843. }
  844. return $merged;
  845. }
  846. }