Merge pull request #19101 from colemanw/searchJoins
[civicrm-core.git] / Civi / Core / SettingsMetadata.php
CommitLineData
c7d90a9f
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
41498ac5 4 | Copyright CiviCRM LLC. All rights reserved. |
c7d90a9f 5 | |
41498ac5
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 |
c7d90a9f
TO
9 +--------------------------------------------------------------------+
10 */
11
12namespace Civi\Core;
13
14/**
15 * Class SettingsMetadata
16 * @package Civi\Core
17 */
18class SettingsMetadata {
19
c7d90a9f
TO
20 /**
21 * WARNING: This interface may change.
22 *
23 * This provides information about the setting - similar to the fields concept for DAO information.
24 * As the setting is serialized code creating validation setting input needs to know the data type
25 * This also helps move information out of the form layer into the data layer where people can interact with
26 * it via the API or other mechanisms. In order to keep this consistent it is important the form layer
27 * also leverages it.
28 *
29 * Note that this function should never be called when using the runtime getvalue function. Caching works
30 * around the expectation it will be called during setting administration
31 *
32 * Function is intended for configuration rather than runtime access to settings
33 *
34 * The following params will filter the result. If none are passed all settings will be returns
35 *
36 * @param array $filters
37 * @param int $domainID
4cc9fbc2 38 * @param bool $loadOptions
c7d90a9f
TO
39 *
40 * @return array
41 * the following information as appropriate for each setting
42 * - name
43 * - type
44 * - default
45 * - add (CiviCRM version added)
46 * - is_domain
47 * - is_contact
48 * - description
49 * - help_text
4cc9fbc2
CW
50 * - options
51 * - pseudoconstant
c7d90a9f 52 */
4cc9fbc2 53 public static function getMetadata($filters = [], $domainID = NULL, $loadOptions = FALSE) {
e1d39824
TO
54 if ($domainID === NULL) {
55 $domainID = \CRM_Core_Config::domainID();
56 }
57
c7d90a9f 58 $cache = \Civi::cache('settings');
e1d39824 59 $cacheString = 'settingsMetadata_' . $domainID . '_';
c7d90a9f 60 $settingsMetadata = $cache->get($cacheString);
c7d90a9f 61
1209c8a7
CW
62 if (!is_array($settingsMetadata)) {
63 global $civicrm_root;
64 $metaDataFolders = [$civicrm_root . '/settings'];
65 \CRM_Utils_Hook::alterSettingsFolders($metaDataFolders);
66 $settingsMetadata = self::loadSettingsMetaDataFolders($metaDataFolders);
67 \CRM_Utils_Hook::alterSettingsMetaData($settingsMetadata, $domainID, NULL);
c7d90a9f
TO
68 $cache->set($cacheString, $settingsMetadata);
69 }
70
71 self::_filterSettingsSpecification($filters, $settingsMetadata);
4cc9fbc2
CW
72 if ($loadOptions) {
73 self::loadOptions($settingsMetadata);
74 }
c7d90a9f
TO
75
76 return $settingsMetadata;
77 }
78
79 /**
80 * Load the settings files defined in a series of folders.
81 * @param array $metaDataFolders
82 * List of folder paths.
83 * @return array
84 */
85 protected static function loadSettingsMetaDataFolders($metaDataFolders) {
c64f69d9
CW
86 $settingsMetadata = [];
87 $loadedFolders = [];
c7d90a9f
TO
88 foreach ($metaDataFolders as $metaDataFolder) {
89 $realFolder = realpath($metaDataFolder);
90 if (is_dir($realFolder) && !isset($loadedFolders[$realFolder])) {
91 $loadedFolders[$realFolder] = TRUE;
3c250b10 92 $settingsMetadata = $settingsMetadata + self::loadSettingsMetadata($metaDataFolder);
c7d90a9f
TO
93 }
94 }
95 return $settingsMetadata;
96 }
97
98 /**
99 * Load up settings metadata from files.
54957108 100 *
101 * @param array $metaDataFolder
102 *
103 * @return array
c7d90a9f
TO
104 */
105 protected static function loadSettingsMetadata($metaDataFolder) {
c64f69d9 106 $settingMetaData = [];
c7d90a9f
TO
107 $settingsFiles = \CRM_Utils_File::findFiles($metaDataFolder, '*.setting.php');
108 foreach ($settingsFiles as $file) {
109 $settings = include $file;
110 $settingMetaData = array_merge($settingMetaData, $settings);
111 }
c7d90a9f
TO
112 return $settingMetaData;
113 }
114
115 /**
116 * Filter the settings metadata according to filters passed in. This is a convenience filter
117 * and allows selective reverting / filling of settings
118 *
119 * @param array $filters
120 * Filters to match against data.
121 * @param array $settingSpec
122 * Metadata to filter.
123 */
124 protected static function _filterSettingsSpecification($filters, &$settingSpec) {
4cc9fbc2
CW
125 if (!empty($filters['name'])) {
126 $settingSpec = array_intersect_key($settingSpec, array_flip((array) $filters['name']));
127 // FIXME: This is a workaround for settingsBag::setDb() called by unit tests with settings names that don't exist
128 $settingSpec += array_fill_keys((array) $filters['name'], []);
129 unset($filters['name']);
c7d90a9f 130 }
4cc9fbc2 131 if (!empty($filters)) {
c7d90a9f
TO
132 foreach ($settingSpec as $field => $fieldValues) {
133 if (array_intersect_assoc($fieldValues, $filters) != $filters) {
134 unset($settingSpec[$field]);
135 }
136 }
4cc9fbc2
CW
137 }
138 }
139
140 /**
141 * Retrieve options from settings metadata
142 *
143 * @param array $settingSpec
144 */
145 protected static function loadOptions(&$settingSpec) {
146 foreach ($settingSpec as &$spec) {
147 if (empty($spec['pseudoconstant'])) {
148 continue;
149 }
356013b6 150 $pseudoconstant = $spec['pseudoconstant'];
4cc9fbc2
CW
151 // It would be nice if we could leverage CRM_Core_PseudoConstant::get() somehow,
152 // but it's tightly coupled to DAO/field. However, if you really need to support
153 // more pseudoconstant types, then probably best to refactor it. For now, KISS.
356013b6 154 if (!empty($pseudoconstant['callback'])) {
155 $spec['options'] = Resolver::singleton()->call($pseudoconstant['callback'], []);
4cc9fbc2 156 }
356013b6 157 elseif (!empty($pseudoconstant['optionGroupName'])) {
158 $keyColumn = \CRM_Utils_Array::value('keyColumn', $pseudoconstant, 'value');
159 $spec['options'] = \CRM_Core_OptionGroup::values($pseudoconstant['optionGroupName'], FALSE, FALSE, TRUE, NULL, 'label', TRUE, FALSE, $keyColumn);
160 }
161 if (!empty($pseudoconstant['table'])) {
162 $params = [
163 'condition' => $pseudoconstant['condition'] ?? [],
164 'keyColumn' => $pseudoconstant['keyColumn'] ?? NULL,
165 'labelColumn' => $pseudoconstant['labelColumn'] ?? NULL,
166 ];
167 $spec['options'] = \CRM_Core_PseudoConstant::renderOptionsFromTablePseudoconstant($pseudoconstant, $params, ($spec['localize_context'] ?? NULL), 'get');
4cc9fbc2 168 }
c7d90a9f
TO
169 }
170 }
171
172}