Exemple #1
0
 public static function errorHandler($errorLevel, $errorDesc, $filePath, $line)
 {
     // If any error processing is enabled, this function is called by the PHP runtime on a failed assertion or
     // runtime error.
     settype($errorLevel, "int");
     settype($line, "int");
     $reportThisError = true;
     if (CConfiguration::isInitialized()) {
         $errorReportingLevel = constant(CConfiguration::option("debug.errorReportingLevel"));
         if ($errorLevel & $errorReportingLevel == 0) {
             $reportThisError = false;
         }
     }
     if ($reportThisError) {
         // Avoid double reporting of the same error if the method registered with `register_shutdown_function` is
         // called by the runtime after an error occurred.
         $errorFileAndLine = [];
         $errorFileAndLine["file"] = $filePath;
         $errorFileAndLine["line"] = $line;
         self::$ms_processedErrors[] = $errorFileAndLine;
         $strErrorLevel;
         switch ($errorLevel) {
             case E_ERROR:
                 // 1
                 $strErrorLevel = "E_ERROR";
                 break;
             case E_WARNING:
                 // 2
                 $strErrorLevel = "E_WARNING";
                 break;
             case E_PARSE:
                 // 4
                 $strErrorLevel = "E_PARSE";
                 break;
             case E_NOTICE:
                 // 8
                 $strErrorLevel = "E_NOTICE";
                 break;
             case E_CORE_ERROR:
                 // 16
                 $strErrorLevel = "E_CORE_ERROR";
                 break;
             case E_CORE_WARNING:
                 // 32
                 $strErrorLevel = "E_CORE_WARNING";
                 break;
             case E_COMPILE_ERROR:
                 // 64
                 $strErrorLevel = "E_COMPILE_ERROR";
                 break;
             case E_COMPILE_WARNING:
                 // 128
                 $strErrorLevel = "E_COMPILE_WARNING";
                 break;
             case E_USER_ERROR:
                 // 256
                 $strErrorLevel = "E_USER_ERROR";
                 break;
             case E_USER_WARNING:
                 // 512
                 $strErrorLevel = "E_USER_WARNING";
                 break;
             case E_USER_NOTICE:
                 // 1024
                 $strErrorLevel = "E_USER_NOTICE";
                 break;
             case E_STRICT:
                 // 2048
                 $strErrorLevel = "E_STRICT";
                 break;
             case E_RECOVERABLE_ERROR:
                 // 4096
                 $strErrorLevel = "E_RECOVERABLE_ERROR";
                 break;
             case E_DEPRECATED:
                 // 8192
                 $strErrorLevel = "E_DEPRECATED";
                 break;
             case E_USER_DEPRECATED:
                 // 16384
                 $strErrorLevel = "E_USER_DEPRECATED";
                 break;
             default:
                 $strErrorLevel = (string) $errorLevel;
                 break;
         }
         $time = gmdate(self::$ms_logRecordDateTimePattern, time());
         $fileRelPath = str_replace(realpath($GLOBALS["PHRED_PATH_TO_FRAMEWORK_ROOT"]) . "/", "", $filePath);
         $isAssertWithVars = is_int(strpos($errorDesc, self::$ms_assertVarsMarker));
         $errorDesc = preg_replace("/\\n{2,}/", "\n", $errorDesc);
         if (!$isAssertWithVars) {
             // In case of an assert without vars.
             $errorDesc = preg_replace("/^assert\\(\\)\\s*:\\s*/", "", $errorDesc);
         } else {
             $errorDesc = preg_replace("/^[^\\n]*\\n(.*)" . self::$ms_assertVarsMarker . "\\s*:\\s*([\"'][^\\n]*)\\s*\\z/s", "\$2 ({$strErrorLevel})\n\$1", $errorDesc);
             if (preg_match("/^\\s*assert/i", $errorDesc) !== 1) {
                 $errorDesc = "Assertion {$errorDesc}";
             }
         }
         // Backtrace.
         ob_start();
         debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
         $backtrace = ob_get_clean();
         $backtrace = preg_replace("/\\n{2,}/", "\n", $backtrace);
         $backtrace = preg_replace("/^\\s*#.*?(?=#)/s", "", $backtrace);
         // remove the first line that is useless
         $backtrace = str_replace(realpath($GLOBALS["PHRED_PATH_TO_FRAMEWORK_ROOT"]) . "/", "", $backtrace);
         $backtrace = preg_replace("/\\s+\\z/", "", $backtrace);
         // Format the error message.
         if (!$isAssertWithVars) {
             $errorMessage = "[Time:] {$time}\n\n[Location:] {$fileRelPath}, line {$line}\n\n{$errorDesc} ({$strErrorLevel})\n\n" . "[Backtrace:]\n{$backtrace}\n";
         } else {
             $errorMessage = "[Time:] {$time}\n\n[Location:] {$fileRelPath}, line {$line}\n\n{$errorDesc}\n\n" . "[Backtrace:]\n{$backtrace}\n";
         }
         $logRecordSep = rtrim(str_repeat("- ", 60));
         $leSep = "\n\n{$logRecordSep}\n\n";
         if (self::$ms_logging) {
             // Log the record.
             $logRecord = "{$errorMessage}\n{$logRecordSep}\n\n";
             if (file_exists(self::$ms_errorLogFp)) {
                 // Check if log rotation needs to be performed for the error log.
                 $log = file_get_contents(self::$ms_errorLogFp);
                 $numRecords = substr_count($log, $leSep);
                 if ($numRecords >= self::$ms_maxNumRecordsInLog) {
                     $numDelFirstRecords = $numRecords - self::$ms_maxNumRecordsInLog + 1;
                     $pos;
                     for ($i = 0; $i < $numDelFirstRecords; $i++) {
                         $pos = !isset($pos) ? 0 : $pos + 1;
                         $pos = strpos($log, $leSep, $pos);
                     }
                     $log = substr($log, $pos);
                     $log = "\n{$logRecordSep}\n\n" . preg_replace("/^{$leSep}/", "", $log);
                     file_put_contents(self::$ms_errorLogFp, $log);
                 }
             } else {
                 file_put_contents(self::$ms_errorLogFp, "\n{$logRecordSep}\n\n");
             }
             file_put_contents(self::$ms_errorLogFp, $logRecord, FILE_APPEND);
         }
         if (self::$ms_mailing) {
             $doMail = true;
             $destDp = sys_get_temp_dir();
             $docRoot = isset($_SERVER["DOCUMENT_ROOT"]) ? $_SERVER["DOCUMENT_ROOT"] : "";
             $docRootHash = hash("crc32", $docRoot, false);
             $lastMailTimeFp = $destDp . "/" . self::$ms_lastMailingTimeFnPrefix . $docRootHash;
             if (file_exists($lastMailTimeFp)) {
                 $lastMailTime = (int) file_get_contents($lastMailTimeFp);
                 $lastMailTimeDiffSeconds = time() - $lastMailTime;
                 // If the difference is negative, which is wrong, the mailing should not be canceled.
                 if ($lastMailTimeDiffSeconds >= 0) {
                     if ($lastMailTimeDiffSeconds < self::$ms_minTimeBetweenSendMailHours * 3600) {
                         // Too little time has passed since the last mailing, so cancel this one.
                         $doMail = false;
                     }
                 }
             }
             if ($doMail) {
                 // Notify about the error by mail.
                 // Format the subject.
                 $subject = "Something curious was encountered on ";
                 // alternative: ""
                 $serverName = isset($_SERVER["SERVER_NAME"]) ? $_SERVER["SERVER_NAME"] : "";
                 $serverIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "";
                 $docRoot = isset($_SERVER["DOCUMENT_ROOT"]) ? basename($_SERVER["DOCUMENT_ROOT"]) : "";
                 if ($serverName !== "") {
                     $subject .= $serverName;
                     if ($serverIp !== "") {
                         $subject .= " ({$serverIp})";
                     }
                     if ($docRoot !== "") {
                         $subject .= " in ";
                     } else {
                         $subject .= "";
                         // alternative: ": "
                     }
                 }
                 if ($docRoot !== "") {
                     $subject .= "'{$docRoot}'";
                     // alternative: "'$docRoot': "
                 }
                 // Alternative:
                 // $subject .= "PHP Encountered a Problem";
                 // Compose the message.
                 $mailMessage = "{$subject}\n\n{$errorMessage}";
                 if (self::$ms_logging && file_exists(self::$ms_errorLogFp)) {
                     // Add the latest log records to the message.
                     $log = file_get_contents(self::$ms_errorLogFp);
                     $log .= "\n";
                     // to be able to use `-1` in `strrpos` below
                     $logLength = strlen($log);
                     $res = strrpos($log, $leSep, -1);
                     if (is_int($res)) {
                         for ($i = 0; $i < self::$ms_maxNumLatestLogRecordsInMailMessage; $i++) {
                             $res = strrpos($log, $leSep, $res - $logLength - 1);
                             if (!is_int($res)) {
                                 break;
                             }
                         }
                         if (!is_int($res)) {
                             $res = 0;
                         }
                         $latestRecords = substr($log, $res);
                         $latestRecords = trim($latestRecords);
                         $mailMessage .= "\n\n\n\n[Latest error log records, chronologically:]\n\n{$latestRecords}\n";
                     }
                 }
                 // Send.
                 self::$ms_mail->setSubject($subject);
                 self::$ms_mail->setBody($mailMessage);
                 self::$ms_mail->disableWordWrapping();
                 $numMailsSent = self::$ms_mail->send();
                 if ($numMailsSent > 0) {
                     file_put_contents($lastMailTimeFp, time());
                 }
             }
         }
     }
     // If a value other than `false` was returned, the error would not be shown in the output, regardless of
     // whether or not the PHP's "display_errors" option was enabled or disabled.
     return false;
 }
