2ba5c4d54deb299e0ac2d7ce0a4c29ca8e428290
[civicrm-core.git] / Civi / Core / SettingsMetadata.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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 +--------------------------------------------------------------------+
26 */
27
28 namespace Civi\Core;
29
30 /**
31 * Class SettingsMetadata
32 * @package Civi\Core
33 */
34 class SettingsMetadata {
35
36 const ALL = 'all';
37
38 /**
39 * WARNING: This interface may change.
40 *
41 * This provides information about the setting - similar to the fields concept for DAO information.
42 * As the setting is serialized code creating validation setting input needs to know the data type
43 * This also helps move information out of the form layer into the data layer where people can interact with
44 * it via the API or other mechanisms. In order to keep this consistent it is important the form layer
45 * also leverages it.
46 *
47 * Note that this function should never be called when using the runtime getvalue function. Caching works
48 * around the expectation it will be called during setting administration
49 *
50 * Function is intended for configuration rather than runtime access to settings
51 *
52 * The following params will filter the result. If none are passed all settings will be returns
53 *
54 * @param array $filters
55 * @param int $domainID
56 *
57 * @return array
58 * the following information as appropriate for each setting
59 * - name
60 * - type
61 * - default
62 * - add (CiviCRM version added)
63 * - is_domain
64 * - is_contact
65 * - description
66 * - help_text
67 */
68 public static function getMetadata($filters = array(), $domainID = NULL) {
69 if ($domainID === NULL) {
70 $domainID = \CRM_Core_Config::domainID();
71 }
72
73 $cache = \Civi::cache('settings');
74 $cacheString = 'settingsMetadata_' . $domainID . '_';
75 // the caching into 'All' seems to be a duplicate of caching to
76 // settingsMetadata__ - I think the reason was to cache all settings as defined & then those altered by a hook
77 $settingsMetadata = $cache->get($cacheString);
78 $cached = is_array($settingsMetadata);
79
80 if (!$cached) {
81 $settingsMetadata = $cache->get(self::ALL);
82 if (empty($settingsMetadata)) {
83 global $civicrm_root;
84 $metaDataFolders = array($civicrm_root . '/settings');
85 \CRM_Utils_Hook::alterSettingsFolders($metaDataFolders);
86 $settingsMetadata = self::loadSettingsMetaDataFolders($metaDataFolders);
87 $cache->set(self::ALL, $settingsMetadata);
88 }
89 }
90
91 \CRM_Utils_Hook::alterSettingsMetaData($settingsMetadata, $domainID, NULL);
92
93 if (!$cached) {
94 $cache->set($cacheString, $settingsMetadata);
95 }
96
97 self::_filterSettingsSpecification($filters, $settingsMetadata);
98
99 return $settingsMetadata;
100 }
101
102 /**
103 * Load the settings files defined in a series of folders.
104 * @param array $metaDataFolders
105 * List of folder paths.
106 * @return array
107 */
108 protected static function loadSettingsMetaDataFolders($metaDataFolders) {
109 $settingsMetadata = array();
110 $loadedFolders = array();
111 foreach ($metaDataFolders as $metaDataFolder) {
112 $realFolder = realpath($metaDataFolder);
113 if (is_dir($realFolder) && !isset($loadedFolders[$realFolder])) {
114 $loadedFolders[$realFolder] = TRUE;
115 $settingsMetadata = $settingsMetadata + self::loadSettingsMetadata($metaDataFolder);
116 }
117 }
118 return $settingsMetadata;
119 }
120
121 /**
122 * Load up settings metadata from files.
123 *
124 * @param array $metaDataFolder
125 *
126 * @return array
127 */
128 protected static function loadSettingsMetadata($metaDataFolder) {
129 $settingMetaData = array();
130 $settingsFiles = \CRM_Utils_File::findFiles($metaDataFolder, '*.setting.php');
131 foreach ($settingsFiles as $file) {
132 $settings = include $file;
133 $settingMetaData = array_merge($settingMetaData, $settings);
134 }
135 return $settingMetaData;
136 }
137
138 /**
139 * Filter the settings metadata according to filters passed in. This is a convenience filter
140 * and allows selective reverting / filling of settings
141 *
142 * @param array $filters
143 * Filters to match against data.
144 * @param array $settingSpec
145 * Metadata to filter.
146 */
147 protected static function _filterSettingsSpecification($filters, &$settingSpec) {
148 if (empty($filters)) {
149 return;
150 }
151 elseif (array_keys($filters) == array('name')) {
152 $settingSpec = array($filters['name'] => \CRM_Utils_Array::value($filters['name'], $settingSpec, ''));
153 return;
154 }
155 else {
156 foreach ($settingSpec as $field => $fieldValues) {
157 if (array_intersect_assoc($fieldValues, $filters) != $filters) {
158 unset($settingSpec[$field]);
159 }
160 }
161 return;
162 }
163 }
164
165 }