CRM-15901: Turn off PHP errors display for all ajax calls
[civicrm-core.git] / CRM / Core / Invoke.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
06b69b18 4 | CiviCRM version 4.5 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
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 * Given an argument list, invoke the appropriate CRM function
31 * Serves as a wrapper between the UserFrameWork and Core CRM
32 *
33 * @package CRM
06b69b18 34 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
35 * $Id$
36 *
37 */
38class CRM_Core_Invoke {
39
40 /**
41 * This is the main function that is called on every click action and based on the argument
42 * respective functions are called
43 *
44 * @param $args array this array contains the arguments of the url
45 * @return string, HTML
46 *
47 * @static
48 * @access public
49 */
50 static function invoke($args) {
51 try {
52 return self::_invoke($args);
dcc4f6a7 53 }
54
55 catch (Exception $e) {
6a488035
TO
56 return CRM_Core_Error::handleUnhandledException($e);
57 }
58 }
59
a0ee3941
EM
60 /**
61 * @param $args
62 */
6a488035
TO
63 protected static function _invoke($args) {
64 if ($args[0] !== 'civicrm') {
65 return;
66 }
1ebbf8bf
NG
67 // CRM-15901: Turn off PHP errors display for all ajax calls
68 if (CRM_Utils_Array::value(1, $args) == 'ajax' || CRM_Utils_Array::value('snippet', $_REQUEST)) {
69 ini_set('display_errors', 0);
70 }
6a488035
TO
71
72 if (!defined('CIVICRM_SYMFONY_PATH')) {
73 try {
74 // Traditional Civi invocation path
75 self::hackMenuRebuild($args); // may exit
76 self::init($args);
77 self::hackStandalone($args);
78 $item = self::getItem($args);
79 return self::runItem($item);
dcc4f6a7 80 }
81 catch (CRM_Core_EXCEPTION $e) {
82 $params = $e->getErrorData();
83 $message = $e->getMessage();
84 if (isset($params['legacy_status_bounce'])) {
85 //@todo remove this- see comments on
86 //https://github.com/eileenmcnaughton/civicrm-core/commit/ae686b09e2c987091612bb25ba0a58e520a203e7
87 CRM_Core_Error::statusBounce($params['message']);
88 }
89 else {
90 $session = CRM_Core_Session::singleton();
91 $session->setStatus(
92 $message,
93 CRM_Utils_Array::value('message_title', $params),
94 CRM_Utils_Array::value('message_type', $params, 'error')
95 );
96
97 // @todo remove this code - legacy redirect path is an interim measure for moving redirects out of BAO
98 // to somewhere slightly more acceptable. they should not be part of the exception class & should
99 // be managed @ the form level - if you find a form that is triggering this piece of code
100 // you should log a ticket for it to be removed with details about the form you were on.
101 if(!empty($params['legacy_redirect_path'])) {
102 if(CRM_Utils_System::isDevelopment()) {
103 // here we could set a message telling devs to log it per above
104 }
105 CRM_Utils_System::redirect($params['legacy_redirect_path'], $params['legacy_redirect_query']);
106 }
107 }
108 }
109 catch (Exception $e) {
6a488035
TO
110 // Recall: CRM_Core_Config is initialized before calling CRM_Core_Invoke
111 $config = CRM_Core_Config::singleton();
112 return CRM_Core_Error::handleUnhandledException($e);
113 /*
114 if ($config->backtrace) {
115 return CRM_Core_Error::formatHtmlException($e);
116 } else {
117 // TODO
118 }*/
119 }
120 } else {
121 // Symfony-based invocation path
122 require_once CIVICRM_SYMFONY_PATH . '/app/bootstrap.php.cache';
123 require_once CIVICRM_SYMFONY_PATH . '/app/AppKernel.php';
124 $kernel = new AppKernel('dev', true);
125 $kernel->loadClassCache();
126 $response = $kernel->handle(Symfony\Component\HttpFoundation\Request::createFromGlobals());
c24c4679
TO
127 if (preg_match(':^text/html:', $response->headers->get('Content-Type'))) {
128 // let the CMS handle the trappings
129 return $response->getContent();
130 } else {
131 $response->send();
132 exit();
133 }
6a488035
TO
134 }
135 }
136 /**
137 * Hackish support /civicrm/menu/rebuild
138 *
139 * @param array $args list of path parts
140 * @void
141 */
142 static public function hackMenuRebuild($args) {
143 if (array('civicrm','menu','rebuild') == $args || array('civicrm', 'clearcache') == $args) {
144 // ensure that the user has a good privilege level
145 if (CRM_Core_Permission::check('administer CiviCRM')) {
146 self::rebuildMenuAndCaches();
147 CRM_Core_Session::setStatus(ts('Cleared all CiviCRM caches (database, menu, templates)'), ts('Complete'), 'success');
148 return CRM_Utils_System::redirect(); // exits
149 }
150 else {
151 CRM_Core_Error::fatal('You do not have permission to execute this url');
152 }
153 }
154 }
155
156 /**
157 * Perform general setup
158 *
159 * @param array $args list of path parts
160 * @void
161 */
162 static public function init($args) {
163 // first fire up IDS and check for bad stuff
164 $config = CRM_Core_Config::singleton();
634e1a1a 165 if (!CRM_Core_Permission::check('skip IDS check')) {
6a488035
TO
166 $ids = new CRM_Core_IDS();
167 $ids->check($args);
168 }
169
170 // also initialize the i18n framework
171 require_once 'CRM/Core/I18n.php';
172 $i18n = CRM_Core_I18n::singleton();
173 }
174
175 /**
176 * Hackish support for /standalone/*
177 *
178 * @param array $args list of path parts
179 * @void
180 */
181 static public function hackStandalone($args) {
182 $config = CRM_Core_Config::singleton();
183 if ($config->userFramework == 'Standalone') {
184 $session = CRM_Core_Session::singleton();
185 if ($session->get('new_install') !== TRUE) {
186 CRM_Core_Standalone::sidebarLeft();
187 }
188 elseif ($args[1] == 'standalone' && $args[2] == 'register') {
189 CRM_Core_Menu::store();
190 }
191 }
192 }
193
194 /**
195 * Determine which menu $item corresponds to $args
196 *
197 * @param array $args list of path parts
198 * @return array; see CRM_Core_Menu
199 */
200 static public function getItem($args) {
201 if (is_array($args)) {
202 // get the menu items
203 $path = implode('/', $args);
204 } else {
205 $path = $args;
206 }
207 $item = CRM_Core_Menu::get($path);
208
209 // we should try to compute menus, if item is empty and stay on the same page,
210 // rather than compute and redirect to dashboard.
211 if (!$item) {
212 CRM_Core_Menu::store(FALSE);
213 $item = CRM_Core_Menu::get($path);
214 }
215
216 return $item;
217 }
218
219 /**
220 * Given a menu item, call the appropriate controller and return the response
221 *
222 * @param array $item see CRM_Core_Menu
223 * @return string, HTML
224 */
225 static public function runItem($item) {
226 $config = CRM_Core_Config::singleton();
227 if ($config->userFramework == 'Joomla' && $item) {
228 $config->userFrameworkURLVar = 'task';
229
230 // joomla 1.5RC1 seems to push this in the POST variable, which messes
231 // QF and checkboxes
232 unset($_POST['option']);
233 CRM_Core_Joomla::sidebarLeft();
234 }
235
236 // set active Component
237 $template = CRM_Core_Smarty::singleton();
238 $template->assign('activeComponent', 'CiviCRM');
239 $template->assign('formTpl', 'default');
240
241 if ($item) {
242 // CRM-7656 - make sure we send a clean sanitized path to create printer friendly url
243 $printerFriendly = CRM_Utils_System::makeURL(
244 'snippet', FALSE, FALSE,
245 CRM_Utils_Array::value('path', $item)
246 ) . '2';
247 $template->assign('printerFriendly', $printerFriendly);
248
249 if (!array_key_exists('page_callback', $item)) {
250 CRM_Core_Error::debug('Bad item', $item);
251 CRM_Core_Error::fatal(ts('Bad menu record in database'));
252 }
253
254 // check that we are permissioned to access this page
255 if (!CRM_Core_Permission::checkMenuItem($item)) {
256 CRM_Utils_System::permissionDenied();
257 return;
258 }
259
260 // check if ssl is set
a7488080 261 if (!empty($item['is_ssl'])) {
6a488035
TO
262 CRM_Utils_System::redirectToSSL();
263 }
264
265 if (isset($item['title'])) {
266 CRM_Utils_System::setTitle($item['title']);
267 }
268
269 if (isset($item['breadcrumb']) && !isset($item['is_public'])) {
270 CRM_Utils_System::appendBreadCrumb($item['breadcrumb']);
271 }
272
273 $pageArgs = NULL;
a7488080 274 if (!empty($item['page_arguments'])) {
6a488035
TO
275 $pageArgs = CRM_Core_Menu::getArrayForPathArgs($item['page_arguments']);
276 }
277
278 $template = CRM_Core_Smarty::singleton();
279 if (!empty($item['is_public'])) {
280 $template->assign('urlIsPublic', TRUE);
281 }
282 else {
283 $template->assign('urlIsPublic', FALSE);
284 self::versionCheck($template);
285 }
286
287 if (isset($item['return_url'])) {
288 $session = CRM_Core_Session::singleton();
289 $args = CRM_Utils_Array::value(
290 'return_url_args',
291 $item,
292 'reset=1'
293 );
294 $session->pushUserContext(CRM_Utils_System::url($item['return_url'], $args));
295 }
296
297 $result = NULL;
298 if (is_array($item['page_callback'])) {
6a488035 299 require_once (str_replace('_', DIRECTORY_SEPARATOR, $item['page_callback'][0]) . '.php');
a1f0ed4e 300 $result = call_user_func($item['page_callback']);
6a488035
TO
301 }
302 elseif (strstr($item['page_callback'], '_Form')) {
303 $wrapper = new CRM_Utils_Wrapper();
304 $result = $wrapper->run(
305 CRM_Utils_Array::value('page_callback', $item),
306 CRM_Utils_Array::value('title', $item),
307 isset($pageArgs) ? $pageArgs : NULL
308 );
309 }
310 else {
311 $newArgs = explode('/', $_GET[$config->userFrameworkURLVar]);
312 require_once (str_replace('_', DIRECTORY_SEPARATOR, $item['page_callback']) . '.php');
313 $mode = 'null';
314 if (isset($pageArgs['mode'])) {
315 $mode = $pageArgs['mode'];
316 unset($pageArgs['mode']);
317 }
318 $title = CRM_Utils_Array::value('title', $item);
319 if (strstr($item['page_callback'], '_Page')) {
320 $object = new $item['page_callback'] ($title, $mode );
6c2473d5 321 $object->urlPath = explode('/', $_GET[$config->userFrameworkURLVar]);
6a488035
TO
322 }
323 elseif (strstr($item['page_callback'], '_Controller')) {
324 $addSequence = 'false';
325 if (isset($pageArgs['addSequence'])) {
326 $addSequence = $pageArgs['addSequence'];
327 $addSequence = $addSequence ? 'true' : 'false';
328 unset($pageArgs['addSequence']);
329 }
330 $object = new $item['page_callback'] ($title, true, $mode, null, $addSequence );
331 }
332 else {
333 CRM_Core_Error::fatal();
334 }
335 $result = $object->run($newArgs, $pageArgs);
336 }
337
338 CRM_Core_Session::storeSessionObjects();
339 return $result;
340 }
341
342 CRM_Core_Menu::store();
343 CRM_Core_Session::setStatus(ts('Menu has been rebuilt'), ts('Complete'), 'success');
344 return CRM_Utils_System::redirect();
345 }
346
347 /**
348 * This function contains the default action
349 *
350 * @param $action
351 *
77b97be7
EM
352 * @param $contact_type
353 * @param $contact_sub_type
354 *
6a488035
TO
355 * @static
356 * @access public
357 */
358 static function form($action, $contact_type, $contact_sub_type) {
359 CRM_Utils_System::setUserContext(array('civicrm/contact/search/basic', 'civicrm/contact/view'));
360 $wrapper = new CRM_Utils_Wrapper();
361
362 $properties = CRM_Core_Component::contactSubTypeProperties($contact_sub_type, 'Edit');
363 if ($properties) {
364 $wrapper->run($properties['class'], ts('New %1', array(1 => $contact_sub_type)), $action, TRUE);
365 }
366 else {
367 $wrapper->run('CRM_Contact_Form_Contact', ts('New Contact'), $action, TRUE);
368 }
369 }
370
6a488035
TO
371 /**
372 * Show the message about CiviCRM versions
373 *
374 * @param obj: $template (reference)
375 */
376 static function versionCheck($template) {
377 if (CRM_Core_Config::isUpgradeMode()) {
378 return;
379 }
380 $versionCheck = CRM_Utils_VersionCheck::singleton();
381 $newerVersion = $versionCheck->newerVersion();
382 $template->assign('newer_civicrm_version', $newerVersion);
383 }
384
a0ee3941
EM
385 /**
386 * @param bool $triggerRebuild
387 * @param bool $sessionReset
388 *
389 * @throws Exception
390 */
6a488035
TO
391 static function rebuildMenuAndCaches($triggerRebuild = FALSE, $sessionReset = FALSE) {
392 $config = CRM_Core_Config::singleton();
393 $config->clearModuleList();
394
ae2cab23
TO
395 // also cleanup all caches
396 $config->cleanupCaches($sessionReset || CRM_Utils_Request::retrieve('sessionReset', 'Boolean', CRM_Core_DAO::$_nullObject, FALSE, 0, 'GET'));
397
6a488035
TO
398 CRM_Core_Menu::store();
399
400 // also reset navigation
401 CRM_Core_BAO_Navigation::resetNavigation();
402
6a488035
TO
403 // also cleanup module permissions
404 $config->cleanupPermissions();
405
9762f6ff
CW
406 // rebuild word replacement cache - pass false to prevent operations redundant with this fn
407 CRM_Core_BAO_WordReplacement::rebuild(FALSE);
76dca235 408
9f83bb22 409 CRM_Core_BAO_Setting::updateSettingsFromMetaData();
9762f6ff
CW
410 // Clear js caches
411 CRM_Core_Resources::singleton()->flushStrings()->rebuildDynamicResources();
ab89fdde 412 CRM_Case_XMLRepository::singleton(TRUE);
1fcf16cc 413
6a488035
TO
414 // also rebuild triggers if requested explicitly
415 if (
416 $triggerRebuild ||
417 CRM_Utils_Request::retrieve('triggerRebuild', 'Boolean', CRM_Core_DAO::$_nullObject, FALSE, 0, 'GET')
418 ) {
419 CRM_Core_DAO::triggerRebuild();
420 }
95a90cba 421 CRM_Core_DAO_AllCoreTables::reinitializeCache(TRUE);
6a488035
TO
422 CRM_Core_ManagedEntities::singleton(TRUE)->reconcile();
423 }
424}