PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/concrete/src/Foundation/ClassLoader.php

https://gitlab.com/koodersmiikka/operaatio-terveys
PHP | 239 lines | 169 code | 16 blank | 54 comment | 6 complexity | 72880b4c6518c1cd5bdb750b7db9ba9a MD5 | raw file
  1. <?php
  2. namespace Concrete\Core\Foundation;
  3. use \Concrete\Core\Foundation\Object;
  4. use \Concrete\Core\Package\Package;
  5. use \Concrete\Core\Foundation\ModifiedPSR4ClassLoader;
  6. use \Symfony\Component\ClassLoader\MapClassLoader as SymfonyMapClassloader;
  7. use Symfony\Component\ClassLoader\Psr4ClassLoader as SymfonyClassLoader;
  8. /**
  9. * Provides autoloading for concrete5
  10. * Typically getInstance() should be used rather than instantiating a new object.
  11. * @package Concrete\Core\Foundation
  12. */
  13. class ClassLoader
  14. {
  15. /** @var ClassLoader */
  16. static $instance;
  17. protected $classAliases = array();
  18. /**
  19. * Returns the ClassLoader instance
  20. * @return ClassLoader
  21. */
  22. public static function getInstance()
  23. {
  24. if (!isset(static::$instance)) {
  25. static::$instance = new Classloader();
  26. }
  27. return static::$instance;
  28. }
  29. public function __construct()
  30. {
  31. $this->setupFileAutoloader();
  32. $this->setupAliasAutoloader();
  33. $this->setupMapClassAutoloader();
  34. }
  35. /**
  36. * Maps legacy classes
  37. */
  38. protected function setupMapClassAutoloader()
  39. {
  40. $mapping = array(
  41. 'Loader' => DIR_BASE_CORE . '/' . DIRNAME_CLASSES . '/Legacy/Loader.php',
  42. 'TaskPermission' => DIR_BASE_CORE . '/' . DIRNAME_CLASSES . '/Legacy/TaskPermission.php',
  43. 'FilePermissions' => DIR_BASE_CORE . '/' . DIRNAME_CLASSES . '/Legacy/FilePermissions.php'
  44. );
  45. $loader = new SymfonyMapClassloader($mapping);
  46. $loader->register();
  47. }
  48. /**
  49. * Aliases concrete5 classes to shorter class name aliases
  50. *
  51. * IDEs will not recognize these classes by default. A symbols file can be generated to
  52. * assist IDEs by running SymbolGenerator::render() via PHP or executing the command-line
  53. * 'concrete/bin/concrete5 c5:ide-symbols
  54. */
  55. protected function setupAliasAutoloader()
  56. {
  57. $loader = $this;
  58. spl_autoload_register(function ($class) use ($loader) {
  59. $list = ClassAliasList::getInstance();
  60. if (array_key_exists($class, $aliases = $list->getRegisteredAliases())) {
  61. // we have an alias for it, but we don't have it yet loaded
  62. // (because after all, we're in the auto loader.)
  63. $fullClass = $aliases[$class];
  64. if (!class_exists($fullClass, false)) {
  65. spl_autoload_call($fullClass);
  66. }
  67. // finally, we set up a class alias for this list. We do this now because
  68. // we don't know earlier what namespace it'll be in
  69. class_alias($fullClass, $class);
  70. }
  71. });
  72. }
  73. /**
  74. * Registers the prefixes for a package
  75. *
  76. * The following prefixes are registered:
  77. * <ul>
  78. * <li>`Concrete\Package\PkgHandle\Attribute` -> `packages/pkg_handle/attributes`</li>
  79. * <li>`Concrete\Package\PkgHandle\MenuItem` -> `packages/pkg_handle/menu_items`</li>
  80. * <li>`Concrete\Package\PkgHandle\Authentication` -> `packages/pkg_handle/authentication`</li>
  81. * <li>`Concrete\Package\PkgHandle\Block` -> `packages/pkg_handle/blocks`</li>
  82. * <li>`Concrete\Package\PkgHandle\Theme` -> `packages/pkg_handle/themes`</li>
  83. * <li>`Concrete\Package\PkgHandle\Controller\PageType` -> `packages/pkg_handle/controllers/page_type`</li>
  84. * <li>`Concrete\Package\PkgHandle\Controller` -> `packages/pkg_handle/controllers`</li>
  85. * <li>`Concrete\Package\PkgHandle\Job` -> `packages/pkg_handle/jobs`</li>
  86. * </ul>
  87. *
  88. * If Package::$pkgAutoloaderMapCoreExtensions is true, all remaining class paths will be checked for
  89. * under packages/pkg_handle/src/Concrete
  90. *
  91. * Otherwise, `Concrete\Package\PkgHandle\Src` -> `packages/pkg_handle/src` will be registered
  92. *
  93. * The function Package::getPackageAutoloaderRegistries() can be used to add custom prefixes
  94. *
  95. * @param string|\Package $pkg Package handle or an instance of the package controller
  96. * @see Package::$pkgAutoloaderMapCoreExtensions, Package::getPackageAutoloaderRegistries()
  97. */
  98. public function registerPackage($pkg)
  99. {
  100. if (!($pkg instanceof Package)) {
  101. $pkg = \Package::getClass($pkg);
  102. }
  103. $pkgHandle = $pkg->getPackageHandle();
  104. $symfonyLoader = new ModifiedPSR4ClassLoader();
  105. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\Attribute', DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_ATTRIBUTES);
  106. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\MenuItem', DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_MENU_ITEMS);
  107. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\Authentication', DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_AUTHENTICATION);
  108. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\Block', DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_BLOCKS);
  109. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\Theme', DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_THEMES);
  110. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\Controller\\PageType', DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_CONTROLLERS . '/' . DIRNAME_PAGE_TYPES);
  111. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\Controller', DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_CONTROLLERS);
  112. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\Job', DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_JOBS);
  113. $strictLoader = new SymfonyClassLoader();
  114. $loaders = $pkg->getPackageAutoloaderRegistries();
  115. if (count($loaders) > 0) {
  116. foreach ($loaders as $path => $prefix) {
  117. $strictLoader->addPrefix($prefix, DIR_PACKAGES . '/' . $pkgHandle . '/' . $path);
  118. }
  119. }
  120. if ($pkg->providesCoreExtensionAutoloaderMapping()) {
  121. // We map all src files in the package to the src/Concrete directory
  122. $strictLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle), DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_CLASSES . '/Concrete');
  123. } else {
  124. // legacy Src support
  125. $strictLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\Src', DIR_PACKAGES . '/' . $pkgHandle . '/' . DIRNAME_CLASSES);
  126. }
  127. $symfonyLoader->register();
  128. $strictLoader->register();
  129. $this->registerPackageController($pkgHandle);
  130. }
  131. /**
  132. * Maps a package controller's class name to the file
  133. * @param string $pkgHandle Handle of package
  134. */
  135. public function registerPackageController($pkgHandle)
  136. {
  137. $symfonyLoader = new SymfonyMapClassloader(array(
  138. NAMESPACE_SEGMENT_VENDOR . '\\Package\\' . camelcase($pkgHandle) . '\\Controller' =>
  139. DIR_PACKAGES . '/' . $pkgHandle . '/' . FILENAME_PACKAGE_CONTROLLER
  140. ));
  141. $symfonyLoader->register();
  142. }
  143. /**
  144. * Adds concrete5's core autoloading prefixes
  145. *
  146. * * The following prefixes are registered:
  147. * <ul>
  148. * <li>`Concrete\StartingPointPackage` -> `concrete/config/install/packages`</li>
  149. * <li>`Concrete\Attribute` -> `concrete/attributes`</li>
  150. * <li>`Concrete\Authentication` -> `concrete/authentication`</li>
  151. * <li>`Concrete\Block` -> `concrete/blocks`</li>
  152. * <li>`Concrete\Theme` -> `concrete/themes`</li>
  153. * <li>`Concrete\Controller\PageType` -> `concrete/controllers/page_types`</li>
  154. * <li>`Concrete\Controller` -> `concrete/controllers`</li>
  155. * <li>`Concrete\Job` -> `concrete/jobs`</li>
  156. * <li>`Concrete\Core` -> `concrete/src`</li>
  157. * <li>`Application\StartingPointPackage` -> `application/config/install/packages`</li>
  158. * <li>`Application\Attribute` -> `application/attributes`</li>
  159. * <li>`Application\Authentication` -> `application/authentication`</li>
  160. * <li>`Application\Block` -> `application/blocks`</li>
  161. * <li>`Application\Theme` -> `application/themes`</li>
  162. * <li>`Application\Controller\PageType` -> `application/controllers/page_types`</li>
  163. * <li>`Application\Controller` -> `application/controllers`</li>
  164. * <li>`Application\Job` -> `application/jobs`</li>
  165. * <li>`Application\Core` -> `application/src`</li>
  166. * </ul>
  167. *
  168. * The application namespace can be customized by setting `namespace` in the application's `config/app.php`.
  169. */
  170. protected function setupFileAutoloader()
  171. {
  172. $symfonyLoader = new ModifiedPSR4ClassLoader();
  173. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\StartingPointPackage', DIR_BASE_CORE . '/config/install/' . DIRNAME_PACKAGES);
  174. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Attribute', DIR_BASE_CORE . '/' . DIRNAME_ATTRIBUTES);
  175. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\MenuItem', DIR_BASE_CORE . '/' . DIRNAME_MENU_ITEMS);
  176. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Authentication', DIR_BASE_CORE . '/' . DIRNAME_AUTHENTICATION);
  177. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Block', DIR_BASE_CORE . '/' . DIRNAME_BLOCKS);
  178. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Theme', DIR_BASE_CORE . '/' . DIRNAME_THEMES);
  179. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Controller\\PageType', DIR_BASE_CORE . '/' . DIRNAME_CONTROLLERS . '/' . DIRNAME_PAGE_TYPES);
  180. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Controller', DIR_BASE_CORE . '/' . DIRNAME_CONTROLLERS);
  181. $symfonyLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Job', DIR_BASE_CORE . '/' . DIRNAME_JOBS);
  182. $namespace = 'Application';
  183. $app_config_path = DIR_APPLICATION . '/config/app.php';
  184. $provideCoreExtensionAutoloaderMapping = false;
  185. if (file_exists($app_config_path)) {
  186. $app_config = require $app_config_path;
  187. if (isset($app_config['namespace'])) {
  188. $namespace = $app_config['namespace'];
  189. }
  190. if (isset($app_config['provide_core_extension_autoloader_mapping'])) {
  191. $provideCoreExtensionAutoloaderMapping = true;
  192. }
  193. }
  194. $symfonyLoader->addPrefix($namespace . '\\StartingPointPackage', DIR_APPLICATION . '/config/install/' . DIRNAME_PACKAGES);
  195. $symfonyLoader->addPrefix($namespace . '\\Attribute', DIR_APPLICATION . '/' . DIRNAME_ATTRIBUTES);
  196. $symfonyLoader->addPrefix($namespace . '\\MenuItem', DIR_APPLICATION . '/' . DIRNAME_MENU_ITEMS);
  197. $symfonyLoader->addPrefix($namespace . '\\Authentication', DIR_APPLICATION . '/' . DIRNAME_AUTHENTICATION);
  198. $symfonyLoader->addPrefix($namespace . '\\Block', DIR_APPLICATION . '/' . DIRNAME_BLOCKS);
  199. $symfonyLoader->addPrefix($namespace . '\\Theme', DIR_APPLICATION . '/' . DIRNAME_THEMES);
  200. $symfonyLoader->addPrefix($namespace . '\\Controller\\PageType', DIR_APPLICATION . '/' . DIRNAME_CONTROLLERS . '/' . DIRNAME_PAGE_TYPES);
  201. $symfonyLoader->addPrefix($namespace . '\\Controller', DIR_APPLICATION . '/' . DIRNAME_CONTROLLERS);
  202. $symfonyLoader->addPrefix($namespace . '\\Job', DIR_APPLICATION . '/' . DIRNAME_JOBS);
  203. $symfonyLoader->register();
  204. $strictLoader = new SymfonyClassLoader();
  205. $strictLoader->addPrefix(NAMESPACE_SEGMENT_VENDOR . '\\Core', DIR_BASE_CORE . '/' . DIRNAME_CLASSES);
  206. if ($provideCoreExtensionAutoloaderMapping) {
  207. $strictLoader->addPrefix($namespace, DIR_APPLICATION . '/' . DIRNAME_CLASSES . '/Concrete');
  208. } else {
  209. $strictLoader->addPrefix($namespace . '\\Src', DIR_APPLICATION . '/' . DIRNAME_CLASSES);
  210. }
  211. $strictLoader->register();
  212. }
  213. }