3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
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 |
9 +--------------------------------------------------------------------+
13 * Component stores all the static and dynamic information of the various
17 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 class CRM_Core_Component
{
22 * End part (filename) of the component information class'es name
23 * that needs to be present in components main directory.
25 const COMPONENT_INFO_CLASS
= 'Info';
30 public static $_contactSubTypes = NULL;
35 * @return CRM_Core_Component_Info[]
37 private static function &_info($force = FALSE) {
38 if (!isset(Civi
::$statics[__CLASS__
]['info'])||
$force) {
39 Civi
::$statics[__CLASS__
]['info'] = [];
41 $config = CRM_Core_Config
::singleton();
42 $c = self
::getComponents();
44 foreach ($c as $name => $comp) {
45 if (in_array($name, $config->enableComponents
)) {
46 Civi
::$statics[__CLASS__
]['info'][$name] = $comp;
51 return Civi
::$statics[__CLASS__
]['info'];
56 * @param null $attribute
60 public static function get($name, $attribute = NULL) {
61 $comp = CRM_Utils_Array
::value($name, self
::_info());
63 return $comp->info
[$attribute] ??
NULL;
71 * @return CRM_Core_Component_Info[]
72 * @throws CRM_Core_Exception
74 public static function &getComponents($force = FALSE) {
75 if (!isset(Civi
::$statics[__CLASS__
]['all']) ||
$force) {
76 Civi
::$statics[__CLASS__
]['all'] = [];
78 $cr = new CRM_Core_DAO_Component();
80 while ($cr->fetch()) {
81 $infoClass = $cr->namespace . '_' . self
::COMPONENT_INFO_CLASS
;
82 $infoClassFile = str_replace('_', DIRECTORY_SEPARATOR
, $infoClass) . '.php';
83 if (!CRM_Utils_File
::isIncludable($infoClassFile)) {
86 require_once $infoClassFile;
87 $infoObject = new $infoClass($cr->name
, $cr->namespace, $cr->id
);
88 if ($infoObject->info
['name'] !== $cr->name
) {
89 throw new CRM_Core_Exception("There is a discrepancy between name in component registry and in info file ({$cr->name}).");
91 Civi
::$statics[__CLASS__
]['all'][$cr->name
] = $infoObject;
96 return Civi
::$statics[__CLASS__
]['all'];
101 * Array(string $name => int $id).
103 public static function &getComponentIDs() {
106 $cr = new CRM_Core_DAO_Component();
108 while ($cr->fetch()) {
109 $componentIDs[$cr->name
] = $cr->id
;
112 return $componentIDs;
118 * @return CRM_Core_Component_Info[]
120 public static function &getEnabledComponents($force = FALSE) {
121 return self
::_info($force);
125 * Triggered by on_change callback of the 'enable_components' setting.
127 public static function flushEnabledComponents() {
128 unset(Civi
::$statics[__CLASS__
]);
129 CRM_Core_BAO_Navigation
::resetNavigation();
130 Civi
::cache('metadata')->clear();
134 * @param bool $translated
138 public static function &getNames($translated = FALSE) {
139 $allComponents = self
::getComponents();
142 foreach ($allComponents as $name => $comp) {
144 $names[$comp->componentID
] = $comp->info
['translatedName'];
147 $names[$comp->componentID
] = $name;
159 public static function invoke(&$args, $type) {
160 $info = self
::_info();
161 $config = CRM_Core_Config
::singleton();
163 $firstArg = CRM_Utils_Array
::value(1, $args, '');
164 $secondArg = CRM_Utils_Array
::value(2, $args, '');
165 foreach ($info as $name => $comp) {
166 if (in_array($name, $config->enableComponents
) &&
167 (($comp->info
['url'] === $firstArg && $type == 'main') ||
168 ($comp->info
['url'] === $secondArg && $type == 'admin')
171 if ($type == 'main') {
172 // also set the smarty variables to the current component
173 $template = CRM_Core_Smarty
::singleton();
174 $template->assign('activeComponent', $name);
175 if (!empty($comp->info
[$name]['formTpl'])) {
176 $template->assign('formTpl', $comp->info
[$name]['formTpl']);
178 if (!empty($comp->info
[$name]['css'])) {
179 $styleSheets = '<style type="text/css">@import url(' . "{$config->resourceBase}css/{$comp->info[$name]['css']});</style>";
180 CRM_Utils_System
::addHTMLHead($styleSheet);
183 $inv = $comp->getInvokeObject();
194 public static function xmlMenu() {
196 // lets build the menu for all components
197 $info = self
::getComponents(TRUE);
200 foreach ($info as $name => $comp) {
201 $files = array_merge($files,
210 * @param string $componentName
214 public static function getComponentID($componentName) {
215 $info = self
::_info();
216 if (!empty($info[$componentName])) {
217 return $info[$componentName]->componentID
;
222 * @param int $componentID
224 * @return int|null|string
226 public static function getComponentName($componentID) {
227 $info = self
::_info();
229 $componentName = NULL;
230 foreach ($info as $compName => $component) {
231 if ($component->componentID
== $componentID) {
232 $componentName = $compName;
237 return $componentName;
243 public static function &getQueryFields($checkPermission = TRUE) {
244 $info = self
::_info();
246 foreach ($info as $name => $comp) {
247 if ($comp->usesSearch()) {
248 $bqr = $comp->getBAOQueryObject();
249 $flds = $bqr->getFields($checkPermission);
250 $fields = array_merge($fields, $flds);
258 * @param string $fnName
260 public static function alterQuery(&$query, $fnName) {
261 $info = self
::_info();
263 foreach ($info as $name => $comp) {
264 if ($comp->usesSearch()) {
265 $bqr = $comp->getBAOQueryObject();
266 $bqr->$fnName($query);
272 * @param string $fieldName
278 public static function from($fieldName, $mode, $side) {
279 $info = self
::_info();
282 foreach ($info as $name => $comp) {
283 if ($comp->usesSearch()) {
284 $bqr = $comp->getBAOQueryObject();
285 $from = $bqr->from($fieldName, $mode, $side);
296 * @param bool $includeCustomFields
300 public static function &defaultReturnProperties(
302 $includeCustomFields = TRUE
304 $info = self
::_info();
307 foreach ($info as $name => $comp) {
308 if ($comp->usesSearch()) {
309 $bqr = $comp->getBAOQueryObject();
310 $properties = $bqr->defaultReturnProperties($mode, $includeCustomFields);
317 $properties = CRM_Contact_BAO_Query_Hook
::singleton()->getDefaultReturnProperties($mode);
323 * @param CRM_Core_Form $form
325 public static function &buildSearchForm(&$form) {
326 $info = self
::_info();
328 foreach ($info as $name => $comp) {
329 if ($comp->usesSearch()) {
330 $bqr = $comp->getBAOQueryObject();
331 $bqr->buildSearchForm($form);
340 public static function searchAction(&$row, $id) {
341 $info = self
::_info();
343 foreach ($info as $name => $comp) {
344 if ($comp->usesSearch()) {
345 $bqr = $comp->getBAOQueryObject();
346 $bqr->searchAction($row, $id);
354 public static function &contactSubTypes() {
355 if (self
::$_contactSubTypes == NULL) {
356 self
::$_contactSubTypes = [];
358 return self
::$_contactSubTypes;
367 public static function &contactSubTypeProperties($subType, $op) {
368 $properties = self
::contactSubTypes();
369 if (array_key_exists($subType, $properties) &&
370 array_key_exists($op, $properties[$subType])
372 return $properties[$subType][$op];
374 return CRM_Core_DAO
::$_nullObject;
378 * Handle table dependencies of components.
380 * @param array $tables
384 public static function tableNames(&$tables) {
385 $info = self
::_info();
387 foreach ($info as $name => $comp) {
388 if ($comp->usesSearch()) {
389 $bqr = $comp->getBAOQueryObject();
390 $bqr->tableNames($tables);
396 * Get components info from info file.
398 * @param string $crmFolderDir
402 public static function getComponentsFromFile($crmFolderDir) {
404 //traverse CRM folder and check for Info file
405 if (is_dir($crmFolderDir) && $dir = opendir($crmFolderDir)) {
406 while ($subDir = readdir($dir)) {
407 // skip the extensions diretory since it has an Info.php file also
408 if ($subDir == 'Extension') {
412 $infoFile = $crmFolderDir . "/{$subDir}/" . self
::COMPONENT_INFO_CLASS
. '.php';
413 if (file_exists($infoFile)) {
414 $infoClass = 'CRM_' . $subDir . '_' . self
::COMPONENT_INFO_CLASS
;
415 require_once str_replace('_', DIRECTORY_SEPARATOR
, $infoClass) . '.php';
416 $infoObject = new $infoClass(NULL, NULL, NULL);
417 $components[$infoObject->info
['name']] = $infoObject;
427 * Is the specified component enabled.
429 * @param string $component
430 * Component name - ie CiviMember, CiviContribute, CiviEvent...
433 * Is the component enabled.
435 public static function isEnabled(string $component): bool {
436 return in_array($component, CRM_Core_Config
::singleton()->enableComponents
, TRUE);