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 * @return CRM_Core_Component_Info[]
32 private static function &_info($force = FALSE) {
33 if (!isset(Civi
::$statics[__CLASS__
]['info'])||
$force) {
34 Civi
::$statics[__CLASS__
]['info'] = [];
36 $config = CRM_Core_Config
::singleton();
37 $c = self
::getComponents();
39 foreach ($c as $name => $comp) {
40 if (in_array($name, $config->enableComponents
)) {
41 Civi
::$statics[__CLASS__
]['info'][$name] = $comp;
46 return Civi
::$statics[__CLASS__
]['info'];
51 * @param null $attribute
55 public static function get($name, $attribute = NULL) {
56 $comp = CRM_Utils_Array
::value($name, self
::_info());
58 return $comp->info
[$attribute] ??
NULL;
66 * @return CRM_Core_Component_Info[]
67 * @throws CRM_Core_Exception
69 public static function &getComponents($force = FALSE) {
70 if (!isset(Civi
::$statics[__CLASS__
]['all']) ||
$force) {
71 Civi
::$statics[__CLASS__
]['all'] = [];
73 $cr = new CRM_Core_DAO_Component();
75 while ($cr->fetch()) {
76 $infoClass = $cr->namespace . '_' . self
::COMPONENT_INFO_CLASS
;
77 $infoClassFile = str_replace('_', DIRECTORY_SEPARATOR
, $infoClass) . '.php';
78 if (!CRM_Utils_File
::isIncludable($infoClassFile)) {
81 require_once $infoClassFile;
82 $infoObject = new $infoClass($cr->name
, $cr->namespace, $cr->id
);
83 if ($infoObject->info
['name'] !== $cr->name
) {
84 throw new CRM_Core_Exception("There is a discrepancy between name in component registry and in info file ({$cr->name}).");
86 Civi
::$statics[__CLASS__
]['all'][$cr->name
] = $infoObject;
91 return Civi
::$statics[__CLASS__
]['all'];
96 * Array(string $name => int $id).
98 public static function &getComponentIDs() {
101 $cr = new CRM_Core_DAO_Component();
103 while ($cr->fetch()) {
104 $componentIDs[$cr->name
] = $cr->id
;
107 return $componentIDs;
113 * @return CRM_Core_Component_Info[]
115 public static function &getEnabledComponents($force = FALSE) {
116 return self
::_info($force);
120 * Triggered by on_change callback of the 'enable_components' setting.
122 public static function flushEnabledComponents() {
123 unset(Civi
::$statics[__CLASS__
]);
124 CRM_Core_BAO_Navigation
::resetNavigation();
125 Civi
::cache('metadata')->clear();
129 * @param bool $translated
133 public static function &getNames($translated = FALSE) {
134 $allComponents = self
::getComponents();
137 foreach ($allComponents as $name => $comp) {
139 $names[$comp->componentID
] = $comp->info
['translatedName'];
142 $names[$comp->componentID
] = $name;
154 public static function invoke(&$args, $type) {
155 $info = self
::_info();
156 $config = CRM_Core_Config
::singleton();
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')
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);
170 if (!empty($comp->info
[$name]['formTpl'])) {
171 $template->assign('formTpl', $comp->info
[$name]['formTpl']);
173 if (!empty($comp->info
[$name]['css'])) {
174 $styleSheets = '<style type="text/css">@import url(' . "{$config->resourceBase}css/{$comp->info[$name]['css']});</style>";
175 CRM_Utils_System
::addHTMLHead($styleSheet);
178 $inv = $comp->getInvokeObject();
189 public static function xmlMenu() {
191 // lets build the menu for all components
192 $info = self
::getComponents(TRUE);
195 foreach ($info as $name => $comp) {
196 $files = array_merge($files,
205 * @param string $componentName
209 public static function getComponentID($componentName) {
210 $info = self
::_info();
211 if (!empty($info[$componentName])) {
212 return $info[$componentName]->componentID
;
217 * @param int $componentID
219 * @return int|null|string
221 public static function getComponentName($componentID) {
222 $info = self
::_info();
224 $componentName = NULL;
225 foreach ($info as $compName => $component) {
226 if ($component->componentID
== $componentID) {
227 $componentName = $compName;
232 return $componentName;
238 public static function &getQueryFields($checkPermission = TRUE) {
239 $info = self
::_info();
241 foreach ($info as $name => $comp) {
242 if ($comp->usesSearch()) {
243 $bqr = $comp->getBAOQueryObject();
244 $flds = $bqr->getFields($checkPermission);
245 $fields = array_merge($fields, $flds);
253 * @param string $fnName
255 public static function alterQuery(&$query, $fnName) {
256 $info = self
::_info();
258 foreach ($info as $name => $comp) {
259 if ($comp->usesSearch()) {
260 $bqr = $comp->getBAOQueryObject();
261 $bqr->$fnName($query);
267 * @param string $fieldName
273 public static function from($fieldName, $mode, $side) {
274 $info = self
::_info();
277 foreach ($info as $name => $comp) {
278 if ($comp->usesSearch()) {
279 $bqr = $comp->getBAOQueryObject();
280 $from = $bqr->from($fieldName, $mode, $side);
291 * @param bool $includeCustomFields
295 public static function &defaultReturnProperties(
297 $includeCustomFields = TRUE
299 $info = self
::_info();
302 foreach ($info as $name => $comp) {
303 if ($comp->usesSearch()) {
304 $bqr = $comp->getBAOQueryObject();
305 $properties = $bqr->defaultReturnProperties($mode, $includeCustomFields);
312 $properties = CRM_Contact_BAO_Query_Hook
::singleton()->getDefaultReturnProperties($mode);
318 * @param CRM_Core_Form $form
320 public static function &buildSearchForm(&$form) {
321 $info = self
::_info();
323 foreach ($info as $name => $comp) {
324 if ($comp->usesSearch()) {
325 $bqr = $comp->getBAOQueryObject();
326 $bqr->buildSearchForm($form);
335 public static function searchAction(&$row, $id) {
336 $info = self
::_info();
338 foreach ($info as $name => $comp) {
339 if ($comp->usesSearch()) {
340 $bqr = $comp->getBAOQueryObject();
341 $bqr->searchAction($row, $id);
353 public static function contactSubTypes() {
354 CRM_Core_Error
::deprecatedWarning('unused');
361 * @param string $subType
364 * @return null|string
368 public static function contactSubTypeProperties($subType, $op): ?
string {
369 CRM_Core_Error
::deprecatedWarning('unused');
370 $properties = self
::contactSubTypes();
371 if (array_key_exists($subType, $properties) &&
372 array_key_exists($op, $properties[$subType])
374 return $properties[$subType][$op];
380 * Handle table dependencies of components.
382 * @param array $tables
386 public static function tableNames(&$tables) {
387 $info = self
::_info();
389 foreach ($info as $name => $comp) {
390 if ($comp->usesSearch()) {
391 $bqr = $comp->getBAOQueryObject();
392 $bqr->tableNames($tables);
398 * Get components info from info file.
400 * @param string $crmFolderDir
404 public static function getComponentsFromFile($crmFolderDir) {
406 //traverse CRM folder and check for Info file
407 if (is_dir($crmFolderDir) && $dir = opendir($crmFolderDir)) {
408 while ($subDir = readdir($dir)) {
409 // skip the extensions diretory since it has an Info.php file also
410 if ($subDir === 'Extension') {
414 $infoFile = $crmFolderDir . "/{$subDir}/" . self
::COMPONENT_INFO_CLASS
. '.php';
415 if (file_exists($infoFile)) {
416 $infoClass = 'CRM_' . $subDir . '_' . self
::COMPONENT_INFO_CLASS
;
417 $infoObject = new $infoClass(NULL, NULL, NULL);
418 $components[$infoObject->info
['name']] = $infoObject;
428 * Is the specified component enabled.
430 * @param string $component
431 * Component name - ie CiviMember, CiviContribute, CiviEvent...
434 * Is the component enabled.
436 public static function isEnabled(string $component): bool {
437 return in_array($component, CRM_Core_Config
::singleton()->enableComponents
, TRUE);