function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next)
 {
     /** @var ResponseInterface $response */
     $response = $next();
     $lang = $this->locale->locale();
     // The check for app->translation is made here instead of conditionally adding this middleware
     // because loaded modules can change this setting.
     if (!$this->settings->translation || !$lang) {
         return $response;
     }
     if (!isset(self::$translation[$lang])) {
         // Load and merge all translation files now.
         self::$translation[$lang] = [];
         $trans =& self::$translation[$lang];
         $folders = $this->settings->languageFolders;
         foreach ($folders as $folder) {
             $path = "{$folder}/{$lang}.ini";
             $newTrans = fileExists($path) ? parse_ini_file($path) : null;
             if ($newTrans) {
                 $trans = array_merge($trans, $newTrans);
             }
         }
         if (!$trans) {
             $paths = array_map(function ($path) {
                 return "<li>" . ErrorConsole::shortFileName($path);
             }, $folders);
             throw new ConfigException("A translation file for language <b>{$lang}</b> was not found.\n<p>Search paths:\n<ul>" . implode('', $paths) . "</ul>", FlashType::ERROR);
         }
     }
     $out = preg_replace_callback(self::FIND_TRANS_KEY, function ($args) use($lang) {
         $a = $args[1];
         return empty(self::$translation[$lang][$a]) ? '$' . $a : preg_replace('#\\r?\\n#', '<br>', self::$translation[$lang][$a]);
     }, $response->getBody());
     return $response->withBody($this->responseFactory->makeBody($out));
 }
