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