Merge pull request #15982 from civicrm/5.20
[civicrm-core.git] / CRM / Extension / ClassLoader.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 *
15 * @package CRM
16 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 * $Id$
18 *
19 */
20 class CRM_Extension_ClassLoader {
21
22 /**
23 * @var CRM_Extension_Mapper
24 */
25 protected $mapper;
26
27 /**
28 * @var CRM_Extension_Container_Interface
29 */
30 protected $container;
31
32 /**
33 * @var CRM_Extension_Manager
34 */
35 protected $manager;
36
37 /**
38 * @var \Composer\Autoload\ClassLoader
39 */
40 protected $loader;
41
42 /**
43 * CRM_Extension_ClassLoader constructor.
44 * @param \CRM_Extension_Mapper $mapper
45 * @param \CRM_Extension_Container_Interface $container
46 * @param \CRM_Extension_Manager $manager
47 */
48 public function __construct(\CRM_Extension_Mapper $mapper, \CRM_Extension_Container_Interface $container, \CRM_Extension_Manager $manager) {
49 $this->mapper = $mapper;
50 $this->container = $container;
51 $this->manager = $manager;
52 }
53
54 public function __destruct() {
55 $this->unregister();
56 }
57
58 /**
59 * Registers this instance as an autoloader.
60 * @return CRM_Extension_ClassLoader
61 */
62 public function register() {
63 // In pre-installation environments, don't bother with caching.
64 if (!defined('CIVICRM_DSN') || defined('CIVICRM_TEST') || \CRM_Utils_System::isInUpgradeMode()) {
65 return $this->buildClassLoader()->register();
66 }
67
68 $file = $this->getCacheFile();
69 if (file_exists($file)) {
70 $loader = require $file;
71 }
72 else {
73 $loader = $this->buildClassLoader();
74 $ser = serialize($loader);
75 file_put_contents($file,
76 sprintf("<?php\nreturn unserialize(%s);", var_export($ser, 1))
77 );
78 }
79 return $loader->register();
80 }
81
82 /**
83 * @return \Composer\Autoload\ClassLoader
84 * @throws \CRM_Extension_Exception
85 * @throws \Exception
86 */
87 public function buildClassLoader() {
88 $loader = new \Composer\Autoload\ClassLoader();
89
90 $statuses = $this->manager->getStatuses();
91 foreach ($statuses as $key => $status) {
92 if ($status !== CRM_Extension_Manager::STATUS_INSTALLED) {
93 continue;
94 }
95 $path = $this->mapper->keyToBasePath($key);
96 $info = $this->mapper->keyToInfo($key);
97 if (!empty($info->classloader)) {
98 foreach ($info->classloader as $mapping) {
99 switch ($mapping['type']) {
100 case 'psr4':
101 $loader->addPsr4($mapping['prefix'], $path . '/' . $mapping['path']);
102 break;
103 }
104 $result[] = $mapping;
105 }
106 }
107 }
108
109 return $loader;
110 }
111
112 public function unregister() {
113 if ($this->loader) {
114 $this->loader->unregister();
115 $this->loader = NULL;
116 }
117 }
118
119 public function refresh() {
120 $this->unregister();
121 $file = $this->getCacheFile();
122 if (file_exists($file)) {
123 unlink($file);
124 }
125 $this->register();
126 }
127
128 /**
129 * @return string
130 */
131 protected function getCacheFile() {
132 $envId = \CRM_Core_Config_Runtime::getId();
133 $file = \Civi::paths()->getPath("[civicrm.compile]/CachedExtLoader.{$envId}.php");
134 return $file;
135 }
136
137 }