3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
13 * Class CRM_Extension_ClassLoader
15 class CRM_Extension_ClassLoader
{
18 * List of class-loader features that are valid in this version of Civi.
20 * This may be useful for some extensions which enable/disable polyfills based on environment.
22 const FEATURES
= ',psr0,psr4,';
25 * @var CRM_Extension_Mapper
30 * @var CRM_Extension_Container_Interface
35 * @var CRM_Extension_Manager
40 * @var \Composer\Autoload\ClassLoader
45 * CRM_Extension_ClassLoader constructor.
46 * @param \CRM_Extension_Mapper $mapper
47 * @param \CRM_Extension_Container_Interface $container
48 * @param \CRM_Extension_Manager $manager
50 public function __construct(\CRM_Extension_Mapper
$mapper, \CRM_Extension_Container_Interface
$container, \CRM_Extension_Manager
$manager) {
51 $this->mapper
= $mapper;
52 $this->container
= $container;
53 $this->manager
= $manager;
56 public function __destruct() {
61 * Registers this instance as an autoloader.
62 * @return CRM_Extension_ClassLoader
64 public function register() {
65 // In pre-installation environments, don't bother with caching.
66 if (!defined('CIVICRM_DSN') ||
defined('CIVICRM_TEST') || \CRM_Utils_System
::isInUpgradeMode()) {
67 $this->loader
= $this->buildClassLoader();
68 return $this->loader
->register();
71 $file = $this->getCacheFile();
72 if (file_exists($file)) {
73 $this->loader
= require $file;
76 $this->loader
= $this->buildClassLoader();
77 $ser = serialize($this->loader
);
78 file_put_contents($file,
79 sprintf("<?php\nreturn unserialize(%s);", var_export($ser, 1))
82 return $this->loader
->register();
86 * @return \Composer\Autoload\ClassLoader
87 * @throws \CRM_Extension_Exception
90 public function buildClassLoader() {
91 $loader = new \Composer\Autoload\
ClassLoader();
93 $statuses = $this->manager
->getStatuses();
94 foreach ($statuses as $key => $status) {
95 if ($status !== CRM_Extension_Manager
::STATUS_INSTALLED
) {
98 self
::loadExtension($loader, $this->mapper
->keyToInfo($key), $this->mapper
->keyToBasePath($key));
104 public function unregister() {
106 $this->loader
->unregister();
107 $this->loader
= NULL;
111 public function refresh() {
113 $file = $this->getCacheFile();
114 if (file_exists($file)) {
121 * Add a newly installed extension to the active classloader.
123 * NOTE: This is intended for use by CRM/Extension subsystem during installation.
125 * @param \CRM_Extension_Info $info
126 * @param string $path
128 public function installExtension(CRM_Extension_Info
$info, string $path): void
{
129 $file = $this->getCacheFile();
130 if (file_exists($file)) {
134 self
::loadExtension($this->loader
, $info, $path);
139 * Read the extension metadata configure a classloader.
141 * @param \Composer\Autoload\ClassLoader $loader
142 * @param \CRM_Extension_Info $info
143 * @param string $path
145 private static function loadExtension(\Composer\Autoload\ClassLoader
$loader, CRM_Extension_Info
$info, string $path): void
{
146 if (!empty($info->classloader
)) {
147 foreach ($info->classloader
as $mapping) {
148 switch ($mapping['type']) {
150 $loader->add($mapping['prefix'], CRM_Utils_File
::addTrailingSlash($path . '/' . $mapping['path']));
154 $loader->addPsr4($mapping['prefix'], $path . '/' . $mapping['path']);
164 protected function getCacheFile() {
165 $envId = \CRM_Core_Config_Runtime
::getId();
166 $file = \Civi
::paths()->getPath("[civicrm.compile]/CachedExtLoader.{$envId}.php");