timer('check_' . __CLASS__, self::CHECK_TIMER)) {
// Best attempt at re-securing folders
$config = CRM_Core_Config::singleton();
$config->cleanup(0, FALSE);
if ($messages === NULL) {
$messages = $this->checkAll();
}
$statusMessages = array();
$statusType = 'alert';
foreach ($messages as $message) {
if ($filter === TRUE || $message->getSeverity() >= 3) {
$statusType = $message->getSeverity() >= 4 ? 'error' : $statusType;
$statusMessage = $message->getMessage();
$statusMessages[] = $statusTitle = $message->getTitle();
}
}
if (count($statusMessages)) {
if (count($statusMessages) > 1) {
$statusTitle = ts('Multiple Alerts');
$statusMessage = ts('Please check your status page for a full list and further details.', array(1 => CRM_Utils_System::url('civicrm/a/#/status'))) . '
- ' . implode('
- ', $statusMessages) . '
';
}
// @todo add link to status page
CRM_Core_Session::setStatus($statusMessage, $statusTitle, $statusType);
}
}
}
}
/**
* Sort messages based upon severity
*
* @param CRM_Utils_Check_Message $a
* @param CRM_Utils_Check_Message $b
* @return int
*/
public static function severitySort($a, $b) {
$aSeverity = $a->getSeverity();
$bSeverity = $b->getSeverity();
if ($aSeverity == $bSeverity) {
return strcmp($a->getName(), $b->getName());
}
// The Message constructor guarantees that these will always be integers.
return ($aSeverity < $bSeverity);
}
/**
* Get the integer value (useful for thresholds) of the severity.
*
* @param int|const $severity
* the value to look up
* @param bool $reverse
* whether to find the constant from the integer
* @return bool
*/
public static function severityMap($severity, $reverse = FALSE) {
// Lowercase string-based severities
if (!$reverse) {
$severity = strtolower($severity);
}
// See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
$levels = array(
\Psr\Log\LogLevel::EMERGENCY => 7,
\Psr\Log\LogLevel::ALERT => 6,
\Psr\Log\LogLevel::CRITICAL => 5,
\Psr\Log\LogLevel::ERROR => 4,
\Psr\Log\LogLevel::WARNING => 3,
\Psr\Log\LogLevel::NOTICE => 2,
\Psr\Log\LogLevel::INFO => 1,
\Psr\Log\LogLevel::DEBUG => 0,
);
return ($reverse) ? array_search($severity, $levels) : $levels[$severity];
}
/**
* Throw an exception if any of the checks fail.
*
* @param array|NULL $messages list of CRM_Utils_Check_Message; or NULL if the default list should be fetched
*
* @throws Exception
*/
public function assertValid($messages = NULL) {
if ($messages === NULL) {
$messages = $this->checkAll();
}
if (!empty($messages)) {
$messagesAsArray = array();
foreach ($messages as $message) {
$messagesAsArray[] = $message->toArray();
}
throw new Exception('There are configuration problems with this installation: ' . print_r($messagesAsArray, TRUE));
}
}
/**
* Run some sanity checks.
*
* This could become a hook so that CiviCRM can run both built-in
* configuration & sanity checks, and modules/extensions can add
* their own checks.
*
* We might even expose the results of these checks on the Wordpress
* plugin status page or the Drupal admin/reports/status path.
*
* @param bool $max
* Whether to return just the maximum non-hushed severity
*
* @return array
* Array of messages
* @link https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_requirements
*/
public static function checkAll($max = FALSE) {
$checks = array();
$checks[] = new CRM_Utils_Check_Security();
$checks[] = new CRM_Utils_Check_Env();
$compInfo = CRM_Core_Component::getEnabledComponents();
foreach ($compInfo as $compObj) {
switch ($compObj->info['name']) {
case 'CiviCase':
$checks[] = new CRM_Utils_Check_Case(CRM_Case_XMLRepository::singleton(), CRM_Case_PseudoConstant::caseType('name'));
break;
default:
}
}
$messages = array();
foreach ($checks as $check) {
$messages = array_merge($messages, $check->checkAll());
}
CRM_Utils_Hook::check($messages);
foreach ($messages as $key => $message) {
$hush = self::checkHushSnooze($message);
$message->setVisible(!$hush);
}
uasort($messages, array(__CLASS__, 'severitySort'));
$maxSeverity = 1;
foreach ($messages as $message) {
if (!$message->isVisible()) {
continue;
}
$maxSeverity = max(1, $message->getLevel());
break;
}
Civi::cache()->set('systemCheckSeverity', $maxSeverity);
$timestamp = time();
Civi::cache()->set('systemCheckDate', $timestamp);
return ($max) ? $maxSeverity : $messages;
}
/**
* Evaluate if a system check should be hushed/snoozed.
*
* @param string $message
*
* @return bool
* TRUE means hush/snooze, FALSE means display.
* @throws \CiviCRM_API3_Exception
*/
public static function checkHushSnooze($message) {
$statusPreferenceParams = array(
'name' => $message->getName(),
'domain_id' => CRM_Core_Config::domainID(),
);
// Check if there's a StatusPreference matching this name/domain.
$statusPreference = civicrm_api3('StatusPreference', 'get', $statusPreferenceParams);
$spid = FALSE;
if (isset($statusPreference['id'])) {
$spid = $statusPreference['id'];
}
if ($spid) {
// If so, compare severity to StatusPreference->severity.
$severity = $message->getSeverity();
if ($severity <= $statusPreference['values'][$spid]['ignore_severity']) {
// A hush or a snooze has been set. Find out which.
if (isset($statusPreference['values'][$spid]['hush_until'])) {
// Snooze is set.
$today = new DateTime();
$snoozeDate = new DateTime($statusPreference['values'][$spid]['hush_until']);
if ($today > $snoozeDate) {
// Snooze is expired.
return FALSE;
}
else {
// Snooze is active.
return TRUE;
}
}
else {
// Hush.
return TRUE;
}
}
}
return FALSE;
}
}