Exemple #2
0
 /**
  * @ignore
  */
 public static function onThirdPartyUpdateByPackageManager()
 {
     if (!self::isInCliMode()) {
         // This method can be run in CLI mode only.
         assert('false', vs(isset($this), get_defined_vars()));
     }
     $timeoutPause = new CTimeoutPause();
     CShell::speak("Processing third-party components ...");
     $tpDps = CFile::listDirectories(CFilePath::absolute($GLOBALS["PHRED_PATH_TO_THIRD_PARTY"]));
     $ignorePackages = CConfiguration::option("upd.thirdPartyOopWrappingIgnorePackages");
     $ignorePackagesL2 = CArray::filter($ignorePackages, function ($package) {
         return CString::find($package, "/");
     });
     $newTpDps = CArray::make();
     $len = CArray::length($tpDps);
     for ($i = 0; $i < $len; $i++) {
         $tpDp = $tpDps[$i];
         $dirName = CFilePath::name($tpDp);
         if (!CArray::find($ignorePackages, $dirName)) {
             $dpHasL2DirsToIgnore = CArray::find($ignorePackagesL2, $dirName, function ($packageL2, $dirName) {
                 return CString::equals(CFilePath::directory($packageL2), $dirName);
             });
             if (!$dpHasL2DirsToIgnore) {
                 CArray::push($newTpDps, $tpDp);
             } else {
                 $tpSubDps = CFile::listDirectories($tpDp);
                 $tpSubDps = CArray::filter($tpSubDps, function ($subDp) use($ignorePackagesL2) {
                     return !CArray::find($ignorePackagesL2, $subDp, function ($packageL2, $subDp) {
                         return CString::endsWith($subDp, $packageL2);
                     });
                 });
                 CArray::pushArray($newTpDps, $tpSubDps);
             }
         }
     }
     $tpDps = $newTpDps;
     $wrapProtectedMethods = CConfiguration::option("upd.thirdPartyOopWrappingInProtectedMethods");
     $wrapPrivateMethods = CConfiguration::option("upd.thirdPartyOopWrappingInPrivateMethods");
     static $s_stdPhpTag = "<?php";
     static $s_progressResolution = 0.05;
     $prevProgressDivR = 0;
     $tpDpsLen = CArray::length($tpDps);
     for ($i0 = 0; $i0 < $tpDpsLen; $i0++) {
         $tpFps = CFile::reFindFilesRecursive($tpDps[$i0], "/\\.php\\d?\\z/");
         $tpFpsLen = CArray::length($tpFps);
         for ($i1 = 0; $i1 < $tpFpsLen; $i1++) {
             $fileCode = CFile::read($tpFps[$i1]);
             if (!CString::find($fileCode, self::$ms_thirdPartyAlreadyOopWrappedMark)) {
                 $parser = new PhpParser\Parser(new PhpParser\Lexer());
                 try {
                     // Parse the code.
                     $statements = $parser->parse($fileCode);
                     // Wrap the code into OOP.
                     $traverser = new PhpParser\NodeTraverser();
                     $mainVisitor = new CMainVisitor($wrapProtectedMethods, $wrapPrivateMethods);
                     $traverser->addVisitor($mainVisitor);
                     $statements = $traverser->traverse($statements);
                     $wrappedCode = (new PhpParser\PrettyPrinter\Standard())->prettyPrint($statements);
                     $phpTagPos = CString::indexOf($wrappedCode, $s_stdPhpTag);
                     if ($phpTagPos == -1) {
                         $wrappedCode = "{$s_stdPhpTag}\n\n{$wrappedCode}";
                         $phpTagPos = 0;
                     }
                     $wrappedCode = CString::insert($wrappedCode, $phpTagPos + CString::length($s_stdPhpTag), "\n\n" . self::$ms_thirdPartyAlreadyOopWrappedMark);
                     // Save.
                     CFile::write($tpFps[$i1], $wrappedCode);
                 } catch (PhpParser\Error $parserError) {
                     CShell::say("\nPhpParser: " . $tpFps[$i1] . ", at line " . $parserError->getRawLine() . ": " . $parserError->getRawMessage());
                 }
             }
             $progress = (double) ($i0 / $tpDpsLen + 1 / $tpDpsLen * $i1 / $tpFpsLen);
             $progressDivR = CMathi::floor($progress / $s_progressResolution);
             if ($progressDivR != $prevProgressDivR) {
                 $perc = CMathi::round($progressDivR * $s_progressResolution * 100);
                 CShell::speak("{$perc}%");
             }
             $prevProgressDivR = $progressDivR;
         }
     }
     CShell::speak("100%");
     CShell::say("Done.");
     $timeoutPause->end();
 }
Exemple #3
0
// A function used in the OOP wrapping of third-party components.
function _is_non_tp_call()
{
    static $s_thirdPartyAbsDp;
    if (!isset($s_thirdPartyAbsDp)) {
        $s_thirdPartyAbsDp = realpath($GLOBALS["PHRED_PATH_TO_THIRD_PARTY"]);
    }
    $backTrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
    if (count($backTrace) < 2) {
        return true;
    }
    return strpos($backTrace[1]["file"], $s_thirdPartyAbsDp) !== 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// If xdebug is used, tell it that the recursion depth of 100 is not always enough.
ini_set("xdebug.max_nesting_level", 4096);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ready to initialize the framework.
CSystem::initializeFramework();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Register the aliases for the core classes.
$GLOBALS["PHRED_CLASS_ALIASES"] = CConfiguration::option("classaliases");
foreach ($GLOBALS["PHRED_CLASS_ALIASES"] as $className => $alias) {
    class_alias($className, $alias, true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Import OOP methods for the string type.
if (function_exists("register_primitive_type_handler")) {
    register_primitive_type_handler("string", "CUStringObject");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -