Resolve docblock inaccuracy in CRM_Contribute_Form_Task_TaskTrait
[civicrm-core.git] / CRM / Extension / ClassLoader.php
index 2e181a887784b13be254a32e4e665329bbb62da6..a46580651d24d8424956350c68b1868af65f4c86 100644 (file)
  */
 class CRM_Extension_ClassLoader {
 
+  /**
+   * List of class-loader features that are valid in this version of Civi.
+   *
+   * This may be useful for some extensions which enable/disable polyfills based on environment.
+   */
+  const FEATURES = ',psr0,psr4,';
+
   /**
    * @var CRM_Extension_Mapper
    */
@@ -57,21 +64,22 @@ class CRM_Extension_ClassLoader {
   public function register() {
     // In pre-installation environments, don't bother with caching.
     if (!defined('CIVICRM_DSN') || defined('CIVICRM_TEST') || \CRM_Utils_System::isInUpgradeMode()) {
-      return $this->buildClassLoader()->register();
+      $this->loader = $this->buildClassLoader();
+      return $this->loader->register();
     }
 
     $file = $this->getCacheFile();
     if (file_exists($file)) {
-      $loader = require $file;
+      $this->loader = require $file;
     }
     else {
-      $loader = $this->buildClassLoader();
-      $ser = serialize($loader);
+      $this->loader = $this->buildClassLoader();
+      $ser = serialize($this->loader);
       file_put_contents($file,
         sprintf("<?php\nreturn unserialize(%s);", var_export($ser, 1))
       );
     }
-    return $loader->register();
+    return $this->loader->register();
   }
 
   /**
@@ -87,18 +95,7 @@ class CRM_Extension_ClassLoader {
       if ($status !== CRM_Extension_Manager::STATUS_INSTALLED) {
         continue;
       }
-      $path = $this->mapper->keyToBasePath($key);
-      $info = $this->mapper->keyToInfo($key);
-      if (!empty($info->classloader)) {
-        foreach ($info->classloader as $mapping) {
-          switch ($mapping['type']) {
-            case 'psr4':
-              $loader->addPsr4($mapping['prefix'], $path . '/' . $mapping['path']);
-              break;
-          }
-          $result[] = $mapping;
-        }
-      }
+      self::loadExtension($loader, $this->mapper->keyToInfo($key), $this->mapper->keyToBasePath($key));
     }
 
     return $loader;
@@ -120,6 +117,47 @@ class CRM_Extension_ClassLoader {
     $this->register();
   }
 
+  /**
+   * Add a newly installed extension to the active classloader.
+   *
+   * NOTE: This is intended for use by CRM/Extension subsystem during installation.
+   *
+   * @param \CRM_Extension_Info $info
+   * @param string $path
+   */
+  public function installExtension(CRM_Extension_Info $info, string $path): void {
+    $file = $this->getCacheFile();
+    if (file_exists($file)) {
+      unlink($file);
+    }
+    if ($this->loader) {
+      self::loadExtension($this->loader, $info, $path);
+    }
+  }
+
+  /**
+   * Read the extension metadata configure a classloader.
+   *
+   * @param \Composer\Autoload\ClassLoader $loader
+   * @param \CRM_Extension_Info $info
+   * @param string $path
+   */
+  private static function loadExtension(\Composer\Autoload\ClassLoader $loader, CRM_Extension_Info $info, string $path): void {
+    if (!empty($info->classloader)) {
+      foreach ($info->classloader as $mapping) {
+        switch ($mapping['type']) {
+          case 'psr0':
+            $loader->add($mapping['prefix'], CRM_Utils_File::addTrailingSlash($path . '/' . $mapping['path']));
+            break;
+
+          case 'psr4':
+            $loader->addPsr4($mapping['prefix'], $path . '/' . $mapping['path']);
+            break;
+        }
+      }
+    }
+  }
+
   /**
    * @return string
    */