3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
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 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
21 * This is base class for all ajax calls
23 class CRM_Core_Page_AJAX
{
26 * Call generic ajax forms.
29 public static function run() {
30 $className = CRM_Utils_Type
::escape($_REQUEST['class_name'], 'String');
32 if (!empty($_REQUEST['type'])) {
33 $type = CRM_Utils_Type
::escape($_REQUEST['type'], 'String');
37 CRM_Core_Error
::fatal(ts('Invalid className: %1', [1 => $className]));
41 if (isset($_REQUEST['fn_name'])) {
42 $fnName = CRM_Utils_Type
::escape($_REQUEST['fn_name'], 'String');
45 if (!self
::checkAuthz($type, $className, $fnName)) {
46 CRM_Utils_System
::civiExit();
51 call_user_func([$className, $fnName]);
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();
64 $wrapper = new CRM_Utils_Wrapper();
65 $wrapper->run($className);
70 CRM_Core_Error
::debug_log_message('Unsupported inline request type: ' . var_export($type, TRUE));
72 CRM_Utils_System
::civiExit();
76 * Change is_quick_config priceSet to complex.
79 public static function setIsQuickConfig() {
80 $id = $context = NULL;
81 if (!empty($_REQUEST['id'])) {
82 $id = CRM_Utils_Type
::escape($_REQUEST['id'], 'Integer');
85 $context = CRM_Utils_Request
::retrieve('context', 'Alphanumeric');
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'])) {
92 $priceSetId = CRM_Price_BAO_PriceSet
::getFor($context, $id, NULL);
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)
100 CRM_Core_DAO
::executeQuery($sql, [1 => [$id, 'Integer']]);
102 if ($context == 'civicrm_event') {
103 CRM_Core_BAO_Discount
::del($id, $context);
107 CRM_Utils_JSON
::output($priceSetId);
111 * Determine whether the request is for a valid class/method name.
113 * @param string $type
114 * 'method'|'class'|''.
115 * @param string $className
117 * @param string $fnName
122 public static function checkAuthz($type, $className, $fnName = NULL) {
125 if (!preg_match('/^CRM_[a-zA-Z0-9]+_Page_AJAX$/', $className)) {
128 if (!preg_match('/^[a-zA-Z0-9]+$/', $fnName)) {
132 // ensure that function exists
133 return method_exists($className, $fnName);
138 if (!preg_match('/^CRM_[a-zA-Z0-9]+_(Page|Form)_Inline_[a-zA-Z0-9]+$/', $className)) {
141 return class_exists($className);
149 * Outputs the CiviCRM standard json-formatted page/form response
150 * @param array|string $response
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];
157 // Add session variables to response
158 $session = CRM_Core_Session
::singleton();
160 'status' => 'success',
161 'userContext' => htmlspecialchars_decode($session->readUserContext()),
162 'title' => CRM_Utils_System
::$title,
164 // crmMessages will be automatically handled by our ajax preprocessor
166 if ($session->getStatus(FALSE)) {
167 $response['crmMessages'] = $session->getStatus(TRUE);
169 $output = json_encode($response);
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');
176 $output = "<textarea>$output</textarea>";
179 CRM_Utils_System
::civiExit();
183 * Set headers appropriate for a js file.
185 * @param int|null $ttl
186 * Time-to-live (seconds).
188 public static function setJsHeaders($ttl = NULL) {
190 // Encourage browsers to cache for a long time - 1 year
191 $ttl = 60 * 60 * 24 * 364;
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");
199 * Set defaults for sort and pager.
201 * @param int $defaultOffset
202 * @param int $defaultRowCount
203 * @param string $defaultSort
204 * @param string $defaultsortOrder
208 public static function defaultSortAndPagerParams($defaultOffset = 0, $defaultRowCount = 25, $defaultSort = NULL, $defaultsortOrder = 'asc') {
214 if (isset($_GET['columns'])) {
215 foreach ($_GET['columns'] as $key => $value) {
216 $sortMapper[$key] = CRM_Utils_Type
::validate($value['data'], 'MysqlColumnNameOrAlias');
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;
227 $params['sortBy'] = "{$sort} {$sortOrder}";
229 $params['_raw_values']['sort'][0] = $sort;
230 $params['_raw_values']['order'][0] = $sortOrder;
233 $params['offset'] = $offset;
234 $params['rp'] = $rowCount;
235 $params['page'] = ($offset / $rowCount) +
1;
241 * Validate ajax input parameters.
243 * @param array $requiredParams
244 * @param array $optionalParams
248 public static function validateParams($requiredParams = [], $optionalParams = []) {
251 foreach ($requiredParams as $param => $type) {
252 $params[$param] = CRM_Utils_Type
::validate(CRM_Utils_Array
::value($param, $_GET), $type);
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);
261 foreach ($_GET[$param] as $index => $value) {
262 $params[$param][$index] = CRM_Utils_Type
::validate($value, $type);