Commit 7e9ae297 authored by bgm's avatar bgm Committed by Aegir user

Update reporterror to v3.1

parent 4be79955
<?php
/*
+--------------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2012-2013 |
+--------------------------------------------------------------------------+
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU Affero General Public License as published |
| by the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. |
+--------------------------------------------------------------------------+
*/
class CRM_Admin_Form_Setting_ReportError extends CRM_Admin_Form_Setting {
protected $_values;
function preProcess() {
// Needs to be here as form is built before default values are set
$this->_values = CRM_Core_BAO_Setting::getItem(REPORTERROR_SETTINGS_GROUP);
}
function setDefaultValues() {
$defaults = $this->_values;
$defaults['show_full_backtrace'] = CRM_Utils_Array::value('show_full_backtrace', $defaults, FALSE);
$defaults['show_post_data'] = CRM_Utils_Array::value('show_post_data', $defaults, FALSE);
$defaults['bots_sendreport'] = CRM_Utils_Array::value('bots_sendreport', $defaults, FALSE);
$defaults['bots_404'] = CRM_Utils_Array::value('bots_404', $defaults, FALSE);
$defaults['bots_regexp'] = CRM_Utils_Array::value('bots_regexp', $defaults, '(Googlebot|bingbot)');
return $defaults;
}
/**
* Function to build the form
*
* @return None
* @access public
*/
public function buildQuickForm() {
$this->applyFilter('__ALL__', 'trim');
$this->add('text', 'mailto',
ts('Error Report Recipient', array('domain' => 'ca.bidon.reporterror')),
CRM_Utils_Array::value('mailto', $this->_values),
FALSE);
$this->addYesNo('show_full_backtrace', ts('Display a full backtrace in e-mails?', array('domain' => 'ca.bidon.reporterror')));
$this->addYesNo('show_post_data', ts('Display POST data in e-mails?', array('domain' => 'ca.bidon.reporterror')));
$this->addYesNo('show_session_data', ts('Display session data in e-mails?', array('domain' => 'ca.bidon.reporterror')));
// Special handling of Contribution page errors.
// Get a list of contribution pages
$results = civicrm_api3('ContributionPage', 'get', array('is_active' => 1));
$contribution_pages = array(
0 => ts('- Select -'),
);
if($results['is_error'] == 0) {
foreach ($results['values'] as $val) {
$contribution_pages[$val['id']] = $val['title'];
}
}
$radio_choices = array(
'0' => ts('Do nothing (show the CiviCRM error)', array('domain' => 'ca.bidon.reporterror')),
'1' => ts('Redirect to front page of CMS', array('domain' => 'ca.bidon.reporterror')),
'2' => ts('Redirect to a specific contribution page', array('domain' => 'ca.bidon.reporterror'))
);
$this->addRadio('noreferer_handle',
ts('Enable transparent redirection?', array('domain' => 'ca.bidon.reporterror')),
$radio_choices,
array('options_per_line' => 1),
'<br/>' /* one option per line */
);
$this->addYesNo('noreferer_sendreport', ts('Send error reports for this particular error?', array('domain' => 'ca.bidon.reporterror')));
$this->add('select', 'noreferer_pageid',
ts('Redirect to Contribution Page', array('domain' => 'ca.bidon.reporterror')),
$contribution_pages,
TRUE);
// Special handling of Event page errors.
$results = civicrm_api3('Event', 'get', array('is_active' => 1));
$event_pages = array(
0 => ts('- Select -'),
);
if($results['is_error'] == 0) {
foreach ($results['values'] as $val) {
$event_pages[$val['id']] = $val['title'];
}
}
$radio_choices = array(
'0' => ts('Do nothing (show the CiviCRM error)', array('domain' => 'ca.bidon.reporterror')),
'1' => ts('Redirect to front page of CMS', array('domain' => 'ca.bidon.reporterror')),
'2' => ts('Redirect to a specific event registration page', array('domain' => 'ca.bidon.reporterror'))
);
$this->addRadio('noreferer_handle_event',
ts('Enable transparent redirection?', array('domain' => 'ca.bidon.reporterror')),
$radio_choices,
array('options_per_line' => 1),
'<br/>' /* one option per line */
);
$this->addYesNo('noreferer_sendreport_event', ts('Send error reports for this particular error?', array('domain' => 'ca.bidon.reporterror')));
$this->add('select', 'noreferer_handle_eventid',
ts('Redirect to Event Page', array('domain' => 'ca.bidon.reporterror')),
$event_pages,
TRUE);
// Special handling of bots
$this->addYesNo('bots_sendreport', ts('Send error reports for errors caused by bots?', array('domain' => 'ca.bidon.reporterror')), FALSE, TRUE);
$this->addYesNo('bots_404', ts('Respond with a 404 page not found error?', array('domain' => 'ca.bidon.reporterror')), FALSE, TRUE);
$this->add('text', 'bots_regexp',
ts('Bots to ignore', array('domain' => 'ca.bidon.reporterror')),
TRUE);
$this->addButtons(array(
array(
'type' => 'submit',
'name' => ts('Save'),
'isDefault' => TRUE,
),
array(
'type' => 'cancel',
'name' => ts('Cancel'),
),
));
}
/**
* Function to process the form
*
* @access public
* @return None
*/
public function postProcess() {
// store the submitted values in an array
$values = $this->exportValues();
$fields = array(
'noreferer_handle',
'noreferer_pageid',
'noreferer_sendreport',
'noreferer_handle_event',
'noreferer_handle_eventid',
'noreferer_sendreport_event',
'mailto',
'show_full_backtrace',
'show_post_data',
'show_session_data',
'bots_sendreport',
'bots_404',
'bots_regexp',
);
foreach ($fields as $field) {
$value = $values[$field];
$result = CRM_Core_BAO_Setting::setItem($value, REPORTERROR_SETTINGS_GROUP, $field);
}
// we will return to this form by default
CRM_Core_Session::setStatus(ts('Settings saved.', array('domain' => 'ca.bidon.reporterror')), '', 'success');
}
}
<?php
use CRM_ReportError_ExtensionUtil as E;
class CRM_ReportError_Admin_Form_Settings extends CRM_Admin_Form_Setting {
protected $_values;
protected $_settings = [
'reporterror_noreferer_handle' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_noreferer_pageid' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_noreferer_sendreport' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_noreferer_handle_event' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_noreferer_handle_eventid' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_noreferer_sendreport_event' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_handle_profile' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_sendreport_profile' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_mailto' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_show_full_backtrace' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_show_post_data' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_show_session_data' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_bots_sendreport' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_bots_404' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_bots_regexp' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_smartgroups_autodisable' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_gelf_enable' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_gelf_hostname' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'reporterror_gelf_port' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
];
/**
* Function to build the form
*
* @return None
* @access public
*/
public function buildQuickForm() {
$this->applyFilter('__ALL__', 'trim');
$this->add('text', 'reporterror_mailto',
E::ts('Error Report Recipient'),
CRM_Utils_Array::value('mailto', $this->_values),
FALSE);
$this->addYesNo('reporterror_show_full_backtrace', E::ts('Display a full backtrace in e-mails?'));
$this->addYesNo('reporterror_show_post_data', E::ts('Display POST data in e-mails?'));
$this->addYesNo('reporterror_show_session_data', E::ts('Display session data in e-mails?'));
// Special handling of Contribution page errors.
// Get a list of contribution pages
$results = civicrm_api3('ContributionPage', 'get', [
'is_active' => 1,
'option.limit' => 0,
]);
$contribution_pages = [
0 => ts('- Select -'),
];
foreach ($results['values'] as $val) {
$contribution_pages[$val['id']] = CRM_Utils_Array::value('title', $val);
}
$radio_choices = [
'0' => E::ts('Do nothing (show the CiviCRM error)'),
'1' => E::ts('Redirect to front page of CMS'),
'2' => E::ts('Redirect to a specific contribution page'),
];
$this->addRadio('reporterror_noreferer_handle',
E::ts('Enable transparent redirection?'),
$radio_choices,
array('options_per_line' => 1),
'<br/>' /* one option per line */
);
$this->addYesNo('reporterror_noreferer_sendreport', E::ts('Send error reports for this particular error?'));
$this->add('select', 'reporterror_noreferer_pageid',
E::ts('Redirect to Contribution Page'),
$contribution_pages,
TRUE);
// Special handling of Event page errors.
$results = civicrm_api3('Event', 'get', [
'is_active' => 1,
'option.limit' => 0,
]);
$event_pages = [
0 => ts('- Select -'),
];
foreach ($results['values'] as $val) {
$event_pages[$val['id']] = CRM_Utils_Array::value('title', $val);
}
$radio_choices = [
'0' => E::ts('Do nothing (show the CiviCRM error)'),
'1' => E::ts('Redirect to front page of CMS'),
'2' => E::ts('Redirect to a specific event registration page'),
];
$this->addRadio('reporterror_noreferer_handle_event',
E::ts('Enable transparent redirection?'),
$radio_choices,
array('options_per_line' => 1),
'<br/>' /* one option per line */
);
$this->addYesNo('reporterror_noreferer_sendreport_event', E::ts('Send error reports for this particular error?'));
$this->add('select', 'reporterror_noreferer_handle_eventid',
E::ts('Redirect to Event Page'),
$event_pages,
TRUE);
// Special handling of profiles
$radio_choices = [
'0' => E::ts('Do nothing (show the CiviCRM error)'),
'1' => E::ts('Redirect to front page of CMS'),
];
$this->addRadio('reporterror_handle_profile',
E::ts('Enable transparent redirection?'),
$radio_choices,
array('options_per_line' => 1),
'<br/>' /* one option per line */
);
$this->addYesNo('reporterror_sendreport_profile', E::ts('Send error reports for this particular error?'));
// Special handling of bots
$this->addYesNo('reporterror_bots_sendreport', E::ts('Send error reports for errors caused by bots?'));
$this->addYesNo('reporterror_bots_404', E::ts('Respond with a 404 page not found error?'));
$this->add('text', 'reporterror_bots_regexp', E::ts('Bots to ignore'), TRUE);
// Smartgroups
$this->addYesNo('reporterror_smartgroups_autodisable', E::ts('Automatically disable broken smartgroups?'));
// Remote Logging
$this->addYesNo('reporterror_gelf_enable', E::ts('Enable remote logging?'));
$this->add('text', 'reporterror_gelf_hostname', E::ts('Logging server hostname'));
$this->add('text', 'reporterror_gelf_port', E::ts('Logging server port'));
$this->addButtons([
array(
'type' => 'submit',
'name' => ts('Save'),
'isDefault' => TRUE,
),
array(
'type' => 'cancel',
'name' => ts('Cancel'),
),
]);
}
/**
* Function to process the form
*
* @access public
* @return None
*/
public function postProcess() {
// store the submitted values in an array
$values = $this->exportValues();
foreach ($this->_settings as $setting => $group) {
$value = $values[$setting];
Civi::settings()->set($setting, $value);
}
// Return back to this form by default
CRM_Core_Session::setStatus(E::ts('Settings saved.'), '', 'success');
CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/setting/reporterror', 'reset=1'));
}
}
<?php
class CRM_ReportError_Handler_FormsNoReferer {
/**
* Contribution or Event forms: if an error was generated, but there was no HTTP_REFERER,
* it is most likely a bot, a restored session, or copy-pasted link. Those users should be
* redirected to a more appropriate page, instead of fatal error.
*
* Typical use-case: someone copy-pasted a link to a contribution form, but they did not
* select the arguments of the URL, so it directs people to /civicrm/contribution/transact,
* which fatals because there is no 'id' present.
*/
static public function handler($vars, $options_overrides) {
$redirect_path = NULL;
$redirect_options = array();
$sendreport = TRUE;
$config = CRM_Core_Config::singleton();
$urlVar = $config->userFrameworkURLVar;
$arg = explode('/', $_GET[$urlVar]);
// Redirect for Contribution pages without a referrer (close / restore browser page)
if ($arg[0] == 'civicrm' && $arg[1] == 'contribute' && $arg[2] == 'transact' && ! $_SERVER['HTTP_REFERER'] && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
$handle = reporterror_setting_get('reporterror_noreferer_handle', $options_overrides);
$pageid = reporterror_setting_get('reporterror_noreferer_pageid', $options_overrides);
$sendreport = reporterror_setting_get('reporterror_noreferer_sendreport', $options_overrides, 1);
if ($handle == 1 || ($handle == 2 && ! $pageid)) {
$redirect_path = CRM_Utils_System::baseCMSURL();
}
elseif ($handle == 2) {
$redirect_path = CRM_Utils_System::url('civicrm/contribute/transact', 'reset=1&id=' . $pageid);
}
}
elseif ($arg[0] == 'civicrm' && $arg[1] == 'event' && ! $_SERVER['HTTP_REFERER'] && $_SERVER['REQUEST_METHOD'] != 'HEAD') {
$handle = reporterror_setting_get('reporterror_noreferer_handle_event', $options_overrides);
$pageid = reporterror_setting_get('reporterror_noreferer_handle_eventid', $options_overrides);
$sendreport = reporterror_setting_get('reporterror_noreferer_sendreport_event', $options_overrides, 1);
if ($handle == 1 || ($handle == 2 && ! $pageid)) {
$redirect_path = CRM_Utils_System::baseCMSURL();
}
elseif ($handle == 2) {
$redirect_path = CRM_Utils_System::url('civicrm/event/register', 'reset=1&id=' . $pageid);
}
}
if ($sendreport) {
if ($redirect_path) {
$vars['reporterror_subject'] = ts('redirected', array('domain' => 'ca.bidon.reporterror'));
}
CRM_ReportError_Utils::sendReport($vars, $options_overrides);
}
// A redirection avoids displaying the error to the user.
if ($redirect_path) {
// 307 = temporary redirect. Assuming it reduces the chances that the browser
// keeps the redirection in cache.
CRM_Utils_System::redirect($redirect_path);
return TRUE;
}
return FALSE;
}
}
<?php
use CRM_ReportError_ExtensionUtil as E;
class CRM_ReportError_Handler_SmartGroupRefresh {
/**
* Try to handle a failing smartgroup refresh.
* This will automatically disable a broken smartgroup.
*/
static public function handler($vars, $options_overrides) {
if (!isset($vars['exception']) && !isset($vars['pearError'])) {
return FALSE;
}
if (!Civi::settings()->get('reporterror_smartgroups_autodisable')) {
return FALSE;
}
$sql = NULL;
$error_message = NULL;
if (empty($sql) && isset($vars['exception']) && method_exists($vars['exception'], 'getExtraParams')) {
$extra_params = $vars['exception']->getExtraParams();
if (isset($extra_params['sql'])) {
$sql = $extra_params['sql'];
}
$error_message = $vars['exception']->getMessage();
}
if (empty($sql) && isset($vars['pearError'])) {
if (!empty($vars['pearError']->userinfo)) {
$sql = $vars['pearError']->userinfo;
}
$error_message = $vars['pearError']->message;
}
if (preg_match('/^CREATE TEMPORARY TABLE civicrm_temp_group_contact_cache\d+ \(SELECT (\d+) as group_id/', $sql, $matches)) {
$broken_group_id = $matches[1];
$output = [
'data' => [],
];
$result = civicrm_api3('Group', 'getsingle', [
'group_id' => $broken_group_id,
]);
$description = ($result['description'] ? $result['description'] . ' -- ' : '') . 'Disabled automatically by reporterror: ' . $error_message;
civicrm_api3('Group', 'create', [
'group_id' => $broken_group_id,
'description' => $description,
'is_active' => 0,
]);
if (CRM_Utils_Array::value('update_smart_groups', $_REQUEST) == 1) {
CRM_Core_Session::setStatus(E::ts('ERROR: Group ID %1 could not be loaded and has been disabled. This may be the result of a deleted custom field or a bug in a custom search.', [1 => $broken_group_id]), '', 'error');
CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/group', 'reset=1'));
return TRUE;
}
else {
// Assumes this is while the main database was being loaded on /civicrm/group?reset=1
$output['data'][] = [
'id' => 99999,
'count' => 1,
'title' => E::ts('ERROR: Group ID %1 could not be loaded and has been disabled. This may be the result of a deleted custom field or a bug in a custom search.', [1 => $broken_group_id]),
'description' => '',
'group_type' => '',
'visibility' => '',
'links' => '',
'created_by' => '',
'DT_RowId' => 'row_99999',
'DT_RowClass' => 'crm-group-parent',
'DT_RowAttr' => [
'data-id' => 99999,
'data-entity' => 'group',
],
];
echo json_encode($output);
}
$vars['reporterror_subject'] = "SmartGroupRefresh";
CRM_ReportError_Utils::sendReport($vars, $options_overrides);
return TRUE;
}
return FALSE;
}
}
<?php
use CRM_ReportError_ExtensionUtil as E;
/**
* Collection of upgrade steps.
*/
class CRM_ReportError_Upgrader extends CRM_ReportError_Upgrader_Base {
// By convention, functions that look like "function upgrade_NNNN()" are
// upgrade tasks. They are executed in order (like Drupal's hook_update_N).
/**
* Example: Run an external SQL script when the module is installed.
*
public function install() {
$this->executeSqlFile('sql/install.sql');
}
/**
* This method can be used for any post-install tasks. For example, if a step
* of your installation depends on accessing an entity that is itself
* created during the installation (e.g., a setting or a managed entity), do
* so here to avoid order of operation problems.
*
public function postInstall() {
}
/**
* Run an external SQL script when the module is uninstalled.
*
public function uninstall() {
$this->executeSqlFile('sql/uninstall.sql');
}
/**
* Run a simple query when a module is enabled.
*
public function enable() {
}
/**
* Run a simple query when a module is disabled.
*
public function disable() {