Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
6a488035 | 5 | | | |
bc77d7c0 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 | | |
6a488035 | 9 | +--------------------------------------------------------------------+ |
d25dd0ee | 10 | */ |
6a488035 TO |
11 | |
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | */ |
17 | ||
18 | /** | |
ce064e4f | 19 | * This class contains all the function that are called using AJAX. |
6a488035 TO |
20 | */ |
21 | class CRM_Admin_Page_AJAX { | |
22 | ||
23 | /** | |
b30809e4 | 24 | * Outputs menubar data (json format) for the current user. |
73538697 | 25 | */ |
b30809e4 CW |
26 | public static function navMenu() { |
27 | if (CRM_Core_Session::getLoggedInContactID()) { | |
28 | ||
29 | $menu = CRM_Core_BAO_Navigation::buildNavigationTree(); | |
30 | CRM_Core_BAO_Navigation::buildHomeMenu($menu); | |
31 | CRM_Utils_Hook::navigationMenu($menu); | |
32 | CRM_Core_BAO_Navigation::fixNavigationMenu($menu); | |
33 | CRM_Core_BAO_Navigation::orderByWeight($menu); | |
34 | CRM_Core_BAO_Navigation::filterByPermission($menu); | |
35 | self::formatMenuItems($menu); | |
36 | ||
37 | $output = [ | |
38 | 'menu' => $menu, | |
39 | 'search' => CRM_Utils_Array::makeNonAssociative(self::getSearchOptions()), | |
40 | ]; | |
41 | // Encourage browsers to cache for a long time - 1 year | |
42 | $ttl = 60 * 60 * 24 * 364; | |
43 | CRM_Utils_System::setHttpHeader('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + $ttl)); | |
44 | CRM_Utils_System::setHttpHeader('Cache-Control', "max-age=$ttl, public"); | |
45 | CRM_Utils_System::setHttpHeader('Content-Type', 'application/json'); | |
46 | print (json_encode($output)); | |
73538697 | 47 | } |
0a15daa2 | 48 | CRM_Utils_System::civiExit(); |
73538697 CW |
49 | } |
50 | ||
b30809e4 CW |
51 | /** |
52 | * @param array $menu | |
53 | */ | |
54 | public static function formatMenuItems(&$menu) { | |
55 | foreach ($menu as $key => &$item) { | |
56 | $props = $item['attributes']; | |
57 | unset($item['attributes']); | |
58 | if (!empty($props['separator'])) { | |
59 | $item['separator'] = ($props['separator'] == 1 ? 'bottom' : 'top'); | |
60 | } | |
61 | if (!empty($props['icon'])) { | |
62 | $item['icon'] = $props['icon']; | |
63 | } | |
64 | if (!empty($props['attr'])) { | |
65 | $item['attr'] = $props['attr']; | |
66 | } | |
67 | if (!empty($props['url'])) { | |
68 | $item['url'] = CRM_Utils_System::evalUrl(CRM_Core_BAO_Navigation::makeFullyFormedUrl($props['url'])); | |
69 | } | |
70 | if (!empty($props['label'])) { | |
71 | $item['label'] = ts($props['label'], ['context' => 'menu']); | |
72 | } | |
73 | $item['name'] = !empty($props['name']) ? $props['name'] : CRM_Utils_String::munge(CRM_Utils_Array::value('label', $props)); | |
74 | if (!empty($item['child'])) { | |
75 | self::formatMenuItems($item['child']); | |
76 | } | |
77 | } | |
78 | $menu = array_values($menu); | |
79 | } | |
80 | ||
4235341b | 81 | public static function getSearchOptions() { |
4e086328 | 82 | $searchOptions = Civi::settings()->get('quicksearch_options'); |
b30809e4 CW |
83 | $labels = CRM_Core_SelectValues::quicksearchOptions(); |
84 | $result = []; | |
85 | foreach ($searchOptions as $key) { | |
86 | $label = $labels[$key]; | |
4235341b | 87 | if (strpos($key, 'custom_') === 0) { |
b30809e4 CW |
88 | $key = 'custom_' . CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField', substr($key, 7), 'id', 'name'); |
89 | $label = array_slice(explode(': ', $label, 2), -1); | |
4235341b | 90 | } |
b30809e4 | 91 | $result[$key] = $label; |
4235341b | 92 | } |
b30809e4 | 93 | return $result; |
4235341b CW |
94 | } |
95 | ||
6a488035 | 96 | /** |
ce064e4f | 97 | * Process drag/move action for menu tree. |
6a488035 | 98 | */ |
00be9182 | 99 | public static function menuTree() { |
73538697 | 100 | CRM_Core_BAO_Navigation::processNavigation($_GET); |
6a488035 TO |
101 | } |
102 | ||
103 | /** | |
ce064e4f | 104 | * Build status message while enabling/ disabling various objects. |
6a488035 | 105 | */ |
00be9182 | 106 | public static function getStatusMsg() { |
02fc859b | 107 | require_once 'api/v3/utils.php'; |
353ffa53 | 108 | $recordID = CRM_Utils_Type::escape($_GET['id'], 'Integer'); |
12798ddc | 109 | $entity = CRM_Utils_Type::escape($_GET['entity'], 'String'); |
be2fb01f | 110 | $ret = []; |
6a488035 | 111 | |
4d17a233 | 112 | if ($recordID && $entity && $recordBAO = _civicrm_api3_get_BAO($entity)) { |
6a488035 TO |
113 | switch ($recordBAO) { |
114 | case 'CRM_Core_BAO_UFGroup': | |
6a488035 | 115 | $method = 'getUFJoinRecord'; |
be2fb01f CW |
116 | $result = [$recordBAO, $method]; |
117 | $ufJoin = call_user_func_array(($result), [$recordID, TRUE]); | |
6a488035 | 118 | if (!empty($ufJoin)) { |
be2fb01f | 119 | $ret['content'] = ts('This profile is currently used for %1.', [1 => implode(', ', $ufJoin)]) . ' <br/><br/>' . ts('If you disable the profile - it will be removed from these forms and/or modules. Do you want to continue?'); |
6a488035 TO |
120 | } |
121 | else { | |
4d17a233 | 122 | $ret['content'] = ts('Are you sure you want to disable this profile?'); |
6a488035 TO |
123 | } |
124 | break; | |
125 | ||
9da8dc8c | 126 | case 'CRM_Price_BAO_PriceSet': |
9da8dc8c | 127 | $usedBy = CRM_Price_BAO_PriceSet::getUsedBy($recordID); |
128 | $priceSet = CRM_Price_BAO_PriceSet::getTitle($recordID); | |
6a488035 TO |
129 | |
130 | if (!CRM_Utils_System::isNull($usedBy)) { | |
131 | $template = CRM_Core_Smarty::singleton(); | |
132 | $template->assign('usedBy', $usedBy); | |
be2fb01f | 133 | $comps = [ |
6a488035 TO |
134 | 'Event' => 'civicrm_event', |
135 | 'Contribution' => 'civicrm_contribution_page', | |
21dfd5f5 | 136 | 'EventTemplate' => 'civicrm_event_template', |
be2fb01f CW |
137 | ]; |
138 | $contexts = []; | |
6a488035 TO |
139 | foreach ($comps as $name => $table) { |
140 | if (array_key_exists($table, $usedBy)) { | |
141 | $contexts[] = $name; | |
142 | } | |
143 | } | |
144 | $template->assign('contexts', $contexts); | |
145 | ||
4d17a233 | 146 | $ret['illegal'] = TRUE; |
353ffa53 | 147 | $table = $template->fetch('CRM/Price/Page/table.tpl'); |
be2fb01f | 148 | $ret['content'] = ts('Unable to disable the \'%1\' price set - it is currently in use by one or more active events, contribution pages or contributions.', [ |
0d48f1cc TO |
149 | 1 => $priceSet, |
150 | ]) . "<br/> $table"; | |
6a488035 TO |
151 | } |
152 | else { | |
be2fb01f | 153 | $ret['content'] = ts('Are you sure you want to disable \'%1\' Price Set?', [1 => $priceSet]); |
6a488035 TO |
154 | } |
155 | break; | |
156 | ||
157 | case 'CRM_Event_BAO_Event': | |
4d17a233 | 158 | $ret['content'] = ts('Are you sure you want to disable this Event?'); |
6a488035 TO |
159 | break; |
160 | ||
161 | case 'CRM_Core_BAO_UFField': | |
4d17a233 | 162 | $ret['content'] = ts('Are you sure you want to disable this CiviCRM Profile field?'); |
6a488035 TO |
163 | break; |
164 | ||
37828d4f | 165 | case 'CRM_Contribute_BAO_Product': |
4d17a233 | 166 | $ret['content'] = ts('Are you sure you want to disable this premium? This action will remove the premium from any contribution pages that currently offer it. However it will not delete the premium record - so you can re-enable it and add it back to your contribution page(s) at a later time.'); |
6a488035 TO |
167 | break; |
168 | ||
6e4cdf9c CW |
169 | case 'CRM_Contact_BAO_Relationship': |
170 | $ret['content'] = ts('Are you sure you want to disable this relationship?'); | |
171 | break; | |
172 | ||
6a488035 | 173 | case 'CRM_Contact_BAO_RelationshipType': |
4d17a233 | 174 | $ret['content'] = ts('Are you sure you want to disable this relationship type?') . '<br/><br/>' . ts('Users will no longer be able to select this value when adding or editing relationships between contacts.'); |
6a488035 TO |
175 | break; |
176 | ||
7b3622bf | 177 | case 'CRM_Financial_BAO_FinancialType': |
4d17a233 | 178 | $ret['content'] = ts('Are you sure you want to disable this financial type?'); |
6a488035 | 179 | break; |
8ef12e64 | 180 | |
7b3622bf PN |
181 | case 'CRM_Financial_BAO_FinancialAccount': |
182 | if (!CRM_Financial_BAO_FinancialAccount::getARAccounts($recordID)) { | |
4d17a233 CW |
183 | $ret['illegal'] = TRUE; |
184 | $ret['content'] = ts('The selected financial account cannot be disabled because at least one Accounts Receivable type account is required (to ensure that accounting transactions are in balance).'); | |
7b3622bf PN |
185 | } |
186 | else { | |
4d17a233 | 187 | $ret['content'] = ts('Are you sure you want to disable this financial account?'); |
7b3622bf PN |
188 | } |
189 | break; | |
6a488035 | 190 | |
8ef12e64 | 191 | case 'CRM_Financial_BAO_PaymentProcessor': |
4d17a233 | 192 | $ret['content'] = ts('Are you sure you want to disable this payment processor?') . ' <br/><br/>' . ts('Users will no longer be able to select this value when adding or editing transaction pages.'); |
6a488035 TO |
193 | break; |
194 | ||
195 | case 'CRM_Financial_BAO_PaymentProcessorType': | |
4d17a233 | 196 | $ret['content'] = ts('Are you sure you want to disable this payment processor type?'); |
6a488035 TO |
197 | break; |
198 | ||
199 | case 'CRM_Core_BAO_LocationType': | |
4d17a233 | 200 | $ret['content'] = ts('Are you sure you want to disable this location type?') . ' <br/><br/>' . ts('Users will no longer be able to select this value when adding or editing contact locations.'); |
6a488035 TO |
201 | break; |
202 | ||
203 | case 'CRM_Event_BAO_ParticipantStatusType': | |
4d17a233 | 204 | $ret['content'] = ts('Are you sure you want to disable this Participant Status?') . '<br/><br/> ' . ts('Users will no longer be able to select this value when adding or editing Participant Status.'); |
6a488035 TO |
205 | break; |
206 | ||
4825de4a | 207 | case 'CRM_Mailing_BAO_MailingComponent': |
4d17a233 | 208 | $ret['content'] = ts('Are you sure you want to disable this component?'); |
6a488035 TO |
209 | break; |
210 | ||
211 | case 'CRM_Core_BAO_CustomField': | |
4d17a233 | 212 | $ret['content'] = ts('Are you sure you want to disable this custom data field?'); |
6a488035 TO |
213 | break; |
214 | ||
215 | case 'CRM_Core_BAO_CustomGroup': | |
4d17a233 | 216 | $ret['content'] = ts('Are you sure you want to disable this custom data group? Any profile fields that are linked to custom fields of this group will be disabled.'); |
6a488035 TO |
217 | break; |
218 | ||
c6327d7d | 219 | case 'CRM_Core_BAO_MessageTemplate': |
4d17a233 | 220 | $ret['content'] = ts('Are you sure you want to disable this message tempate?'); |
6a488035 TO |
221 | break; |
222 | ||
223 | case 'CRM_ACL_BAO_ACL': | |
4d17a233 | 224 | $ret['content'] = ts('Are you sure you want to disable this ACL?'); |
6a488035 TO |
225 | break; |
226 | ||
227 | case 'CRM_ACL_BAO_EntityRole': | |
4d17a233 | 228 | $ret['content'] = ts('Are you sure you want to disable this ACL Role Assignment?'); |
6a488035 TO |
229 | break; |
230 | ||
231 | case 'CRM_Member_BAO_MembershipType': | |
4d17a233 | 232 | $ret['content'] = ts('Are you sure you want to disable this membership type?'); |
6a488035 TO |
233 | break; |
234 | ||
235 | case 'CRM_Member_BAO_MembershipStatus': | |
4d17a233 | 236 | $ret['content'] = ts('Are you sure you want to disable this membership status rule?'); |
6a488035 TO |
237 | break; |
238 | ||
9da8dc8c | 239 | case 'CRM_Price_BAO_PriceField': |
4d17a233 | 240 | $ret['content'] = ts('Are you sure you want to disable this price field?'); |
6a488035 TO |
241 | break; |
242 | ||
243 | case 'CRM_Contact_BAO_Group': | |
4d17a233 | 244 | $ret['content'] = ts('Are you sure you want to disable this Group?'); |
240c0ebd | 245 | $ret['content'] .= '<br /><br /><strong>' . ts('WARNING - Disabling this group will disable all the child groups associated if any.') . '</strong>'; |
6a488035 TO |
246 | break; |
247 | ||
248 | case 'CRM_Core_BAO_OptionGroup': | |
4d17a233 | 249 | $ret['content'] = ts('Are you sure you want to disable this Option?'); |
6a488035 TO |
250 | break; |
251 | ||
252 | case 'CRM_Contact_BAO_ContactType': | |
4d17a233 | 253 | $ret['content'] = ts('Are you sure you want to disable this Contact Type?'); |
6a488035 TO |
254 | break; |
255 | ||
256 | case 'CRM_Core_BAO_OptionValue': | |
6a488035 | 257 | $label = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $recordID, 'label'); |
be2fb01f | 258 | $ret['content'] = ts('Are you sure you want to disable the \'%1\' option ?', [1 => $label]); |
4d17a233 | 259 | $ret['content'] .= '<br /><br />' . ts('WARNING - Disabling an option which has been assigned to existing records will result in that option being cleared when the record is edited.'); |
6a488035 TO |
260 | break; |
261 | ||
262 | case 'CRM_Contribute_BAO_ContributionRecur': | |
263 | $recurDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($recordID); | |
4d17a233 CW |
264 | $ret['content'] = ts('Are you sure you want to mark this recurring contribution as cancelled?'); |
265 | $ret['content'] .= '<br /><br /><strong>' . ts('WARNING - This action sets the CiviCRM recurring contribution status to Cancelled, but does NOT send a cancellation request to the payment processor. You will need to ensure that this recurring payment (subscription) is cancelled by the payment processor.') . '</strong>'; | |
6a488035 | 266 | if ($recurDetails->membership_id) { |
4d17a233 | 267 | $ret['content'] .= '<br /><br /><strong>' . ts('This recurring contribution is linked to an auto-renew membership. If you cancel it, the associated membership will no longer renew automatically. However, the current membership status will not be affected.') . '</strong>'; |
6a488035 TO |
268 | } |
269 | break; | |
8ef12e64 | 270 | |
6a488035 | 271 | default: |
4d17a233 | 272 | $ret['content'] = ts('Are you sure you want to disable this record?'); |
6a488035 TO |
273 | break; |
274 | } | |
275 | } | |
4d17a233 | 276 | else { |
be2fb01f | 277 | $ret = ['status' => 'error', 'content' => 'Error: Unknown entity type.', 'illegal' => TRUE]; |
4d17a233 CW |
278 | } |
279 | CRM_Core_Page_AJAX::returnJsonResponse($ret); | |
6a488035 TO |
280 | } |
281 | ||
f8b84800 | 282 | /** |
283 | * Get a list of mappings. | |
284 | * | |
285 | * This appears to be only used by scheduled reminders. | |
286 | */ | |
62d3ee27 | 287 | public static function mappingList() { |
581c7be2 | 288 | if (empty($_GET['mappingID'])) { |
be2fb01f | 289 | CRM_Utils_JSON::output(['status' => 'error', 'error_msg' => 'required params missing.']); |
6a488035 TO |
290 | } |
291 | ||
0905ee5d | 292 | $mapping = CRM_Core_BAO_ActionSchedule::getMapping($_GET['mappingID']); |
be2fb01f | 293 | $dateFieldLabels = $mapping ? $mapping->getDateFields() : []; |
9d97a648 TO |
294 | |
295 | // The UX here is quirky -- for "Activity" types, there's a simple drop "Recipients" | |
296 | // dropdown which is always displayed. For other types, the "Recipients" drop down is | |
297 | // conditional upon the weird isLimit ('Limit To / Also Include / Neither') dropdown. | |
298 | $noThanksJustKidding = !$_GET['isLimit']; | |
299 | if ($mapping instanceof CRM_Activity_ActionMapping || !$noThanksJustKidding) { | |
be2fb01f | 300 | $entityRecipientLabels = $mapping ? ($mapping->getRecipientTypes() + CRM_Core_BAO_ActionSchedule::getAdditionalRecipients()) : []; |
9d97a648 TO |
301 | } |
302 | else { | |
303 | $entityRecipientLabels = CRM_Core_BAO_ActionSchedule::getAdditionalRecipients(); | |
304 | } | |
0905ee5d | 305 | $recipientMapping = array_combine(array_keys($entityRecipientLabels), array_keys($entityRecipientLabels)); |
6a488035 | 306 | |
be2fb01f | 307 | $output = [ |
dde482e0 CW |
308 | 'sel4' => CRM_Utils_Array::makeNonAssociative($dateFieldLabels), |
309 | 'sel5' => CRM_Utils_Array::makeNonAssociative($entityRecipientLabels), | |
0905ee5d | 310 | 'recipientMapping' => $recipientMapping, |
be2fb01f | 311 | ]; |
6a488035 | 312 | |
581c7be2 | 313 | CRM_Utils_JSON::output($output); |
6a488035 TO |
314 | } |
315 | ||
bf2ce887 TO |
316 | /** |
317 | * (Scheduled Reminders) Get the list of possible recipient filters. | |
318 | * | |
319 | * Ex: GET /civicrm/ajax/recipientListing?mappingID=contribpage&recipientType= | |
320 | */ | |
321 | public static function recipientListing() { | |
be2fb01f CW |
322 | $mappingID = filter_input(INPUT_GET, 'mappingID', FILTER_VALIDATE_REGEXP, [ |
323 | 'options' => [ | |
bf2ce887 | 324 | 'regexp' => '/^[a-zA-Z0-9_\-]+$/', |
be2fb01f CW |
325 | ], |
326 | ]); | |
327 | $recipientType = filter_input(INPUT_GET, 'recipientType', FILTER_VALIDATE_REGEXP, [ | |
328 | 'options' => [ | |
bf2ce887 | 329 | 'regexp' => '/^[a-zA-Z0-9_\-]+$/', |
be2fb01f CW |
330 | ], |
331 | ]); | |
bf2ce887 | 332 | |
be2fb01f | 333 | CRM_Utils_JSON::output([ |
dde482e0 | 334 | 'recipients' => CRM_Utils_Array::makeNonAssociative(CRM_Core_BAO_ActionSchedule::getRecipientListing($mappingID, $recipientType)), |
be2fb01f | 335 | ]); |
bf2ce887 TO |
336 | } |
337 | ||
d3cbd0a5 CW |
338 | /** |
339 | * Outputs one branch in the tag tree | |
340 | * | |
341 | * Used by jstree to incrementally load tags | |
342 | */ | |
343 | public static function getTagTree() { | |
2975f0aa | 344 | $parent = CRM_Utils_Type::escape(($_GET['parent_id'] ?? 0), 'Integer'); |
6e80ee11 | 345 | $substring = CRM_Utils_Type::escape(CRM_Utils_Array::value('str', $_GET), 'String'); |
be2fb01f | 346 | $result = []; |
d3cbd0a5 | 347 | |
be2fb01f | 348 | $whereClauses = ['is_tagset <> 1']; |
97dcf1d8 | 349 | $orderColumn = 'name'; |
dfe61fcf | 350 | |
351 | // fetch all child tags in Array('parent_tag' => array('child_tag_1', 'child_tag_2', ...)) format | |
6e80ee11 | 352 | $childTagIDs = CRM_Core_BAO_Tag::getChildTags($substring); |
353 | $parentIDs = array_keys($childTagIDs); | |
354 | ||
97dcf1d8 | 355 | if ($parent) { |
356 | $whereClauses[] = "parent_id = $parent"; | |
357 | } | |
358 | elseif ($substring) { | |
6e80ee11 | 359 | $whereClauses['substring'] = " name LIKE '%$substring%' "; |
360 | if (!empty($parentIDs)) { | |
97dcf1d8 | 361 | $whereClauses['substring'] = sprintf(" %s OR id IN (%s) ", $whereClauses['substring'], implode(',', $parentIDs)); |
6e80ee11 | 362 | } |
97dcf1d8 | 363 | $orderColumn = 'id'; |
364 | } | |
365 | else { | |
366 | $whereClauses[] = "parent_id IS NULL"; | |
6e80ee11 | 367 | } |
368 | ||
369 | $dao = CRM_Utils_SQL_Select::from('civicrm_tag') | |
62d3ee27 SL |
370 | ->where($whereClauses) |
371 | ->groupBy('id') | |
372 | ->orderBy($orderColumn) | |
373 | ->execute(); | |
dfe61fcf | 374 | |
d3cbd0a5 | 375 | while ($dao->fetch()) { |
6e80ee11 | 376 | if (!empty($substring)) { |
377 | $result[] = $dao->id; | |
378 | if (!empty($childTagIDs[$dao->id])) { | |
379 | $result = array_merge($result, $childTagIDs[$dao->id]); | |
380 | } | |
381 | } | |
382 | else { | |
91768280 | 383 | $hasChildTags = !empty($childTagIDs[$dao->id]); |
6e80ee11 | 384 | $usedFor = (array) explode(',', $dao->used_for); |
28dd94bd | 385 | $tag = [ |
6e80ee11 | 386 | 'id' => $dao->id, |
387 | 'text' => $dao->name, | |
28dd94bd | 388 | 'a_attr' => [ |
6e80ee11 | 389 | 'class' => 'crm-tag-item', |
28dd94bd | 390 | ], |
6e80ee11 | 391 | 'children' => $hasChildTags, |
28dd94bd | 392 | 'data' => [ |
6e80ee11 | 393 | 'description' => (string) $dao->description, |
394 | 'is_selectable' => (bool) $dao->is_selectable, | |
395 | 'is_reserved' => (bool) $dao->is_reserved, | |
396 | 'used_for' => $usedFor, | |
397 | 'color' => $dao->color ? $dao->color : '#ffffff', | |
28dd94bd CW |
398 | 'usages' => civicrm_api3('EntityTag', 'getcount', [ |
399 | 'entity_table' => ['IN' => $usedFor], | |
6e80ee11 | 400 | 'tag_id' => $dao->id, |
28dd94bd CW |
401 | ]), |
402 | ], | |
403 | ]; | |
404 | if ($dao->description || $dao->is_reserved) { | |
405 | $tag['li_attr']['title'] = ((string) $dao->description) . ($dao->is_reserved ? ' (*' . ts('Reserved') . ')' : ''); | |
406 | } | |
407 | if ($dao->is_reserved) { | |
408 | $tag['li_attr']['class'] = 'is-reserved'; | |
409 | } | |
410 | if ($dao->color) { | |
411 | $tag['a_attr']['style'] = "background-color: {$dao->color}; color: " . CRM_Utils_Color::getContrast($dao->color); | |
412 | } | |
413 | $result[] = $tag; | |
d3cbd0a5 | 414 | } |
d3cbd0a5 CW |
415 | } |
416 | ||
97dcf1d8 | 417 | if ($substring) { |
418 | $result = array_values(array_unique($result)); | |
419 | } | |
420 | ||
dfe61fcf | 421 | if (!empty($_REQUEST['is_unit_test'])) { |
422 | return $result; | |
423 | } | |
424 | ||
d3cbd0a5 CW |
425 | CRM_Utils_JSON::output($result); |
426 | } | |
427 | ||
6a488035 | 428 | } |