Deprecate redundant array util function
[civicrm-core.git] / CRM / Admin / Page / AJAX.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2018 |
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 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2018
32 */
33
34 /**
35 * This class contains all the function that are called using AJAX.
36 */
37 class CRM_Admin_Page_AJAX {
38
39 /**
40 * CRM-12337 Output navigation menu as executable javascript.
41 *
42 * @see smarty_function_crmNavigationMenu
43 */
44 public static function getNavigationMenu() {
45 $contactID = CRM_Core_Session::singleton()->get('userID');
46 if ($contactID) {
47 CRM_Core_Page_AJAX::setJsHeaders();
48 $smarty = CRM_Core_Smarty::singleton();
49 $smarty->assign('includeEmail', civicrm_api3('setting', 'getvalue', array('name' => 'includeEmailInName', 'group' => 'Search Preferences')));
50 print $smarty->fetchWith('CRM/common/navigation.js.tpl', array(
51 'navigation' => CRM_Core_BAO_Navigation::createNavigation($contactID),
52 ));
53 }
54 CRM_Utils_System::civiExit();
55 }
56
57 /**
58 * Process drag/move action for menu tree.
59 */
60 public static function menuTree() {
61 CRM_Core_BAO_Navigation::processNavigation($_GET);
62 }
63
64 /**
65 * Build status message while enabling/ disabling various objects.
66 */
67 public static function getStatusMsg() {
68 require_once 'api/v3/utils.php';
69 $recordID = CRM_Utils_Type::escape($_GET['id'], 'Integer');
70 $entity = CRM_Utils_Type::escape($_GET['entity'], 'String');
71 $ret = array();
72
73 if ($recordID && $entity && $recordBAO = _civicrm_api3_get_BAO($entity)) {
74 switch ($recordBAO) {
75 case 'CRM_Core_BAO_UFGroup':
76 $method = 'getUFJoinRecord';
77 $result = array($recordBAO, $method);
78 $ufJoin = call_user_func_array(($result), array($recordID, TRUE));
79 if (!empty($ufJoin)) {
80 $ret['content'] = ts('This profile is currently used for %1.', array(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?');
81 }
82 else {
83 $ret['content'] = ts('Are you sure you want to disable this profile?');
84 }
85 break;
86
87 case 'CRM_Price_BAO_PriceSet':
88 $usedBy = CRM_Price_BAO_PriceSet::getUsedBy($recordID);
89 $priceSet = CRM_Price_BAO_PriceSet::getTitle($recordID);
90
91 if (!CRM_Utils_System::isNull($usedBy)) {
92 $template = CRM_Core_Smarty::singleton();
93 $template->assign('usedBy', $usedBy);
94 $comps = array(
95 'Event' => 'civicrm_event',
96 'Contribution' => 'civicrm_contribution_page',
97 'EventTemplate' => 'civicrm_event_template',
98 );
99 $contexts = array();
100 foreach ($comps as $name => $table) {
101 if (array_key_exists($table, $usedBy)) {
102 $contexts[] = $name;
103 }
104 }
105 $template->assign('contexts', $contexts);
106
107 $ret['illegal'] = TRUE;
108 $table = $template->fetch('CRM/Price/Page/table.tpl');
109 $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.', array(
110 1 => $priceSet,
111 )) . "<br/> $table";
112 }
113 else {
114 $ret['content'] = ts('Are you sure you want to disable \'%1\' Price Set?', array(1 => $priceSet));
115 }
116 break;
117
118 case 'CRM_Event_BAO_Event':
119 $ret['content'] = ts('Are you sure you want to disable this Event?');
120 break;
121
122 case 'CRM_Core_BAO_UFField':
123 $ret['content'] = ts('Are you sure you want to disable this CiviCRM Profile field?');
124 break;
125
126 case 'CRM_Contribute_BAO_Product':
127 $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.');
128 break;
129
130 case 'CRM_Contact_BAO_Relationship':
131 $ret['content'] = ts('Are you sure you want to disable this relationship?');
132 break;
133
134 case 'CRM_Contact_BAO_RelationshipType':
135 $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.');
136 break;
137
138 case 'CRM_Financial_BAO_FinancialType':
139 $ret['content'] = ts('Are you sure you want to disable this financial type?');
140 break;
141
142 case 'CRM_Financial_BAO_FinancialAccount':
143 if (!CRM_Financial_BAO_FinancialAccount::getARAccounts($recordID)) {
144 $ret['illegal'] = TRUE;
145 $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).');
146 }
147 else {
148 $ret['content'] = ts('Are you sure you want to disable this financial account?');
149 }
150 break;
151
152 case 'CRM_Financial_BAO_PaymentProcessor':
153 $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.');
154 break;
155
156 case 'CRM_Financial_BAO_PaymentProcessorType':
157 $ret['content'] = ts('Are you sure you want to disable this payment processor type?');
158 break;
159
160 case 'CRM_Core_BAO_LocationType':
161 $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.');
162 break;
163
164 case 'CRM_Event_BAO_ParticipantStatusType':
165 $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.');
166 break;
167
168 case 'CRM_Mailing_BAO_Component':
169 $ret['content'] = ts('Are you sure you want to disable this component?');
170 break;
171
172 case 'CRM_Core_BAO_CustomField':
173 $ret['content'] = ts('Are you sure you want to disable this custom data field?');
174 break;
175
176 case 'CRM_Core_BAO_CustomGroup':
177 $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.');
178 break;
179
180 case 'CRM_Core_BAO_MessageTemplate':
181 $ret['content'] = ts('Are you sure you want to disable this message tempate?');
182 break;
183
184 case 'CRM_ACL_BAO_ACL':
185 $ret['content'] = ts('Are you sure you want to disable this ACL?');
186 break;
187
188 case 'CRM_ACL_BAO_EntityRole':
189 $ret['content'] = ts('Are you sure you want to disable this ACL Role Assignment?');
190 break;
191
192 case 'CRM_Member_BAO_MembershipType':
193 $ret['content'] = ts('Are you sure you want to disable this membership type?');
194 break;
195
196 case 'CRM_Member_BAO_MembershipStatus':
197 $ret['content'] = ts('Are you sure you want to disable this membership status rule?');
198 break;
199
200 case 'CRM_Price_BAO_PriceField':
201 $ret['content'] = ts('Are you sure you want to disable this price field?');
202 break;
203
204 case 'CRM_Contact_BAO_Group':
205 $ret['content'] = ts('Are you sure you want to disable this Group?');
206 break;
207
208 case 'CRM_Core_BAO_OptionGroup':
209 $ret['content'] = ts('Are you sure you want to disable this Option?');
210 break;
211
212 case 'CRM_Contact_BAO_ContactType':
213 $ret['content'] = ts('Are you sure you want to disable this Contact Type?');
214 break;
215
216 case 'CRM_Core_BAO_OptionValue':
217 $label = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $recordID, 'label');
218 $ret['content'] = ts('Are you sure you want to disable the \'%1\' option ?', array(1 => $label));
219 $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.');
220 break;
221
222 case 'CRM_Contribute_BAO_ContributionRecur':
223 $recurDetails = CRM_Contribute_BAO_ContributionRecur::getSubscriptionDetails($recordID);
224 $ret['content'] = ts('Are you sure you want to mark this recurring contribution as cancelled?');
225 $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>';
226 if ($recurDetails->membership_id) {
227 $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>';
228 }
229 break;
230
231 default:
232 $ret['content'] = ts('Are you sure you want to disable this record?');
233 break;
234 }
235 }
236 else {
237 $ret = array('status' => 'error', 'content' => 'Error: Unknown entity type.', 'illegal' => TRUE);
238 }
239 CRM_Core_Page_AJAX::returnJsonResponse($ret);
240 }
241
242 /**
243 * Get a list of mappings.
244 *
245 * This appears to be only used by scheduled reminders.
246 */
247 static public function mappingList() {
248 if (empty($_GET['mappingID'])) {
249 CRM_Utils_JSON::output(array('status' => 'error', 'error_msg' => 'required params missing.'));
250 }
251
252 $mapping = CRM_Core_BAO_ActionSchedule::getMapping($_GET['mappingID']);
253 $dateFieldLabels = $mapping ? $mapping->getDateFields() : array();
254
255 // The UX here is quirky -- for "Activity" types, there's a simple drop "Recipients"
256 // dropdown which is always displayed. For other types, the "Recipients" drop down is
257 // conditional upon the weird isLimit ('Limit To / Also Include / Neither') dropdown.
258 $noThanksJustKidding = !$_GET['isLimit'];
259 if ($mapping instanceof CRM_Activity_ActionMapping || !$noThanksJustKidding) {
260 $entityRecipientLabels = $mapping ? ($mapping->getRecipientTypes() + CRM_Core_BAO_ActionSchedule::getAdditionalRecipients()) : array();
261 }
262 else {
263 $entityRecipientLabels = CRM_Core_BAO_ActionSchedule::getAdditionalRecipients();
264 }
265 $recipientMapping = array_combine(array_keys($entityRecipientLabels), array_keys($entityRecipientLabels));
266
267 $output = array(
268 'sel4' => CRM_Utils_Array::makeNonAssociative($dateFieldLabels),
269 'sel5' => CRM_Utils_Array::makeNonAssociative($entityRecipientLabels),
270 'recipientMapping' => $recipientMapping,
271 );
272
273 CRM_Utils_JSON::output($output);
274 }
275
276 /**
277 * (Scheduled Reminders) Get the list of possible recipient filters.
278 *
279 * Ex: GET /civicrm/ajax/recipientListing?mappingID=contribpage&recipientType=
280 */
281 public static function recipientListing() {
282 $mappingID = filter_input(INPUT_GET, 'mappingID', FILTER_VALIDATE_REGEXP, array(
283 'options' => array(
284 'regexp' => '/^[a-zA-Z0-9_\-]+$/',
285 ),
286 ));
287 $recipientType = filter_input(INPUT_GET, 'recipientType', FILTER_VALIDATE_REGEXP, array(
288 'options' => array(
289 'regexp' => '/^[a-zA-Z0-9_\-]+$/',
290 ),
291 ));
292
293 CRM_Utils_JSON::output(array(
294 'recipients' => CRM_Utils_Array::makeNonAssociative(CRM_Core_BAO_ActionSchedule::getRecipientListing($mappingID, $recipientType)),
295 ));
296 }
297
298 /**
299 * Outputs one branch in the tag tree
300 *
301 * Used by jstree to incrementally load tags
302 */
303 public static function getTagTree() {
304 $parent = CRM_Utils_Type::escape(CRM_Utils_Array::value('parent_id', $_GET, 0), 'Integer');
305 $substring = CRM_Utils_Type::escape(CRM_Utils_Array::value('str', $_GET), 'String');
306 $result = array();
307
308 $whereClauses = array('is_tagset <> 1');
309 $orderColumn = 'name';
310
311 // fetch all child tags in Array('parent_tag' => array('child_tag_1', 'child_tag_2', ...)) format
312 $childTagIDs = CRM_Core_BAO_Tag::getChildTags($substring);
313 $parentIDs = array_keys($childTagIDs);
314
315 if ($parent) {
316 $whereClauses[] = "parent_id = $parent";
317 }
318 elseif ($substring) {
319 $whereClauses['substring'] = " name LIKE '%$substring%' ";
320 if (!empty($parentIDs)) {
321 $whereClauses['substring'] = sprintf(" %s OR id IN (%s) ", $whereClauses['substring'], implode(',', $parentIDs));
322 }
323 $orderColumn = 'id';
324 }
325 else {
326 $whereClauses[] = "parent_id IS NULL";
327 }
328
329 $dao = CRM_Utils_SQL_Select::from('civicrm_tag')
330 ->where($whereClauses)
331 ->groupBy('id')
332 ->orderBy($orderColumn)
333 ->execute();
334
335 while ($dao->fetch()) {
336 if (!empty($substring)) {
337 $result[] = $dao->id;
338 if (!empty($childTagIDs[$dao->id])) {
339 $result = array_merge($result, $childTagIDs[$dao->id]);
340 }
341 }
342 else {
343 $hasChildTags = empty($childTagIDs[$dao->id]) ? FALSE : TRUE;
344 $usedFor = (array) explode(',', $dao->used_for);
345 $tag = [
346 'id' => $dao->id,
347 'text' => $dao->name,
348 'a_attr' => [
349 'class' => 'crm-tag-item',
350 ],
351 'children' => $hasChildTags,
352 'data' => [
353 'description' => (string) $dao->description,
354 'is_selectable' => (bool) $dao->is_selectable,
355 'is_reserved' => (bool) $dao->is_reserved,
356 'used_for' => $usedFor,
357 'color' => $dao->color ? $dao->color : '#ffffff',
358 'usages' => civicrm_api3('EntityTag', 'getcount', [
359 'entity_table' => ['IN' => $usedFor],
360 'tag_id' => $dao->id,
361 ]),
362 ],
363 ];
364 if ($dao->description || $dao->is_reserved) {
365 $tag['li_attr']['title'] = ((string) $dao->description) . ($dao->is_reserved ? ' (*' . ts('Reserved') . ')' : '');
366 }
367 if ($dao->is_reserved) {
368 $tag['li_attr']['class'] = 'is-reserved';
369 }
370 if ($dao->color) {
371 $tag['a_attr']['style'] = "background-color: {$dao->color}; color: " . CRM_Utils_Color::getContrast($dao->color);
372 }
373 $result[] = $tag;
374 }
375 }
376
377 if ($substring) {
378 $result = array_values(array_unique($result));
379 }
380
381 if (!empty($_REQUEST['is_unit_test'])) {
382 return $result;
383 }
384
385 CRM_Utils_JSON::output($result);
386 }
387
388 }