Merge pull request #22576 from seamuslee001/update_jquery_ui
[civicrm-core.git] / CRM / Core / ClassLoader.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
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 |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 *
15 * @package CRM
ca5cec67 16 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
17 */
18class CRM_Core_ClassLoader {
19
20 /**
21 * We only need one instance of this object. So we use the singleton
22 * pattern and cache the instance in this variable
23 * @var object
6a488035
TO
24 */
25 private static $_singleton = NULL;
26
649d6dd0
TO
27 /**
28 * The classes in CiviTest have ucky, non-standard naming.
29 *
30 * @var array
31 * Array(string $className => string $filePath).
32 */
33 private $civiTestClasses;
34
a0ee3941
EM
35 /**
36 * @param bool $force
37 *
38 * @return object
39 */
00be9182 40 public static function &singleton($force = FALSE) {
6a488035
TO
41 if ($force || self::$_singleton === NULL) {
42 self::$_singleton = new CRM_Core_ClassLoader();
43 }
44 return self::$_singleton;
45 }
46
47 /**
e97c66ff 48 * Has this been registered already.
49 *
50 * @var bool
6a488035
TO
51 */
52 protected $_registered;
53
a0ee3941 54 /**
e97c66ff 55 * Class constructor.
a0ee3941 56 */
6a488035
TO
57 protected function __construct() {
58 $this->_registered = FALSE;
be2fb01f 59 $this->civiTestClasses = [
649d6dd0
TO
60 'CiviCaseTestCase',
61 'CiviDBAssert',
62 'CiviMailUtils',
63 'CiviReportTestCase',
64 'CiviSeleniumTestCase',
649d6dd0
TO
65 'CiviTestSuite',
66 'CiviUnitTestCase',
9e80c052 67 'CiviEndToEndTestCase',
649d6dd0
TO
68 'Contact',
69 'ContributionPage',
70 'Custom',
71 'Event',
72 'Membership',
73 'Participant',
74 'PaypalPro',
be2fb01f 75 ];
6a488035
TO
76 }
77
45b293a2
DS
78 /**
79 * Requires the autoload.php generated by composer
80 *
81 * @return void
82 */
83 protected function requireComposerAutoload() {
d1f60655
DS
84 // We are trying to locate 'vendor/autoload.php'. When installing CiviCRM
85 // manually from the built tarball, that will be two directories up in the
86 // civicrm-core directory. However, if civicrm-core was installed via
87 // composer as a library, that'll be 5 directories up where composer was
88 // run (ex. the Drupal root on a Drupal 8 site).
9f1588f9
DS
89 $civicrm_base_path = dirname(dirname(__DIR__));
90 $top_path = dirname(dirname(dirname(dirname(dirname(__DIR__)))));
45b293a2
DS
91
92 if (file_exists($civicrm_base_path . '/vendor/autoload.php')) {
93 require_once $civicrm_base_path . '/vendor/autoload.php';
94 }
95 elseif (file_exists($top_path . '/vendor/autoload.php')) {
96 require_once $top_path . '/vendor/autoload.php';
97 }
98 }
99
6a488035
TO
100 /**
101 * Registers this instance as an autoloader.
102 *
6a0b768e
TO
103 * @param bool $prepend
104 * Whether to prepend the autoloader or not.
6a488035
TO
105 *
106 * @api
107 */
00be9182 108 public function register($prepend = FALSE) {
6a488035
TO
109 if ($this->_registered) {
110 return;
111 }
fa184193
TO
112 $civicrm_base_path = dirname(dirname(__DIR__));
113
45b293a2 114 $this->requireComposerAutoload();
6a488035
TO
115
116 // we do this to prevent a autoloader errors with joomla / 3rd party packages
117 // use absolute path since we dont know the content of include_path as yet
118 // CRM-11304
fa184193
TO
119 // TODO Remove this autoloader. For civicrm-core and civicrm-packages, the composer autoloader works fine.
120 // Extensions rely on include_path-based autoloading
be2fb01f 121 spl_autoload_register([$this, 'loadClass'], TRUE, $prepend);
6a488035
TO
122
123 $this->_registered = TRUE;
3b8898e8
TO
124 // The ClassLoader runs before the classes are available. Approximate Civi::paths()->get('[civicrm.packages]').
125 if (isset($GLOBALS['civicrm_paths']['civicrm.packages']['path'])) {
126 $packages_path = rtrim($GLOBALS['civicrm_paths']['civicrm.packages']['path'], DIRECTORY_SEPARATOR);
127 }
128 else {
129 $packages_path = implode(DIRECTORY_SEPARATOR, [$civicrm_base_path, 'packages']);
130 }
be2fb01f 131 $include_paths = [
fa184193
TO
132 '.',
133 $civicrm_base_path,
21dfd5f5 134 $packages_path,
be2fb01f 135 ];
fa184193
TO
136 $include_paths = implode(PATH_SEPARATOR, $include_paths);
137 set_include_path($include_paths . PATH_SEPARATOR . get_include_path());
7991d8ed 138 // @todo Why do we need to load this again?
45b293a2 139 $this->requireComposerAutoload();
6a488035
TO
140 }
141
a0ee3941
EM
142 /**
143 * @param $class
144 */
00be9182 145 public function loadClass($class) {
fcb47cfd 146 if ($class === 'CiviCRM_API3_Exception' || $class === 'API_Exception') {
eb1afb93
ON
147 //call internal error class api/Exception first
148 // allow api/Exception class call external error class
149 // CiviCRM_API3_Exception
150 require_once 'api/Exception.php';
151 }
6a488035
TO
152 if (
153 // Only load classes that clearly belong to CiviCRM.
8581f9ae 154 // Note: api/v3 does not use classes, but api_v3's test-suite does
dbaa9d7d 155 (0 === strncmp($class, 'CRM_', 4) || 0 === strncmp($class, 'CRMTraits', 9) || 0 === strncmp($class, 'api_v3_', 7) || 0 === strncmp($class, 'WebTest_', 8) || 0 === strncmp($class, 'E2E_', 4)) &&
6a488035
TO
156 // Do not load PHP 5.3 namespaced classes.
157 // (in a future version, maybe)
158 FALSE === strpos($class, '\\')
159 ) {
160 $file = strtr($class, '_', '/') . '.php';
161 // There is some question about the best way to do this.
162 // "require_once" is nice because it's simple and throws
a03a3680
TO
163 // intelligible errors.
164 if (FALSE != stream_resolve_include_path($file)) {
165 require_once $file;
166 }
6a488035 167 }
649d6dd0
TO
168 elseif (in_array($class, $this->civiTestClasses)) {
169 $file = "tests/phpunit/CiviTest/{$class}.php";
170 if (FALSE != stream_resolve_include_path($file)) {
171 require_once $file;
172 }
173 }
174 elseif ($class === 'CiviSeleniumSettings') {
175 if (!empty($GLOBALS['_CV'])) {
176 require_once 'tests/phpunit/CiviTest/CiviSeleniumSettings.auto.php';
177 }
178 elseif (CRM_Utils_File::isIncludable('tests/phpunit/CiviTest/CiviSeleniumSettings.php')) {
179 require_once 'tests/phpunit/CiviTest/CiviSeleniumSettings.php';
180 }
181 }
6a488035 182 }
a03a3680 183
6a488035 184}