BAO_Contact - Remove CRM_Utils_Array::value and other unnecessary code
[civicrm-core.git] / CRM / Core / Page / AJAX.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 * $Id$
17 *
18 */
19
20 /**
21 * This is base class for all ajax calls
22 */
23 class CRM_Core_Page_AJAX {
24
25 /**
26 * Call generic ajax forms.
27 *
28 */
29 public static function run() {
30 $className = CRM_Utils_Type::escape($_REQUEST['class_name'], 'String');
31 $type = '';
32 if (!empty($_REQUEST['type'])) {
33 $type = CRM_Utils_Type::escape($_REQUEST['type'], 'String');
34 }
35
36 if (!$className) {
37 CRM_Core_Error::fatal(ts('Invalid className: %1', [1 => $className]));
38 }
39
40 $fnName = NULL;
41 if (isset($_REQUEST['fn_name'])) {
42 $fnName = CRM_Utils_Type::escape($_REQUEST['fn_name'], 'String');
43 }
44
45 if (!self::checkAuthz($type, $className, $fnName)) {
46 CRM_Utils_System::civiExit();
47 }
48
49 switch ($type) {
50 case 'method':
51 call_user_func([$className, $fnName]);
52 break;
53
54 case 'page':
55 case 'class':
56 case '':
57 // FIXME: This is done to maintain current wire protocol, but it might be
58 // simpler to just require different 'types' for pages and forms
59 if (preg_match('/^CRM_[a-zA-Z0-9]+_Page_Inline_/', $className)) {
60 $page = new $className();
61 $page->run();
62 }
63 else {
64 $wrapper = new CRM_Utils_Wrapper();
65 $wrapper->run($className);
66 }
67 break;
68
69 default:
70 CRM_Core_Error::debug_log_message('Unsupported inline request type: ' . var_export($type, TRUE));
71 }
72 CRM_Utils_System::civiExit();
73 }
74
75 /**
76 * Change is_quick_config priceSet to complex.
77 *
78 */
79 public static function setIsQuickConfig() {
80 $id = $context = NULL;
81 if (!empty($_REQUEST['id'])) {
82 $id = CRM_Utils_Type::escape($_REQUEST['id'], 'Integer');
83 }
84
85 $context = CRM_Utils_Request::retrieve('context', 'Alphanumeric');
86
87 // return false if $id is null and
88 // $context is not civicrm_event or civicrm_contribution_page
89 if (!$id || !in_array($context, ['civicrm_event', 'civicrm_contribution_page'])) {
90 return FALSE;
91 }
92 $priceSetId = CRM_Price_BAO_PriceSet::getFor($context, $id, NULL);
93 if ($priceSetId) {
94 $sql = "UPDATE
95 civicrm_price_set cps
96 INNER JOIN civicrm_price_set_entity cpse ON cps.id = cpse.price_set_id
97 INNER JOIN {$context} ce ON cpse.entity_id = ce.id AND ce.id = %1
98 SET cps.is_quick_config = 0, cps.financial_type_id = IF(cps.financial_type_id IS NULL, ce.financial_type_id, cps.financial_type_id)
99 ";
100 CRM_Core_DAO::executeQuery($sql, [1 => [$id, 'Integer']]);
101
102 if ($context == 'civicrm_event') {
103 CRM_Core_BAO_Discount::del($id, $context);
104 }
105 }
106
107 CRM_Utils_JSON::output($priceSetId);
108 }
109
110 /**
111 * Determine whether the request is for a valid class/method name.
112 *
113 * @param string $type
114 * 'method'|'class'|''.
115 * @param string $className
116 * 'Class_Name'.
117 * @param string $fnName
118 * Method name.
119 *
120 * @return bool
121 */
122 public static function checkAuthz($type, $className, $fnName = NULL) {
123 switch ($type) {
124 case 'method':
125 if (!preg_match('/^CRM_[a-zA-Z0-9]+_Page_AJAX$/', $className)) {
126 return FALSE;
127 }
128 if (!preg_match('/^[a-zA-Z0-9]+$/', $fnName)) {
129 return FALSE;
130 }
131
132 // ensure that function exists
133 return method_exists($className, $fnName);
134
135 case 'page':
136 case 'class':
137 case '':
138 if (!preg_match('/^CRM_[a-zA-Z0-9]+_(Page|Form)_Inline_[a-zA-Z0-9]+$/', $className)) {
139 return FALSE;
140 }
141 return class_exists($className);
142
143 default:
144 return FALSE;
145 }
146 }
147
148 /**
149 * Outputs the CiviCRM standard json-formatted page/form response
150 * @param array|string $response
151 */
152 public static function returnJsonResponse($response) {
153 // Allow lazy callers to not wrap content in an array
154 if (is_string($response)) {
155 $response = ['content' => $response];
156 }
157 // Add session variables to response
158 $session = CRM_Core_Session::singleton();
159 $response += [
160 'status' => 'success',
161 'userContext' => htmlspecialchars_decode($session->readUserContext()),
162 'title' => CRM_Utils_System::$title,
163 ];
164 // crmMessages will be automatically handled by our ajax preprocessor
165 // @see js/Common.js
166 if ($session->getStatus(FALSE)) {
167 $response['crmMessages'] = $session->getStatus(TRUE);
168 }
169 $output = json_encode($response);
170
171 // CRM-11831 @see http://www.malsup.com/jquery/form/#file-upload
172 if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
173 CRM_Utils_System::setHttpHeader('Content-Type', 'application/json');
174 }
175 else {
176 $output = "<textarea>$output</textarea>";
177 }
178 echo $output;
179 CRM_Utils_System::civiExit();
180 }
181
182 /**
183 * Set headers appropriate for a js file.
184 *
185 * @param int|null $ttl
186 * Time-to-live (seconds).
187 */
188 public static function setJsHeaders($ttl = NULL) {
189 if ($ttl === NULL) {
190 // Encourage browsers to cache for a long time - 1 year
191 $ttl = 60 * 60 * 24 * 364;
192 }
193 CRM_Utils_System::setHttpHeader('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + $ttl));
194 CRM_Utils_System::setHttpHeader('Content-Type', 'application/javascript');
195 CRM_Utils_System::setHttpHeader('Cache-Control', "max-age=$ttl, public");
196 }
197
198 /**
199 * Set defaults for sort and pager.
200 *
201 * @param int $defaultOffset
202 * @param int $defaultRowCount
203 * @param string $defaultSort
204 * @param string $defaultsortOrder
205 *
206 * @return array
207 */
208 public static function defaultSortAndPagerParams($defaultOffset = 0, $defaultRowCount = 25, $defaultSort = NULL, $defaultsortOrder = 'asc') {
209 $params = [
210 '_raw_values' => [],
211 ];
212
213 $sortMapper = [];
214 if (isset($_GET['columns'])) {
215 foreach ($_GET['columns'] as $key => $value) {
216 $sortMapper[$key] = CRM_Utils_Type::validate($value['data'], 'MysqlColumnNameOrAlias');
217 };
218 }
219
220 $offset = isset($_GET['start']) ? CRM_Utils_Type::validate($_GET['start'], 'Integer') : $defaultOffset;
221 $rowCount = isset($_GET['length']) ? CRM_Utils_Type::validate($_GET['length'], 'Integer') : $defaultRowCount;
222 // Why is the number of order by columns limited to 1?
223 $sort = isset($_GET['order'][0]['column']) ? CRM_Utils_Array::value(CRM_Utils_Type::validate($_GET['order'][0]['column'], 'Integer'), $sortMapper) : $defaultSort;
224 $sortOrder = isset($_GET['order'][0]['dir']) ? CRM_Utils_Type::validate($_GET['order'][0]['dir'], 'MysqlOrderByDirection') : $defaultsortOrder;
225
226 if ($sort) {
227 $params['sortBy'] = "{$sort} {$sortOrder}";
228
229 $params['_raw_values']['sort'][0] = $sort;
230 $params['_raw_values']['order'][0] = $sortOrder;
231 }
232
233 $params['offset'] = $offset;
234 $params['rp'] = $rowCount;
235 $params['page'] = ($offset / $rowCount) + 1;
236
237 return $params;
238 }
239
240 /**
241 * Validate ajax input parameters.
242 *
243 * @param array $requiredParams
244 * @param array $optionalParams
245 *
246 * @return array
247 */
248 public static function validateParams($requiredParams = [], $optionalParams = []) {
249 $params = [];
250
251 foreach ($requiredParams as $param => $type) {
252 $params[$param] = CRM_Utils_Type::validate(CRM_Utils_Array::value($param, $_GET), $type);
253 }
254
255 foreach ($optionalParams as $param => $type) {
256 if (!empty($_GET[$param])) {
257 if (!is_array($_GET[$param])) {
258 $params[$param] = CRM_Utils_Type::validate(CRM_Utils_Array::value($param, $_GET), $type);
259 }
260 else {
261 foreach ($_GET[$param] as $index => $value) {
262 $params[$param][$index] = CRM_Utils_Type::validate($value, $type);
263 }
264 }
265 }
266 }
267
268 return $params;
269
270 }
271
272 }