function run() { if (CRM_Utils_System::authenticateKey()) { $request_type = CRM_Utils_Request::retrieve('type', 'String'); $request_data = CRM_Utils_Request::retrieve('data', 'String'); $config = CRM_Core_Config::singleton(); if ($config->debug) { $request_data_log = print_r($request_data, TRUE); CRM_Core_Error::debug_log_message("Mailchimp Webhook Request [{$request_type}]: \n{$request_data_log}"); } $function_name = 'self::mailchimpWebhook' . ucwords($request_type); if (is_callable($function_name)) { // Set a canary to prevent CiviMailchimp hooks from firing, which // would trigger updates back to Mailchimp, resulting in an endless // loop. civimailchimp_static('mailchimp_do_not_run_hooks', TRUE); try { call_user_func($function_name, $request_data); } catch (Exception $e) { $error = array('code' => get_class($e), 'message' => $e->getMessage(), 'exception' => $e); $message = "Mailchimp Webhook Request [{$request_type}]: {$error['code']}: {$error['message']}"; CRM_CiviMailchimp_BAO_SyncLog::saveMessage('error', 'mailchimp_to_civicrm', $message, $request_data); CRM_Core_Error::debug_var('Fatal Error Details', $error); CRM_Core_Error::backtrace('backTrace', TRUE); throw $e; } } } parent::run(); }
static function clear() { $message_id = CRM_Utils_Request::retrieve('id', 'Integer'); $civicrm_queue_item_id = CRM_Utils_Request::retrieve('qid', 'Integer'); try { CRM_CiviMailchimp_BAO_SyncLog::clearQueueItem($civicrm_queue_item_id); CRM_CiviMailchimp_BAO_SyncLog::clearMessage($message_id); } catch (Exception $e) { $error = array('status' => 'error', 'code' => get_class($e), 'message' => $e->getMessage(), 'exception' => $e); // CRM-11831 @see http://www.malsup.com/jquery/form/#file-upload if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { header('Content-Type: application/json'); } echo json_encode($error); CRM_Core_Error::debug_var('Fatal Error Details', $error); CRM_Core_Error::backtrace('backTrace', TRUE); CRM_Utils_System::civiExit(); } }
/** * get the variable information from the request (GET/POST/SESSION * * @param $name name of the variable to be retrieved * @param $type type of the variable (see CRM_Utils_Type for details) * @param $store session scope where variable is stored * @param $abort is this variable required * @param $default default value of the variable if not present * @param $method where should we look for the variable * * @return string the value of the variable * @access public * @static * */ static function retrieve($name, $type, &$store, $abort = false, $default = null, $method = 'GET') { // hack to detect stuff not yet converted to new style if (!is_string($type)) { CRM_Core_Error::backtrace(); CRM_Core_Error::fatal(ts("Please convert retrieve call to use new function signature")); } $value = null; switch ($method) { case 'GET': $value = CRM_Utils_Array::value($name, $_GET); break; case 'POST': $value = CRM_Utils_Array::value($name, $_POST); break; default: $value = CRM_Utils_Array::value($name, $_REQUEST); break; } require_once 'CRM/Utils/Type.php'; if (isset($value) && CRM_Utils_Type::validate($value, $type, $abort, $name) === null) { $value = null; } if (!isset($value) && $store) { $value = $store->get($name); } if (!isset($value) && $abort) { CRM_Core_Error::fatal(ts("Could not find valid value for %1", array(1 => $name))); } if (!isset($value) && $default) { $value = $default; } // minor hack for action if ($name == 'action' && is_string($value)) { $value = CRM_Core_Action::resolve($value); } if (isset($value) && $store) { $store->set($name, $value); } return $value; }
function civicrm_api3_civi_mailchimp_sync($params) { CRM_CiviMailchimp_BAO_SyncLog::deleteOldMessages(); $records_to_process = $params['records_to_process_per_run']; $queue = CRM_Queue_Service::singleton()->create(array('type' => 'Sql', 'name' => 'mailchimp-sync', 'reset' => FALSE)); if ($queue->numberOfItems() > 0) { $runner = new CRM_Queue_Runner(array('title' => ts('Sync Contacts to Mailchimp'), 'queue' => $queue)); $continue_to_next_item = TRUE; $records_processed = 0; while ($continue_to_next_item && $records_processed < $records_to_process) { $record = $runner->runNext(); if ($record['is_error']) { // Get the current Queue Item being worked on to allow for better error // reporting and logging. $query = "\n SELECT\n id,\n data\n FROM\n civicrm_queue_item\n WHERE\n queue_name = 'mailchimp-sync'\n ORDER BY\n weight ASC,\n id ASC\n LIMIT 1\n "; $item = CRM_Core_DAO::executeQuery($query); while ($item->fetch()) { $item_data = unserialize($item->data); $message = "[{$item_data->arguments[0]}] There was an error syncing contacts to Mailchimp."; $exception_name = ''; if (!empty($record['exception'])) { $exception_name = get_class($record['exception']); $message = "[{$item_data->arguments[0]}] {$exception_name}: {$record['exception']->getMessage()}."; } $message .= " Mailchimp List ID: {$item_data->arguments[1]}. {$records_processed} records were successfully synced before this error."; $error = array('code' => $exception_name, 'message' => $message, 'exception' => $record['exception']); CRM_Core_Error::debug_var('Fatal Error Details', $error); CRM_Core_Error::backtrace('backTrace', TRUE); CRM_CiviMailchimp_BAO_SyncLog::saveMessage('error', 'civicrm_to_mailchimp', $message, $item_data, $item->id); return civicrm_api3_create_error($message); } } $continue_to_next_item = $record['is_continue']; $records_processed++; } $message = ts('%1 records were successfully synced to Mailchimp.', array(1 => $records_processed)); CRM_CiviMailchimp_BAO_SyncLog::saveMessage('success', 'civicrm_to_mailchimp', $message); return civicrm_api3_create_success($records_processed); } }
/** * PEAR error-handler to quietly catch otherwise fatal errors. Intended for use with smtp transport. * * @param object $obj * The PEAR_ERROR object. * @return object * $obj */ public static function nullHandler($obj) { CRM_Core_Error::debug_log_message("Ignoring exception thrown by nullHandler: {$obj->code}, {$obj->message}"); CRM_Core_Error::backtrace('backTrace', TRUE); return $obj; }
static function checkMenuItem(&$item) { if (!array_key_exists('access_callback', $item)) { CRM_Core_Error::backtrace(); CRM_Core_Error::fatal(); } // if component_id is present, ensure it is enabled if (isset($item['component_id']) && $item['component_id']) { $config = CRM_Core_Config::singleton(); if (is_array($config->enableComponentIDs) && in_array($item['component_id'], $config->enableComponentIDs)) { // continue with process } else { return FALSE; } } // the following is imitating drupal 6 code in includes/menu.inc if (empty($item['access_callback']) || is_numeric($item['access_callback'])) { return (bool) $item['access_callback']; } // check whether the following Ajax requests submitted the right key // FIXME: this should be integrated into ACLs proper if (CRM_Utils_Array::value('page_type', $item) == 3) { if (!CRM_Core_Key::validate($_REQUEST['key'], $item['path'])) { return FALSE; } } // check if callback is for checkMenu, if so optimize it if (is_array($item['access_callback']) && $item['access_callback'][0] == 'CRM_Core_Permission' && $item['access_callback'][1] == 'checkMenu') { $op = CRM_Utils_Array::value(1, $item['access_arguments'], 'and'); return self::checkMenu($item['access_arguments'][0], $op); } else { return call_user_func_array($item['access_callback'], $item['access_arguments']); } }
/** * sends query to database - this is the private one that must work * - internal functions use this rather than $this->query() * * @param string $string * @access private * @return mixed none or PEAR_Error */ function _query($string) { global $_DB_DATAOBJECT, $queries, $user; $this->_connect(); if (defined('CIVICRM_DEBUG_LOG_QUERY')) { if (CIVICRM_DEBUG_LOG_QUERY == 'backtrace') { CRM_Core_Error::backtrace($string, true); } else { if (CIVICRM_DEBUG_LOG_QUERY) { CRM_Core_Error::debug_var('Query', $string, false, true); } } } $DB =& $_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]; $options =& $_DB_DATAOBJECT['CONFIG']; $_DB_driver = empty($_DB_DATAOBJECT['CONFIG']['db_driver']) ? 'DB' : $_DB_DATAOBJECT['CONFIG']['db_driver']; if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) { $this->debug($string, $log = "QUERY"); } if (strtoupper($string) == 'BEGIN') { if ($_DB_driver == 'DB') { $DB->autoCommit(false); } else { $DB->beginTransaction(); } // db backend adds begin anyway from now on.. return true; } if (strtoupper($string) == 'COMMIT') { $res = $DB->commit(); if ($_DB_driver == 'DB') { $DB->autoCommit(true); } return $res; } if (strtoupper($string) == 'ROLLBACK') { $DB->rollback(); if ($_DB_driver == 'DB') { $DB->autoCommit(true); } return true; } if (!empty($options['debug_ignore_updates']) && strtolower(substr(trim($string), 0, 6)) != 'select' && strtolower(substr(trim($string), 0, 4)) != 'show' && strtolower(substr(trim($string), 0, 8)) != 'describe') { $this->debug('Disabling Update as you are in debug mode'); return $this->raiseError("Disabling Update as you are in debug mode", null); } //if (@$_DB_DATAOBJECT['CONFIG']['debug'] > 1) { // this will only work when PEAR:DB supports it. //$this->debug($DB->getAll('explain ' .$string,DB_DATAOBJECT_FETCHMODE_ASSOC), $log="sql",2); //} // some sim $t = explode(' ', microtime()); $_DB_DATAOBJECT['QUERYENDTIME'] = $time = $t[0] + $t[1]; for ($tries = 0; $tries < 3; $tries++) { if ($_DB_driver == 'DB') { $result = $DB->query($string); } else { switch (strtolower(substr(trim($string), 0, 6))) { case 'insert': case 'update': case 'delete': $result = $DB->exec($string); break; default: $result = $DB->query($string); break; } } // see if we got a failure.. - try again a few times.. if (!is_a($result, 'PEAR_Error')) { break; } if ($result->getCode() != -14) { // *DB_ERROR_NODBSELECTED break; // not a connection error.. } sleep(1); // wait before retyring.. $DB->connect($DB->dsn); } if (is_a($result, 'PEAR_Error')) { if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) { $this->debug($result->toString(), "Query Error", 1); } return $this->raiseError($result); } /* CRM-3225 */ if (function_exists('variable_get') && variable_get('dev_query', 0)) { // this is for drupal devel module // If devel.module query logging is enabled, prepend a comment with the username and calling function // to the SQL string. $bt = debug_backtrace(); // t() may not be available yet so we don't wrap 'Anonymous' $name = $user->uid ? $user->name : variable_get('anonymous', 'Anonymous'); $query = $bt[3]['function'] . "\n/* " . $name . ' */ ' . str_replace("\n ", '', $string); list($usec, $sec) = explode(' ', microtime()); $stop = (double) $usec + (double) $sec; $diff = $stop - $time; $queries[] = array($query, $diff); } if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) { $t = explode(' ', microtime()); $_DB_DATAOBJECT['QUERYENDTIME'] = $t[0] + $t[1]; $this->debug('QUERY DONE IN ' . ($t[0] + $t[1] - $time) . " seconds", 'query', 1); } switch (strtolower(substr(trim($string), 0, 6))) { case 'insert': case 'update': case 'delete': if ($_DB_driver == 'DB') { // pear DB specific return $DB->affectedRows(); } return $result; } if (is_object($result)) { // lets hope that copying the result object is OK! // fix notices in unit test. if (!CRM_Utils_Array::value('RESULTSEQ', $GLOBALS['_DB_DATAOBJECT'])) { $GLOBALS['_DB_DATAOBJECT']['RESULTSEQ'] = 1; } $_DB_resultid = $GLOBALS['_DB_DATAOBJECT']['RESULTSEQ']++; $_DB_DATAOBJECT['RESULTS'][$_DB_resultid] = $result; $this->_DB_resultid = $_DB_resultid; } $this->N = 0; if (!empty($_DB_DATAOBJECT['CONFIG']['debug'])) { $this->debug(serialize($result), 'RESULT', 5); } if (method_exists($result, 'numrows')) { if ($_DB_driver == 'DB') { $DB->expectError(DB_ERROR_UNSUPPORTED); } else { $DB->expectError(MDB2_ERROR_UNSUPPORTED); } $this->N = $result->numrows(); if (is_a($this->N, 'PEAR_Error')) { $this->N = true; } $DB->popExpect(); } }
static function checkMenuItem(&$item) { if (!array_key_exists('access_callback', $item)) { CRM_Core_Error::backtrace(); CRM_Core_Error::fatal(); } // if component_id is present, ensure it is enabled if (isset($item['component_id']) && $item['component_id']) { $config =& CRM_Core_Config::singleton(); if (is_array($config->enableComponentIDs) && in_array($item['component_id'], $config->enableComponentIDs)) { // continue with process } else { return false; } } // the following is imitating drupal 6 code in includes/menu.inc if (empty($item['access_callback']) || is_numeric($item['access_callback'])) { return (bool) $item['access_callback']; } // check if callback is for checkMenu, if so optimize it if (is_array($item['access_callback']) && $item['access_callback'][0] == 'CRM_Core_Permission' && $item['access_callback'][1] == 'checkMenu') { $op = CRM_Utils_Array::value(1, $item['access_arguments'], 'and'); return self::checkMenu($item['access_arguments'][0], $op); } else { return call_user_func_array($item['access_callback'], $item['access_arguments']); } }
/** * Error handler to quietly catch otherwise fatal smtp transport errors. * * @param object $obj The PEAR_ERROR object * @return object $obj * @access public * @static */ public static function nullHandler($obj) { CRM_Core_Error::debug_var('Ignoring exception thrown here', $obj); CRM_Core_Error::backtrace('backTrace', true); return $obj; }
/** * Catch a Mailchimp API error and add an entry to the CiviCRM log file. */ function civimailchimp_catch_mailchimp_api_error($exception) { // If the Mailchimp API call fails, we want to still allow admins to // create or edit a group. $error = array('code' => get_class($exception), 'message' => $exception->getMessage()); $message = ts("There was an error when trying to retrieve available Mailchimp Lists to sync to a group. {$error['code']}: {$error['message']}."); if (CRM_Core_Permission::check('administer CiviCRM')) { $session = CRM_Core_Session::singleton(); $session->setStatus($message, ts("Mailchimp API Error"), 'alert', array('expires' => 0)); } CRM_Core_Error::debug_var('Fatal Error Details', $error); CRM_Core_Error::backtrace('backTrace', TRUE); }
/** * create the main callback method. this method centralizes error processing. * * the errors we expect are from the pear modules DB, DB_DataObject * which currently use PEAR::raiseError to notify of error messages. * * @param object PEAR_Error * * @return void * @access public */ function handle($pearError) { // setup smarty with config, session and template location. $template =& CRM_Core_Smarty::singleton(); $config =& CRM_Core_Config::singleton(); if ($config->debug && ($_REQUEST['backtrace'] || defined('CIVICRM_BACKTRACE'))) { CRM_Core_Error::backtrace(); } // create the error array $error = array(); $error['callback'] = $pearError->getCallback(); $error['code'] = $pearError->getCode(); $error['message'] = $pearError->getMessage(); $error['mode'] = $pearError->getMode(); $error['debug_info'] = $pearError->getDebugInfo(); $error['type'] = $pearError->getType(); $error['user_info'] = $pearError->getUserInfo(); $error['to_string'] = $pearError->toString(); if (mysql_error()) { $mysql_error = mysql_error() . ', ' . mysql_errno(); $template->assign_by_ref('mysql_code', $mysql_error); // execute a dummy query to clear error stack mysql_query('select 1'); } $template->assign_by_ref('error', $error); $template->assign('tplFile', "CRM/" . CRM_CORE_ERROR_ERROR_TEMPLATE); $content = $template->fetch('CRM/error.tpl'); $content .= CRM_Core_Error::debug('error', $error, false); echo CRM_Utils_System::theme('page', $content); exit(1); }
/** * display an error page with an error message describing what happened * * @param string message the error message * @param string code the error code if any * @param string email the email address to notify of this situation * * @return void * @static * @acess public */ static function fatal($message = null, $code = null, $email = null) { if (!$message) { $message = ts('We experienced an unexpected error. Please file an issue with the backtrace'); } $vars = array('message' => $message, 'code' => $code); $config =& CRM_Core_Config::singleton(); if ($config->fatalErrorHandler && function_exists($config->fatalErrorHandler)) { $name = $config->fatalErrorHandler; $ret = $name($vars); if ($ret) { // the call has been successfully handled // so we just exit exit(CRM_Core_Error::FATAL_ERROR); } } if ($config->backtrace) { self::backtrace(); } $template =& CRM_Core_Smarty::singleton(); $template->assign($vars); CRM_Core_Error::debug_var('Fatal Error Details', $vars); CRM_Core_Error::backtrace('backTrace', true); $content = $template->fetch($config->fatalErrorTemplate); echo CRM_Utils_System::theme('page', $content); // print $content; exit(CRM_Core_Error::FATAL_ERROR); }