CRM-17957 - Allow extensions to register with PHP classloader (PSR-4)
[civicrm-core.git] / CRM / Extension / ClassLoader.php
CommitLineData
4025c773
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28/**
29 *
30 *
31 * @package CRM
32 * @copyright CiviCRM LLC (c) 2004-2015
33 * $Id$
34 *
35 */
36class CRM_Extension_ClassLoader {
37
38 /**
39 * @var CRM_Extension_Mapper
40 */
41 protected $mapper;
42
43 /**
44 * @var CRM_Extension_Container_Interface
45 */
46 protected $container;
47
48 /**
49 * @var CRM_Extension_Manager
50 */
51 protected $manager;
52
53 /**
54 * @var \Composer\Autoload\ClassLoader
55 */
56 protected $loader;
57
58 /**
59 * CRM_Extension_ClassLoader constructor.
60 * @param \CRM_Extension_Mapper $mapper
61 * @param \CRM_Extension_Container_Interface $container
62 * @param \CRM_Extension_Manager $manager
63 */
64 public function __construct(\CRM_Extension_Mapper $mapper, \CRM_Extension_Container_Interface $container, \CRM_Extension_Manager $manager) {
65 $this->mapper = $mapper;
66 $this->container = $container;
67 $this->manager = $manager;
68 }
69
70 public function __destruct() {
71 if ($this->loader) {
72 $this->loader->unregister();
73 $this->loader = NULL;
74 }
75 }
76
77 /**
78 * Registers this instance as an autoloader.
79 * @return $this
80 */
81 public function register() {
82 // In pre-installation environments, don't bother with caching.
83 if (!defined('CIVICRM_TEMPLATE_COMPILEDIR') || !defined('CIVICRM_DSN') || \CRM_Utils_System::isInUpgradeMode()) {
84 return $this->buildClassLoader()->register();
85 }
86
87 $envId = \CRM_Core_Config_Runtime::getId();
88 $file = CIVICRM_TEMPLATE_COMPILEDIR . "/CachedExtLoader.{$envId}.php";
89 if (file_exists($file)) {
90 $loader = require $file;
91 }
92 else {
93 $loader = $this->buildClassLoader();
94 $ser = serialize($loader);
95 file_put_contents($file,
96 sprintf("<?php\nreturn unserialize(%s);", var_export($ser, 1))
97 );
98 }
99 return $loader->register();
100 }
101
102 /**
103 * @return \Composer\Autoload\ClassLoader
104 * @throws \CRM_Extension_Exception
105 * @throws \Exception
106 */
107 public function buildClassLoader() {
108 $loader = new \Composer\Autoload\ClassLoader();
109
110 $statuses = $this->manager->getStatuses();
111 foreach ($statuses as $key => $status) {
112 if ($status !== CRM_Extension_Manager::STATUS_INSTALLED) {
113 continue;
114 }
115 $path = $this->mapper->keyToBasePath($key);
116 $info = $this->mapper->keyToInfo($key);
117 if (!empty($info->classloader)) {
118 foreach ($info->classloader as $mapping) {
119 switch ($mapping['type']) {
120 case 'psr4':
121 $loader->setPsr4($mapping['prefix'], $path . '/' . $mapping['path']);
122 break;
123 }
124 $result[] = $mapping;
125 }
126 }
127 }
128
129 return $loader;
130 }
131
132}