Exemplo n.º 2
0
 function render(ServerRequestInterface $request, ResponseInterface $response, $error = null)
 {
     if ($error) {
         // On debug mode, a debugging error popup is displayed for Exceptions/Errors.
         if ($this->devEnv && Http::clientAccepts($request, 'text/html')) {
             return ErrorConsole::display($error, $this->responseFactory->makeHtmlResponse());
         }
         $status = $error instanceof HttpException ? $error->getCode() : 500;
         // Errors may contain an additional `getTitle()` method.
         if (method_exists($error, 'getTitle')) {
             // The title is assumed to be a plain, one-line string (no formatting). If not, make it so.
             $title = $error->getTitle();
             $message = $error->getMessage();
         } else {
             list($title, $message) = array_pad(explode(PHP_EOL, $error->getMessage(), 2), 2, '');
         }
         $response = $response->withStatus($status);
     } else {
         $status = $response->getStatusCode();
         $title = $response->getReasonPhrase();
         $message = strval($response->getBody());
     }
     /** @var ResponseInterface $response */
     $response = $response->withBody($body = $this->responseFactory->makeBody());
     // Otherwise, errors are rendered into a format accepted by the HTML client.
     if (Http::clientAccepts($request, 'text/html')) {
         $response = $response->withHeader('Content-Type', 'text/html');
         $customRenderer = $this->settings->getCustomRenderer($status);
         if ($customRenderer) {
             if ($customRenderer instanceof RenderableInterface) {
                 $class = $customRenderer->getContextClass();
                 $customRenderer->setContext($this->injector->make($class));
             }
             $response = $customRenderer($request, $response, nop());
         } else {
             ob_start();
             $this->htmlTemplate($status, $title, $message);
             $body->write(ob_get_clean());
         }
     } else {
         $title = strip_tags($title);
         $message = strip_tags($message);
         if (Http::clientAccepts($request, 'text/plain') || Http::clientAccepts($request, '*/*')) {
             $response = $response->withHeader('Content-Type', 'text/plain');
             $body->write("{$title}\n{$message}");
         } elseif (Http::clientAccepts($request, 'application/json')) {
             $response = $response->withHeader('Content-Type', 'application/json');
             $body->write(json_encode(['error' => ['code' => $status, 'message' => $title, 'info' => $message]], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
         } elseif (Http::clientAccepts($request, 'application/xml')) {
             $response = $response->withHeader('Content-Type', 'application/xml');
             $body->write("<?xml version=\"1.0\"?><error><code>{$status}</code><message>{$title}</message><info>{$message}</info></error>");
         }
     }
     // else render nothing
     return $response;
 }
Exemplo n.º 3
0
 /**
  * Initializes the web server and sets up the request object.
  */
 function setup()
 {
     /** @var ServerRequestInterface $request */
     $request = ServerRequestFactory::fromGlobals();
     $baseUrl = dirnameEx(get($request->getServerParams(), 'SCRIPT_NAME'), $this->kernelSettings->urlDepth + 1);
     $this->kernelSettings->baseUrl = $baseUrl;
     ErrorConsole::setEditorUrl(($baseUrl ? "{$baseUrl}/" : '') . $this->kernelSettings->editorUrl);
     $request = $request->withAttribute('originalUri', $request->getUri());
     $request = $request->withAttribute('baseUri', $this->kernelSettings->baseUrl);
     $this->request = $request->withAttribute('virtualUri', $this->getVirtualUri($request));
 }
Exemplo n.º 4
0
 public static function globalExceptionHandler($exception)
 {
     $handled = false;
     if (ErrorConsole::$devEnv) {
         ErrorConsole::display($exception);
         $handled = true;
     }
     if (self::$nextExceptionHandler) {
         call_user_func(self::$nextExceptionHandler, $exception);
     }
     if (!$handled) {
         @ob_end_clean();
         echo "<style>body{background:silver}table {font-family:Menlo,sans-serif;font-size:12px}</style>";
         throw $exception;
     }
     exit;
 }
Exemplo n.º 5
0
 /**
  * @param string $rootDir
  */
 private function setupDebugging($rootDir)
 {
     set_exception_handler([$this, 'exceptionHandler']);
     $devEnv = env('DEV');
     $this->injector->defineParam('devEnv', $devEnv);
     $webConsole = env('CONSOLE');
     $this->injector->defineParam('webConsole', $webConsole);
     ErrorConsole::init($devEnv, $rootDir);
     ErrorConsole::setAppName($this->kernelSettings->appName);
     // Note: the editorUrl can't be set yet. See: WebServer.
     $settings = new DebugConsoleSettings();
     $settings->defaultPanelTitle = 'Inspector';
     $settings->defaultPanelIcon = 'fa fa-search';
     DebugConsole::init($devEnv, $settings);
     // Temporarily set framework path mapping here for errors thrown during modules loading.
     ErrorConsole::setPathsMap($this->kernelSettings->getMainPathMap());
 }
Exemplo n.º 6
0
   /**
    * Outputs a stack trace up to the first call to a trace function (which may be this one or a wrapper that calls
    * this one).
    * <p>It displays detailed timing and memory consumption information about each function/method call.
    *
    * <p>It requires a logger panel named 'trace' to be defined.
    * <p>It also requires XDebug to be installed.
    *
    * ##### Usage
    *
    * Put the following code at the place where you want the trace log to be captured:
    *
    *       \PhpKit\WebConsole\DebugConsole\DebugConsole::trace ();
    *
    * @throws Exception
    */
   public static function trace()
   {
       if (!extension_loaded('xdebug')) {
           throw new Exception("<kbd>trace()</kbd> requires Xdebug to be installed.");
       }
       $v = ini_get('xdebug.collect_params');
       ob_start();
       ini_set('xdebug.collect_params', 2);
       xdebug_print_function_stack();
       $trace = ob_get_clean();
       $trace = preg_replace('@^(?:.*?)<table class=\'xdebug-error xe-xdebug\'(.*?)<tr>(?:.*?)>Location</th></tr>@s', '<table class="__console-table trace"$1<colgroup>
 <col width=40><col width=72><col width=72><col width=72><col width=75%><col width=25%>
 <thead><tr><th>#<th>Time (ms)<th>Delta (ms)<th>Mem.(MB)<th>Function<th>Location</tr></thead>', $trace);
       $trace = preg_replace(['@</table>.*@s', "/align='center'/", '@(trace\\(  \\)</td>.*?</tr>)(.*)</table>@s'], ['</table>', 'align=right', '$1</table>'], $trace);
       $prev = 0;
       $trace = preg_replace_callback('#<tr><td (.*?)>(.*?)</td><td (.*?)>(.*?)</td><td (.*?)>(.*?)</td><td (.*?)>(.*?)</td><td title=\'(.*?)\'(.*?)>(.*?)</td></tr>#', function ($m) use(&$prev) {
           $t = $m[4] * 1000;
           $s = $t - $prev;
           $d = number_format($s, 1);
           $dd = $s >= self::PROFILER_WARNING_TRESHOLD ? ' class=__alert' : '';
           $prev = $t;
           $t = number_format($t, 1);
           $r = number_format($m[6] / 1048576, 3);
           $p = ErrorConsole::shortFileName($m[9]);
           $f = substr($m[11], 3);
           list($fn, $args) = explode('(', $m[8], 2);
           $info = preg_replace('/[\\w{}]+$/', '<b>$0</b>', $fn) . '(' . $args;
           return "<tr><th {$m['1']}>{$m['2']}<td {$m['3']}>{$t}<td align=right{$dd}>{$d}<td {$m['5']}>{$r}<td {$m['7']}>{$info}<td class='__type' title='{$p}'{$m['10']}>{$f}</tr>";
       }, $trace);
       ini_set('xdebug.collect_params', $v);
       self::logger('trace')->write($trace);
   }
Exemplo n.º 7
0
    public function showCallLocation()
    {
        $namespace = Debug::libraryNamespace();
        $base = __DIR__;
        $stack = debug_backtrace(0);
        $FNS = self::GLOBAL_LOG_FNS;
        // Discard frames of all functions that belong to this library.
        while (!empty($stack) && (isset($stack[0]['file']) && stripos($stack[0]['file'], $base) === 0 || isset($stack[0]['class']) && stripos($stack[0]['class'], $namespace) === 0 || isset($stack[0]['function']) && !isset($FNS[$stack[0]['function']]))) {
            array_shift($stack);
        }
        $trace = $stack ? $stack[0] : [];
        $path = isset($trace['file']) ? $trace['file'] : '';
        $line = isset($trace['line']) ? $trace['line'] : '';
        $shortPath = ErrorConsole::shortFileName($path);
        $shortPath = str_segmentsLast($shortPath, '/');
        $location = empty($line) ? $shortPath : ErrorConsole::errorLink($path, $line, 1, "{$shortPath}:{$line}", 'hint--rounded hint--left', 'data-hint');
        if ($path != '') {
            $path = <<<HTML
<div class="__debug-location">At {$location}</div>
HTML;
        }
        $this->write($path);
        return $this;
    }
    /**
     * Note: if the exception has a `getTitle()` method, that value is displayed as the popup's header, otherwise the
     * exception's class name will be shown instead.
     *
     * @param Exception|Error $exception
     * @param string          $popupTitle
     * @param string          $stackTrace
     */
    static function renderPopup($exception, $popupTitle, $stackTrace)
    {
        self::renderStyles();
        ?>
    <!DOCTYPE HTML><html>

    <head>
      <meta charset="UTF-8">
      <title><?php 
        echo $popupTitle;
        ?>
</title>
    </head>

    <body id="__error">
      <div id="__panel">
        <div class="__title-bar"><?php 
        echo $popupTitle;
        ?>
</div>
        <div class="__panel-body">
          <div id="__feedback">Please switch to PHPStorm/IDEA to view the code at the error location.</div>
          <img src="<?php 
        echo self::getIcon();
        ?>
">
          <div class="__message">
            <?php 
        $title = method_exists($exception, 'getTitle') ? $exception->getTitle() : self::friendlyClass(get_class($exception));
        if ($title) {
            echo "<h3>{$title}</h3>";
        }
        echo "<div>" . ucfirst(ErrorConsole::processMessage($exception->getMessage())) . "</div>";
        if (!empty($exception->info)) {
            echo "<div class='__info'>{$exception->info}</div>";
        }
        ?>
          </div>
          <div id="__error-location">
            <?php 
        $link = ErrorConsole::errorLink($exception->getFile(), $exception->getLine(), 1);
        if ($link) {
            echo "Thrown from {$link}, line <b>{$exception->getLine()}</b>";
        }
        ?>
            <div class="__more">
              <a id="__more"
                 class=" __btn"
                 href="javascript:void(document.getElementById('__panel').className='__show')"
                 onclick="this.style.display='none';window.setTimeout(function(){document.body.scrollTop=document.getElementById('__error-location').offsetTop})"> Stack trace
                <span style="font-size:16px">&blacktriangledown;</span></a>
            </div>
          </div>
        </div>
        <div id="__trace">
          <?php 
        echo $stackTrace;
        ?>
        </div>
        <iframe name="hidden" style="display:none"></iframe>
    </body><html>
    <?php 
    }
Exemplo n.º 9
0
 /**
  * Shortcut to log a formatted exception on the provided logger.
  *
  * @param LoggerInterface $logger
  * @param Exception       $exception
  */
 public static function logException(LoggerInterface $logger, Exception $exception)
 {
     $logger->error(sprintf("%s, at %s(%s)", $exception->getMessage(), ErrorConsole::shortFileName($exception->getFile()), $exception->getLine()));
 }
Exemplo n.º 10
0
 /**
  * @param \Error|\Exception $e
  * @param Expression        $exp
  * @throws ComponentException
  */
 private function evalError($e, Expression $exp)
 {
     throw new ComponentException($this, Debug::grid(['Expression' => Debug::RAW_TEXT . "<kbd>{$exp}</kbd>", 'Compiled' => sprintf('%s<code>%s</code>', Debug::RAW_TEXT, \PhpCode::highlight("{$exp->translated}")), 'Error' => sprintf('%s%s %s', Debug::RAW_TEXT, Debug::typeInfoOf($e), $e->getMessage()), 'At' => sprintf('%s%s, line <b>%s</b>', Debug::RAW_TEXT, ErrorConsole::errorLink($e->getFile(), $e->getLine()), $e->getLine())], 'Error while evaluating data-binding expression'));
 }
Exemplo n.º 11
0
 /**
  * For use by renderers.
  *
  * @param string $msg
  * @return string
  */
 public static function processMessage($msg)
 {
     $msg = preg_replace_callback('#<path>([^<]*)</path>#', function ($m) {
         return ErrorConsole::errorLink($m[1], 1, 1, basename($m[1]));
     }, $msg);
     return $msg;
 }