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