/**
  * Handles an exception by showing an appropriate
  * error page.
  */
 public function handleError(Exception $e, $server = null, array &$headers = null)
 {
     $displayErrors = $this->pieCrust->isDebuggingEnabled() || $this->pieCrust->getConfig()->getValue('site/display_errors');
     // If debugging is enabled, just display the error and exit.
     if ($displayErrors) {
         if ($e->getMessage() == '404') {
             //TODO: set header?
             piecrust_show_system_message('404');
             return;
         }
         $errorMessage = self::formatException($e, true);
         piecrust_show_system_message('error', $errorMessage);
         return;
     }
     // First of all, check that we're not running
     // some completely brand new and un-configured website.
     if ($this->isEmptySetup()) {
         piecrust_show_system_message('welcome');
         return;
     }
     // Generic error message in case we don't have anything custom.
     $errorMessage = "<p>We're sorry but something very wrong happened, and we don't know what. " . "We'll try to do better next time.</p>" . PHP_EOL;
     // Get the URI to the custom error page, and the error code.
     if ($e->getMessage() == '404') {
         HttpHeaderHelper::setOrAddHeader(0, 404, $headers);
         $errorPageUri = '_404';
     } else {
         HttpHeaderHelper::setOrAddHeader(0, 500, $headers);
         $errorPageUri = '_error';
     }
     // Get the error page's info.
     try {
         $errorPageUriInfo = UriParser::parseUri($this->pieCrust, $errorPageUri, UriParser::PAGE_URI_REGULAR);
     } catch (Exception $inner) {
         // What the f**k.
         piecrust_show_system_message('critical', $errorMessage);
         return;
     }
     // Render the error page (either a custom one, or a generic one).
     if ($errorPageUriInfo != null and is_file($errorPageUriInfo['path'])) {
         // We have a custom error page. Show it, or display
         // the "fatal error" page if even this doesn't work.
         try {
             $runner = new PieCrustRunner($this->pieCrust);
             $runner->runUnsafe($errorPageUri, $server, null, $headers);
         } catch (Exception $inner) {
             // Well there's really something wrong.
             piecrust_show_system_message('critical', $errorMessage);
         }
     } else {
         // We don't have a custom error page. Just show the generic
         // error page.
         $errorMessage = self::formatException($e, false);
         piecrust_show_system_message(substr($errorPageUri, 1), $errorMessage);
     }
 }
예제 #2
0
 /**
  * Runs PieCrust on the given URI with the given extra page rendering data,
  * but without any error handling.
  */
 public function runUnsafe($uri = null, array $server = null, $extraPageData = null, array &$headers = null)
 {
     // Create an execution context.
     $executionContext = $this->pieCrust->getEnvironment()->getExecutionContext(true);
     // Check the cache validity, and clean it automatically.
     if ($this->pieCrust->isCachingEnabled()) {
         $cacheInfo = new PieCrustCacheInfo($this->pieCrust);
         $cacheValidity = $cacheInfo->getValidity(true);
         $executionContext->isCacheValid = $cacheValidity['is_valid'];
         $executionContext->wasCacheCleaned = $cacheValidity['was_cleaned'];
     }
     // Get the resource URI and corresponding physical path.
     if ($server == null) {
         $server = $_SERVER;
     }
     if ($uri == null) {
         $uri = ServerHelper::getRequestUri($server, $this->pieCrust->getConfig()->getValueUnchecked('site/pretty_urls'));
     }
     // Do the heavy lifting.
     $page = Page::createFromUri($this->pieCrust, $uri);
     $executionContext->pushPage($page);
     if ($extraPageData != null) {
         $page->setExtraPageData($extraPageData);
     }
     $pageRenderer = new PageRenderer($page);
     $output = $pageRenderer->get();
     // Set or return the HTML headers.
     HttpHeaderHelper::setOrAddHeaders(PageRenderer::getHeaders($page->getConfig()->getValue('content_type'), $server), $headers);
     // Handle caching.
     if (!$this->pieCrust->isDebuggingEnabled()) {
         $hash = md5($output);
         HttpHeaderHelper::setOrAddHeader('Etag', '"' . $hash . '"', $headers);
         $clientHash = null;
         if (isset($server['HTTP_IF_NONE_MATCH'])) {
             $clientHash = $server['HTTP_IF_NONE_MATCH'];
         }
         if ($clientHash != null) {
             $clientHash = trim($clientHash, '"');
             if ($hash == $clientHash) {
                 HttpHeaderHelper::setOrAddHeader(0, 304, $headers);
                 HttpHeaderHelper::setOrAddHeader('Content-Length', '0', $headers);
                 return;
             }
         }
     }
     if ($this->pieCrust->isDebuggingEnabled()) {
         HttpHeaderHelper::setOrAddHeader('Cache-Control', 'no-cache, must-revalidate', $headers);
     } else {
         $cacheTime = PageHelper::getConfigValue($page, 'cache_time', 'site');
         if ($cacheTime) {
             HttpHeaderHelper::setOrAddHeader('Cache-Control', 'public, max-age=' . $cacheTime, $headers);
         }
     }
     // Output with or without GZip compression.
     $gzipEnabled = ($this->pieCrust->getConfig()->getValueUnchecked('site/enable_gzip') === true and array_key_exists('HTTP_ACCEPT_ENCODING', $server) and strpos($server['HTTP_ACCEPT_ENCODING'], 'gzip') !== false);
     if ($gzipEnabled) {
         $zippedOutput = gzencode($output);
         if ($zippedOutput === false) {
             HttpHeaderHelper::setOrAddHeader('Content-Length', strlen($output), $headers);
             echo $output;
         } else {
             HttpHeaderHelper::setOrAddHeader('Content-Encoding', 'gzip', $headers);
             HttpHeaderHelper::setOrAddHeader('Content-Length', strlen($zippedOutput), $headers);
             echo $zippedOutput;
         }
     } else {
         HttpHeaderHelper::setOrAddHeader('Content-Length', strlen($output), $headers);
         echo $output;
     }
 }