Example #1
0
 /**
  * Письмо админу с текущим сообщение лога.
  *
  * @return void
  */
 private function mailToAdmin()
 {
     $logIt = $this->logIt;
     if (!($mailTo = $this->conf['_mail'])) {
         $this->addTyped('Не задан email админа, не могу отправить сообщение от логера.', ILogger::ENGINE);
         return;
     }
     $domain = Env::domainName();
     $date = $logIt['ts']->format('Y/m/d H:i:s P');
     $rn = PHP_EOL;
     $letters['text'] = 'Сообщение от логера' . $rn . $rn . $logIt['message'] . $rn . $rn . "Тип: {$logIt['type']}{$rn}" . "Источник: {$logIt['source']}" . $rn . $rn . "URL запроса:{$logIt['request']}" . $rn . "IP юзера: {$logIt['userIP']}" . $rn . $rn . "{$date} (c) {$domain}";
     $vars = ['message' => nl2br($logIt['message']), 'type' => $logIt['type'], 'source' => $logIt['source'], 'request' => $logIt['request'], 'userIP' => $logIt['userIP'], 'date' => $date, 'homeURL' => Env::indexPage(), 'domain' => $domain];
     $letters['html'] = Render::fetch('log_letter.htm', $vars);
     $from = App::conf('noreply_mail') ?: "noreply@{$domain}";
     if (!Mailer::complex($from, $mailTo, "Сообщение от логера сайта {$domain}", $letters)) {
         $this->addTyped('Не удалось отправить сообщение от логера.', ILogger::ENGINE);
     }
 }
Example #2
0
 /**
  * Перехват ошибок PHP
  *
  * Свое оформление, трассировка и логирование. Если текущий тип ошибки отключен в error_reporting, то пишем
  * ее в temp-каталог приложения, в kira_php_error.log. Иначе - выдаем в браузер.
  *
  * Согласно мануала, такая функция вызывается независимо от настройки error_reporting. Поэтому проверяем, требуется
  * ли сообщать о полученной ошибке. Если да - рисуем ответ, иначе скидываем сообщение в лог. Обычно бывает так:
  * на локалке/деве всё включено - будут валиться сообщения в браузер. На проде все отключено - логируем.
  *
  * Опять же по мануалу, если этот обработчик не прервет выполнение вызвав die(), то программа продолжится. Если
  * вернет FALSE - ошибку получит стандартный обработчик и мы увидим еще и его сообщение. Поэтому делаем так:
  * если код соответствует какой-то ERROR - выходим; иначе возвращаем TRUE, чтоб стандартный обработчик
  * не дублировал сообщение в своем стиле.
  *
  * В случае фатальных ошибок трассировка вызовов уже неважна. К тому же я не могу ее получить почему-то. Поэтому
  * в таких сообщениях не будет стека вызовов.
  *
  * По константам кодов см. {@see http://php.net/manual/ru/errorfunc.constants.php}
  * Ликбез: {@link https://habrahabr.ru/post/134499/}
  *
  * @param int    $code уровень ошибки в виде целого числа
  * @param string $msg  сообщение об ошибке в виде строки
  * @param string $file имя файла, в котором произошла ошибка
  * @param int    $line номер строки, в которой произошла ошибка
  * @return bool
  */
 public static function errorHandler($code, $msg, $file, $line)
 {
     $codes = [1 => 'FATAL ERROR', 2 => 'WARNING', 4 => 'PARSE ERROR', 8 => 'NOTICE', 16 => 'CORE ERROR', 32 => 'CORE WARNING', 64 => 'COMPILE ERROR', 128 => 'COMPILE WARNING', 256 => 'USER ERROR', 512 => 'USER WARNING', 1024 => 'USER NOTICE', 2048 => 'STRICT', 4096 => 'RECOVERABLE ERROR', 8192 => 'DEPRECATED', 16384 => 'USER DEPRECATED'];
     $codeTxt = $codes[$code];
     $file = str_replace(ROOT_PATH, '', $file);
     $stack_html = $stack_console = '';
     if (($code & (E_ERROR | E_PARSE | E_COMPILE_ERROR)) == 0) {
         $trace = array_reverse(debug_backtrace());
         array_pop($trace);
         foreach ($trace as $step) {
             $where = isset($step['file']) ? str_replace(ROOT_PATH, '', $step['file']) . ':' . $step['line'] : '';
             $func = isset($step['class']) ? $step['class'] . $step['type'] . $step['function'] : $step['function'];
             if (isset($step['args'])) {
                 $args = $step['args'];
                 array_walk($args, function (&$i) {
                     if (is_string($i)) {
                         $i = "'{$i}'";
                     } elseif (is_array($i)) {
                         $i = '[array]';
                     } elseif (is_bool($i)) {
                         $i = $i ? 'true' : 'false';
                     } elseif (is_object($i)) {
                         $i = get_class($i);
                     }
                 });
                 $args = implode(', ', $args);
             } else {
                 $args = '';
             }
             $stack_html .= "<tr><td class='php-err-txtright'>{$where}</td><td>{$func}({$args})</td></tr>" . PHP_EOL;
             $stack_console .= "{$where} > {$func}({$args})" . PHP_EOL;
         }
         $stack_html = "\n                <p>Стек вызова в хронологическом порядке:</p>\n                <table class = 'php-err-stack'>\n                    {$stack_html}\n                </table>\n            ";
     }
     $rn = PHP_EOL;
     if (error_reporting() & $code) {
         if (isConsoleInterface()) {
             echo "{$rn}{$codeTxt}{$rn}{$rn}\t{$msg}{$rn}{$rn}" . "Стек вызовов:{$rn}{$rn}" . $stack_console . "{$rn}";
         } else {
             if (!headers_sent()) {
                 header('500 Internal Server Error');
                 header('Content-Type: text/html; charset=UTF-8');
             }
             $msg = nl2br(htmlspecialchars($msg, ENT_QUOTES, 'UTF-8'));
             echo Render::fetch('error_handler.htm', compact('codeTxt', 'msg', 'file', 'line', 'stack_html'));
         }
     } else {
         $info = "{$codeTxt}{$rn}{$rn}\t{$msg}{$rn}{$rn}" . 'в ' . date('Y.m.d. H:i:s') . "{$rn}{$rn}" . "Стек вызовов:{$rn}{$rn}" . $stack_console . "{$rn}---{$rn}{$rn}";
         file_put_contents(TEMP_PATH . 'kira_php_error.log', $info, FILE_APPEND);
         return false;
     }
     if ($code & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR)) {
         exit;
     } else {
         return true;
     }
 }