Commit | Line | Data |
---|---|---|
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 | * Component stores all the static and dynamic information of the various | |
14 | * CiviCRM components | |
15 | * | |
16 | * @package CRM | |
ca5cec67 | 17 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
18 | */ |
19 | class CRM_Core_Component { | |
20 | ||
c490a46a CW |
21 | /** |
22 | * End part (filename) of the component information class'es name | |
23 | * that needs to be present in components main directory. | |
24 | */ | |
7da04cde | 25 | const COMPONENT_INFO_CLASS = 'Info'; |
6a488035 | 26 | |
a0ee3941 EM |
27 | /** |
28 | * @param bool $force | |
29 | * | |
9a13600c | 30 | * @return CRM_Core_Component_Info[] |
a0ee3941 | 31 | */ |
6a488035 | 32 | private static function &_info($force = FALSE) { |
edbcbd96 | 33 | if (!isset(Civi::$statics[__CLASS__]['info'])|| $force) { |
be2fb01f | 34 | Civi::$statics[__CLASS__]['info'] = []; |
6a488035 TO |
35 | |
36 | $config = CRM_Core_Config::singleton(); | |
37 | $c = self::getComponents(); | |
38 | ||
39 | foreach ($c as $name => $comp) { | |
40 | if (in_array($name, $config->enableComponents)) { | |
edbcbd96 | 41 | Civi::$statics[__CLASS__]['info'][$name] = $comp; |
6a488035 TO |
42 | } |
43 | } | |
44 | } | |
45 | ||
edbcbd96 | 46 | return Civi::$statics[__CLASS__]['info']; |
6a488035 TO |
47 | } |
48 | ||
a0ee3941 | 49 | /** |
100fef9d | 50 | * @param string $name |
a0ee3941 EM |
51 | * @param null $attribute |
52 | * | |
53 | * @return mixed | |
54 | */ | |
00be9182 | 55 | public static function get($name, $attribute = NULL) { |
6a488035 TO |
56 | $comp = CRM_Utils_Array::value($name, self::_info()); |
57 | if ($attribute) { | |
914d3734 | 58 | return $comp->info[$attribute] ?? NULL; |
6a488035 TO |
59 | } |
60 | return $comp; | |
61 | } | |
62 | ||
a0ee3941 EM |
63 | /** |
64 | * @param bool $force | |
65 | * | |
9a13600c | 66 | * @return CRM_Core_Component_Info[] |
b5834543 | 67 | * @throws CRM_Core_Exception |
a0ee3941 | 68 | */ |
6a488035 | 69 | public static function &getComponents($force = FALSE) { |
edbcbd96 | 70 | if (!isset(Civi::$statics[__CLASS__]['all']) || $force) { |
be2fb01f | 71 | Civi::$statics[__CLASS__]['all'] = []; |
6a488035 TO |
72 | |
73 | $cr = new CRM_Core_DAO_Component(); | |
74 | $cr->find(FALSE); | |
75 | while ($cr->fetch()) { | |
76 | $infoClass = $cr->namespace . '_' . self::COMPONENT_INFO_CLASS; | |
4d669903 | 77 | $infoClassFile = str_replace('_', DIRECTORY_SEPARATOR, $infoClass) . '.php'; |
78 | if (!CRM_Utils_File::isIncludable($infoClassFile)) { | |
79 | continue; | |
80 | } | |
81 | require_once $infoClassFile; | |
6a488035 TO |
82 | $infoObject = new $infoClass($cr->name, $cr->namespace, $cr->id); |
83 | if ($infoObject->info['name'] !== $cr->name) { | |
b5834543 | 84 | throw new CRM_Core_Exception("There is a discrepancy between name in component registry and in info file ({$cr->name})."); |
6a488035 | 85 | } |
edbcbd96 | 86 | Civi::$statics[__CLASS__]['all'][$cr->name] = $infoObject; |
6a488035 TO |
87 | unset($infoObject); |
88 | } | |
89 | } | |
90 | ||
edbcbd96 | 91 | return Civi::$statics[__CLASS__]['all']; |
6a488035 TO |
92 | } |
93 | ||
2ce81580 TO |
94 | /** |
95 | * @return array | |
96 | * Array(string $name => int $id). | |
97 | */ | |
98 | public static function &getComponentIDs() { | |
be2fb01f | 99 | $componentIDs = []; |
2ce81580 TO |
100 | |
101 | $cr = new CRM_Core_DAO_Component(); | |
102 | $cr->find(FALSE); | |
103 | while ($cr->fetch()) { | |
104 | $componentIDs[$cr->name] = $cr->id; | |
105 | } | |
106 | ||
107 | return $componentIDs; | |
108 | } | |
109 | ||
a0ee3941 EM |
110 | /** |
111 | * @param bool $force | |
112 | * | |
9a13600c | 113 | * @return CRM_Core_Component_Info[] |
a0ee3941 | 114 | */ |
518fa0ee | 115 | public static function &getEnabledComponents($force = FALSE) { |
6a488035 TO |
116 | return self::_info($force); |
117 | } | |
2dd1b730 | 118 | |
2f255668 CW |
119 | /** |
120 | * Triggered by on_change callback of the 'enable_components' setting. | |
121 | */ | |
518fa0ee | 122 | public static function flushEnabledComponents() { |
3ea36d17 | 123 | unset(Civi::$statics[__CLASS__]); |
281db812 | 124 | CRM_Core_BAO_Navigation::resetNavigation(); |
2f255668 | 125 | Civi::cache('metadata')->clear(); |
3d0e24ec | 126 | } |
6a488035 | 127 | |
a0ee3941 EM |
128 | /** |
129 | * @param bool $translated | |
130 | * | |
131 | * @return array | |
132 | */ | |
6a488035 TO |
133 | public static function &getNames($translated = FALSE) { |
134 | $allComponents = self::getComponents(); | |
135 | ||
be2fb01f | 136 | $names = []; |
6a488035 TO |
137 | foreach ($allComponents as $name => $comp) { |
138 | if ($translated) { | |
139 | $names[$comp->componentID] = $comp->info['translatedName']; | |
140 | } | |
141 | else { | |
142 | $names[$comp->componentID] = $name; | |
143 | } | |
144 | } | |
145 | return $names; | |
146 | } | |
147 | ||
a0ee3941 EM |
148 | /** |
149 | * @param $args | |
150 | * @param $type | |
151 | * | |
152 | * @return bool | |
153 | */ | |
00be9182 | 154 | public static function invoke(&$args, $type) { |
6a488035 TO |
155 | $info = self::_info(); |
156 | $config = CRM_Core_Config::singleton(); | |
157 | ||
158 | $firstArg = CRM_Utils_Array::value(1, $args, ''); | |
159 | $secondArg = CRM_Utils_Array::value(2, $args, ''); | |
160 | foreach ($info as $name => $comp) { | |
161 | if (in_array($name, $config->enableComponents) && | |
162 | (($comp->info['url'] === $firstArg && $type == 'main') || | |
163 | ($comp->info['url'] === $secondArg && $type == 'admin') | |
164 | ) | |
165 | ) { | |
166 | if ($type == 'main') { | |
167 | // also set the smarty variables to the current component | |
168 | $template = CRM_Core_Smarty::singleton(); | |
169 | $template->assign('activeComponent', $name); | |
a7488080 | 170 | if (!empty($comp->info[$name]['formTpl'])) { |
6a488035 TO |
171 | $template->assign('formTpl', $comp->info[$name]['formTpl']); |
172 | } | |
a7488080 | 173 | if (!empty($comp->info[$name]['css'])) { |
6a488035 TO |
174 | $styleSheets = '<style type="text/css">@import url(' . "{$config->resourceBase}css/{$comp->info[$name]['css']});</style>"; |
175 | CRM_Utils_System::addHTMLHead($styleSheet); | |
176 | } | |
177 | } | |
178 | $inv = $comp->getInvokeObject(); | |
179 | $inv->$type($args); | |
180 | return TRUE; | |
181 | } | |
182 | } | |
183 | return FALSE; | |
184 | } | |
185 | ||
a0ee3941 EM |
186 | /** |
187 | * @return array | |
188 | */ | |
00be9182 | 189 | public static function xmlMenu() { |
6a488035 TO |
190 | |
191 | // lets build the menu for all components | |
192 | $info = self::getComponents(TRUE); | |
193 | ||
be2fb01f | 194 | $files = []; |
6a488035 TO |
195 | foreach ($info as $name => $comp) { |
196 | $files = array_merge($files, | |
197 | $comp->menuFiles() | |
198 | ); | |
199 | } | |
200 | ||
201 | return $files; | |
202 | } | |
203 | ||
a0ee3941 | 204 | /** |
100fef9d | 205 | * @param string $componentName |
a0ee3941 EM |
206 | * |
207 | * @return mixed | |
208 | */ | |
00be9182 | 209 | public static function getComponentID($componentName) { |
6a488035 | 210 | $info = self::_info(); |
7b60d5b9 | 211 | if (!empty($info[$componentName])) { |
212 | return $info[$componentName]->componentID; | |
213 | } | |
6a488035 TO |
214 | } |
215 | ||
a0ee3941 | 216 | /** |
100fef9d | 217 | * @param int $componentID |
a0ee3941 EM |
218 | * |
219 | * @return int|null|string | |
220 | */ | |
00be9182 | 221 | public static function getComponentName($componentID) { |
6a488035 TO |
222 | $info = self::_info(); |
223 | ||
224 | $componentName = NULL; | |
225 | foreach ($info as $compName => $component) { | |
226 | if ($component->componentID == $componentID) { | |
227 | $componentName = $compName; | |
228 | break; | |
229 | } | |
230 | } | |
231 | ||
232 | return $componentName; | |
233 | } | |
234 | ||
a0ee3941 EM |
235 | /** |
236 | * @return array | |
237 | */ | |
5837835b | 238 | public static function &getQueryFields($checkPermission = TRUE) { |
6a488035 | 239 | $info = self::_info(); |
be2fb01f | 240 | $fields = []; |
6a488035 TO |
241 | foreach ($info as $name => $comp) { |
242 | if ($comp->usesSearch()) { | |
353ffa53 | 243 | $bqr = $comp->getBAOQueryObject(); |
5837835b | 244 | $flds = $bqr->getFields($checkPermission); |
6a488035 TO |
245 | $fields = array_merge($fields, $flds); |
246 | } | |
247 | } | |
248 | return $fields; | |
249 | } | |
250 | ||
a0ee3941 EM |
251 | /** |
252 | * @param $query | |
100fef9d | 253 | * @param string $fnName |
a0ee3941 | 254 | */ |
00be9182 | 255 | public static function alterQuery(&$query, $fnName) { |
6a488035 TO |
256 | $info = self::_info(); |
257 | ||
258 | foreach ($info as $name => $comp) { | |
259 | if ($comp->usesSearch()) { | |
260 | $bqr = $comp->getBAOQueryObject(); | |
261 | $bqr->$fnName($query); | |
262 | } | |
263 | } | |
264 | } | |
265 | ||
a0ee3941 | 266 | /** |
100fef9d | 267 | * @param string $fieldName |
a0ee3941 EM |
268 | * @param $mode |
269 | * @param $side | |
270 | * | |
271 | * @return null | |
272 | */ | |
00be9182 | 273 | public static function from($fieldName, $mode, $side) { |
6a488035 TO |
274 | $info = self::_info(); |
275 | ||
276 | $from = NULL; | |
277 | foreach ($info as $name => $comp) { | |
278 | if ($comp->usesSearch()) { | |
279 | $bqr = $comp->getBAOQueryObject(); | |
280 | $from = $bqr->from($fieldName, $mode, $side); | |
281 | if ($from) { | |
282 | return $from; | |
283 | } | |
284 | } | |
285 | } | |
286 | return $from; | |
287 | } | |
288 | ||
a0ee3941 EM |
289 | /** |
290 | * @param $mode | |
291 | * @param bool $includeCustomFields | |
292 | * | |
293 | * @return null | |
294 | */ | |
317fceb4 | 295 | public static function &defaultReturnProperties( |
f9f40af3 | 296 | $mode, |
6a488035 TO |
297 | $includeCustomFields = TRUE |
298 | ) { | |
299 | $info = self::_info(); | |
300 | ||
301 | $properties = NULL; | |
302 | foreach ($info as $name => $comp) { | |
303 | if ($comp->usesSearch()) { | |
304 | $bqr = $comp->getBAOQueryObject(); | |
305 | $properties = $bqr->defaultReturnProperties($mode, $includeCustomFields); | |
306 | if ($properties) { | |
307 | return $properties; | |
308 | } | |
309 | } | |
310 | } | |
adde8f5e CW |
311 | if (!$properties) { |
312 | $properties = CRM_Contact_BAO_Query_Hook::singleton()->getDefaultReturnProperties($mode); | |
313 | } | |
6a488035 TO |
314 | return $properties; |
315 | } | |
316 | ||
a0ee3941 | 317 | /** |
c490a46a | 318 | * @param CRM_Core_Form $form |
a0ee3941 | 319 | */ |
00be9182 | 320 | public static function &buildSearchForm(&$form) { |
6a488035 TO |
321 | $info = self::_info(); |
322 | ||
323 | foreach ($info as $name => $comp) { | |
324 | if ($comp->usesSearch()) { | |
325 | $bqr = $comp->getBAOQueryObject(); | |
326 | $bqr->buildSearchForm($form); | |
327 | } | |
328 | } | |
329 | } | |
330 | ||
a0ee3941 EM |
331 | /** |
332 | * @param $row | |
100fef9d | 333 | * @param int $id |
a0ee3941 | 334 | */ |
00be9182 | 335 | public static function searchAction(&$row, $id) { |
6a488035 TO |
336 | $info = self::_info(); |
337 | ||
338 | foreach ($info as $name => $comp) { | |
339 | if ($comp->usesSearch()) { | |
340 | $bqr = $comp->getBAOQueryObject(); | |
341 | $bqr->searchAction($row, $id); | |
342 | } | |
343 | } | |
344 | } | |
345 | ||
a0ee3941 | 346 | /** |
b5f8992a EM |
347 | * Unused function. |
348 | * | |
a0ee3941 | 349 | * @return array|null |
b5f8992a EM |
350 | * |
351 | * @deprecated | |
a0ee3941 | 352 | */ |
b5f8992a EM |
353 | public static function contactSubTypes() { |
354 | CRM_Core_Error::deprecatedWarning('unused'); | |
06806a70 | 355 | return []; |
6a488035 TO |
356 | } |
357 | ||
a0ee3941 | 358 | /** |
b5f8992a | 359 | * Unused function. |
a0ee3941 | 360 | * |
b5f8992a EM |
361 | * @param string $subType |
362 | * @param string $op | |
363 | * | |
364 | * @return null|string | |
365 | * | |
366 | * @deprecated | |
a0ee3941 | 367 | */ |
b5f8992a EM |
368 | public static function contactSubTypeProperties($subType, $op): ?string { |
369 | CRM_Core_Error::deprecatedWarning('unused'); | |
6a488035 TO |
370 | $properties = self::contactSubTypes(); |
371 | if (array_key_exists($subType, $properties) && | |
372 | array_key_exists($op, $properties[$subType]) | |
373 | ) { | |
374 | return $properties[$subType][$op]; | |
375 | } | |
b5f8992a | 376 | return NULL; |
6a488035 TO |
377 | } |
378 | ||
6a488035 | 379 | /** |
0880a9d0 | 380 | * Handle table dependencies of components. |
6a488035 | 381 | * |
6a0b768e TO |
382 | * @param array $tables |
383 | * Array of tables. | |
6a488035 | 384 | * |
6a488035 | 385 | */ |
00be9182 | 386 | public static function tableNames(&$tables) { |
6a488035 TO |
387 | $info = self::_info(); |
388 | ||
389 | foreach ($info as $name => $comp) { | |
390 | if ($comp->usesSearch()) { | |
391 | $bqr = $comp->getBAOQueryObject(); | |
392 | $bqr->tableNames($tables); | |
393 | } | |
394 | } | |
395 | } | |
396 | ||
397 | /** | |
0880a9d0 | 398 | * Get components info from info file. |
ea3ddccf | 399 | * |
400 | * @param string $crmFolderDir | |
401 | * | |
402 | * @return array | |
6a488035 | 403 | */ |
00be9182 | 404 | public static function getComponentsFromFile($crmFolderDir) { |
be2fb01f | 405 | $components = []; |
6a488035 | 406 | //traverse CRM folder and check for Info file |
948d11bf | 407 | if (is_dir($crmFolderDir) && $dir = opendir($crmFolderDir)) { |
6a488035 TO |
408 | while ($subDir = readdir($dir)) { |
409 | // skip the extensions diretory since it has an Info.php file also | |
b5f8992a | 410 | if ($subDir === 'Extension') { |
6a488035 TO |
411 | continue; |
412 | } | |
413 | ||
414 | $infoFile = $crmFolderDir . "/{$subDir}/" . self::COMPONENT_INFO_CLASS . '.php'; | |
415 | if (file_exists($infoFile)) { | |
416 | $infoClass = 'CRM_' . $subDir . '_' . self::COMPONENT_INFO_CLASS; | |
6a488035 TO |
417 | $infoObject = new $infoClass(NULL, NULL, NULL); |
418 | $components[$infoObject->info['name']] = $infoObject; | |
419 | unset($infoObject); | |
420 | } | |
421 | } | |
422 | } | |
423 | ||
424 | return $components; | |
425 | } | |
96025800 | 426 | |
166a1708 EM |
427 | /** |
428 | * Is the specified component enabled. | |
429 | * | |
430 | * @param string $component | |
431 | * Component name - ie CiviMember, CiviContribute, CiviEvent... | |
432 | * | |
433 | * @return bool | |
434 | * Is the component enabled. | |
435 | */ | |
436 | public static function isEnabled(string $component): bool { | |
437 | return in_array($component, CRM_Core_Config::singleton()->enableComponents, TRUE); | |
438 | } | |
439 | ||
6a488035 | 440 | } |