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