Merge pull request #16488 from mattwire/quickform_requiredfields
[civicrm-core.git] / CRM / Core / BAO / WordReplacement.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 * Class CRM_Core_BAO_WordReplacement.
20 */
21 class CRM_Core_BAO_WordReplacement extends CRM_Core_DAO_WordReplacement {
22
23 /**
24 * Class constructor.
25 */
26 public function __construct() {
27 parent::__construct();
28 }
29
30 /**
31 * Function that must have never worked & should be removed.
32 *
33 * Retrieve DB object based on input parameters.
34 *
35 * It also stores all the retrieved values in the default array.
36 *
37 * @param array $params
38 * (reference ) an assoc array of name/value pairs.
39 * @param array $defaults
40 * (reference ) an assoc array to hold the flattened values.
41 *
42 * @return CRM_Core_DAO_WordReplacement
43 */
44 public static function retrieve(&$params, &$defaults) {
45 return CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_WordRepalcement', $params, $defaults);
46 }
47
48 /**
49 * Get the domain BAO.
50 *
51 * @param null $reset
52 *
53 * @return null|CRM_Core_BAO_WordReplacement
54 * @throws CRM_Core_Exception
55 */
56 public static function getWordReplacement($reset = NULL) {
57 static $wordReplacement = NULL;
58 if (!$wordReplacement || $reset) {
59 $wordReplacement = new CRM_Core_BAO_WordReplacement();
60 $wordReplacement->id = CRM_Core_Config::wordReplacementID();
61 if (!$wordReplacement->find(TRUE)) {
62 throw new CRM_Core_Exception('Unable to find word replacement');
63 }
64 }
65 return $wordReplacement;
66 }
67
68 /**
69 * Save the values of a WordReplacement.
70 *
71 * @param array $params
72 * @param int $id
73 *
74 * @return array
75 */
76 public static function edit(&$params, &$id) {
77 $wordReplacement = new CRM_Core_DAO_WordReplacement();
78 $wordReplacement->id = $id;
79 $wordReplacement->copyValues($params);
80 $wordReplacement->save();
81 if (!isset($params['options']) || CRM_Utils_Array::value('wp-rebuild', $params['options'], TRUE)) {
82 self::rebuild();
83 }
84 return $wordReplacement;
85 }
86
87 /**
88 * Create a new WordReplacement.
89 *
90 * @param array $params
91 *
92 * @return array
93 */
94 public static function create($params) {
95 if (array_key_exists("domain_id", $params) === FALSE) {
96 $params["domain_id"] = CRM_Core_Config::domainID();
97 }
98 $wordReplacement = new CRM_Core_DAO_WordReplacement();
99 $wordReplacement->copyValues($params);
100 $wordReplacement->save();
101 if (!isset($params['options']) || CRM_Utils_Array::value('wp-rebuild', $params['options'], TRUE)) {
102 self::rebuild();
103 }
104 return $wordReplacement;
105 }
106
107 /**
108 * Delete website.
109 *
110 * @param int $id
111 * WordReplacement id.
112 *
113 * @return object
114 */
115 public static function del($id) {
116 $dao = new CRM_Core_DAO_WordReplacement();
117 $dao->id = $id;
118 $dao->delete();
119 if (!isset($params['options']) || CRM_Utils_Array::value('wp-rebuild', $params['options'], TRUE)) {
120 self::rebuild();
121 }
122 return $dao;
123 }
124
125 /**
126 * Get all word-replacements in the form of an array.
127 *
128 * @param int $id
129 * Domain ID.
130 *
131 * @return array
132 * @see civicrm_domain.locale_custom_strings
133 */
134 public static function getAllAsConfigArray($id) {
135 $query = "
136 SELECT find_word,replace_word,is_active,match_type
137 FROM civicrm_word_replacement
138 WHERE domain_id = %1
139 ";
140 $params = [1 => [$id, 'Integer']];
141
142 $dao = CRM_Core_DAO::executeQuery($query, $params);
143
144 $overrides = [];
145
146 while ($dao->fetch()) {
147 if ($dao->is_active == 1) {
148 $overrides['enabled'][$dao->match_type][$dao->find_word] = $dao->replace_word;
149 }
150 else {
151 $overrides['disabled'][$dao->match_type][$dao->find_word] = $dao->replace_word;
152 }
153 }
154 $config = CRM_Core_Config::singleton();
155 $domain = new CRM_Core_DAO_Domain();
156 $domain->find(TRUE);
157
158 // So. Weird. Some bizarre/probably-broken multi-lingual thing where
159 // data isn't really stored in civicrm_word_replacements. Probably
160 // shouldn't exist.
161 $stringOverride = self::_getLocaleCustomStrings($id);
162 $stringOverride[$config->lcMessages] = $overrides;
163
164 return $stringOverride;
165 }
166
167 /**
168 * Rebuild.
169 *
170 * @param bool $clearCaches
171 *
172 * @return bool
173 */
174 public static function rebuild($clearCaches = TRUE) {
175 $id = CRM_Core_Config::domainID();
176 self::_setLocaleCustomStrings($id, self::getAllAsConfigArray($id));
177
178 // Partially mitigate the inefficiency introduced in CRM-13187 by doing this conditionally
179 if ($clearCaches) {
180 // Reset navigation
181 CRM_Core_BAO_Navigation::resetNavigation();
182 // Clear js localization
183 CRM_Core_Resources::singleton()->flushStrings()->resetCacheCode();
184 }
185
186 return TRUE;
187 }
188
189 /**
190 * Get word replacements for the api.
191 *
192 * Get all the word-replacements stored in config-arrays for the
193 * configured language, and convert them to params for the
194 * WordReplacement.create API.
195 *
196 * Note: This function is duplicated in CRM_Core_BAO_WordReplacement and
197 * CRM_Upgrade_Incremental_php_FourFour to ensure that the incremental upgrade
198 * step behaves consistently even as the BAO evolves in future versions.
199 * However, if there's a bug in here prior to 4.4.0, we should apply the
200 * bug-fix in both places.
201 *
202 * @param bool $rebuildEach
203 * Whether to perform rebuild after each individual API call.
204 *
205 * @return array
206 * Each item is $params for WordReplacement.create
207 * @see CRM_Core_BAO_WordReplacement::convertConfigArraysToAPIParams
208 */
209 public static function getConfigArraysAsAPIParams($rebuildEach) {
210 $settingsResult = civicrm_api3('Setting', 'get', [
211 'return' => 'lcMessages',
212 ]);
213 $returnValues = CRM_Utils_Array::first($settingsResult['values']);
214 $lang = $returnValues['lcMessages'];
215
216 $wordReplacementCreateParams = [];
217 // get all domains
218 $result = civicrm_api3('domain', 'get', [
219 'return' => ['locale_custom_strings'],
220 ]);
221 if (!empty($result["values"])) {
222 foreach ($result["values"] as $value) {
223 $params = [];
224 $params["domain_id"] = $value["id"];
225 $params["options"] = ['wp-rebuild' => $rebuildEach];
226 // Unserialize word match string.
227 $localeCustomArray = CRM_Utils_String::unserialize($value["locale_custom_strings"]);
228 if (!empty($localeCustomArray)) {
229 $wordMatchArray = [];
230 // Only return the replacement strings of the current language,
231 // otherwise some replacements will be duplicated, which will
232 // lead to undesired results, like CRM-19683.
233 $localCustomData = $localeCustomArray[$lang];
234 // Traverse status array "enabled" "disabled"
235 foreach ($localCustomData as $status => $matchTypes) {
236 $params["is_active"] = $status == "enabled";
237 // Traverse Match Type array "wildcardMatch" "exactMatch"
238 foreach ($matchTypes as $matchType => $words) {
239 $params["match_type"] = $matchType;
240 foreach ($words as $word => $replace) {
241 $params["find_word"] = $word;
242 $params["replace_word"] = $replace;
243 $wordReplacementCreateParams[] = $params;
244 }
245 }
246 }
247 }
248 }
249 }
250 return $wordReplacementCreateParams;
251 }
252
253 /**
254 * Rebuild word replacements.
255 *
256 * Get all the word-replacements stored in config-arrays
257 * and write them out as records in civicrm_word_replacement.
258 *
259 * Note: This function is duplicated in CRM_Core_BAO_WordReplacement and
260 * CRM_Upgrade_Incremental_php_FourFour to ensure that the incremental upgrade
261 * step behaves consistently even as the BAO evolves in future versions.
262 * However, if there's a bug in here prior to 4.4.0, we should apply the
263 * bug-fix in both places.
264 */
265 public static function rebuildWordReplacementTable() {
266 civicrm_api3('word_replacement', 'replace', [
267 'options' => ['match' => ['domain_id', 'find_word']],
268 'values' => self::getConfigArraysAsAPIParams(FALSE),
269 ]);
270 CRM_Core_BAO_WordReplacement::rebuild();
271 }
272
273 /**
274 * Get WordReplacements for a locale.
275 *
276 * @param string $locale
277 * @param int $domainId
278 *
279 * @return array
280 * List of word replacements (enabled/disabled) for the given locale.
281 */
282 public static function getLocaleCustomStrings($locale, $domainId = NULL) {
283 if ($domainId === NULL) {
284 $domainId = CRM_Core_Config::domainID();
285 }
286
287 return CRM_Utils_Array::value($locale, self::_getLocaleCustomStrings($domainId));
288 }
289
290 /**
291 * Get custom locale strings.
292 *
293 * @param int $domainId
294 *
295 * @return array|mixed
296 */
297 private static function _getLocaleCustomStrings($domainId) {
298 // TODO: Would it be worthwhile using memcache here?
299 $domain = CRM_Core_DAO::executeQuery('SELECT locale_custom_strings FROM civicrm_domain WHERE id = %1', [
300 1 => [$domainId, 'Integer'],
301 ]);
302 while ($domain->fetch()) {
303 return empty($domain->locale_custom_strings) ? [] : CRM_Utils_String::unserialize($domain->locale_custom_strings);
304 }
305 }
306
307 /**
308 * Set locale strings.
309 *
310 * @param string $locale
311 * @param array $values
312 * @param int $domainId
313 */
314 public static function setLocaleCustomStrings($locale, $values, $domainId = NULL) {
315 if ($domainId === NULL) {
316 $domainId = CRM_Core_Config::domainID();
317 }
318
319 $lcs = self::_getLocaleCustomStrings($domainId);
320 $lcs[$locale] = $values;
321
322 self::_setLocaleCustomStrings($domainId, $lcs);
323 }
324
325 /**
326 * Set locale strings.
327 *
328 * @param int $domainId
329 * @param string $lcs
330 */
331 private static function _setLocaleCustomStrings($domainId, $lcs) {
332 CRM_Core_DAO::executeQuery("UPDATE civicrm_domain SET locale_custom_strings = %1 WHERE id = %2", [
333 1 => [serialize($lcs), 'String'],
334 2 => [$domainId, 'Integer'],
335 ]);
336 }
337
338 }