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