public function testParseRegularOnlyUriThatDoesntExist() { $fs = MockFileSystem::create()->withPage('existing-page'); $pc = new PieCrust(array('root' => $fs->getAppRoot(), 'cache' => false)); $uriInfo = UriParser::parseUri($pc, '/non-existing-page', UriParser::PAGE_URI_REGULAR); $this->assertNull($uriInfo); }
/** * 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); } }
protected function doProcess($inputPath, $outputPath) { $sitemap = Yaml::parse(file_get_contents($inputPath)); if (!isset($sitemap['locations'])) { throw new PieCrustException("No locations were defined in the sitemap."); } $xml = new \XMLWriter(); $xml->openMemory(); $xml->setIndent(true); $xml->startDocument('1.0', 'utf-8'); $xml->startElement('urlset'); $xml->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9'); foreach ($sitemap['locations'] as $loc) { $xml->startElement('url'); // loc $locUrl = $this->pieCrust->getConfig()->getValueUnchecked('site/root') . ltrim($loc['url'], '/'); $xml->writeElement('loc', $locUrl); // lastmod $locLastMod = null; if (isset($loc['lastmod'])) { $locLastMod = $loc['lastmod']; } else { if (isset($loc['lastmod_path'])) { $fullPath = $this->pieCrust->getRootDir() . ltrim($loc['lastmod_path'], '/\\'); $locLastMod = date('c', filemtime($fullPath)); } else { $urlInfo = UriParser::parseUri($this->pieCrust, $loc['url']); if ($urlInfo) { if (is_file($urlInfo['path'])) { $locLastMod = date('c', filemtime($urlInfo['path'])); } } } } if (!$locLastMod) { throw new PieCrustException("No idea what '" . $loc['url'] . "' is. Please specify a 'lastmod' time, or 'lastmod_path' path."); } $xml->writeElement('lastmod', $locLastMod); // changefreq if (isset($loc['changefreq'])) { $xml->writeAttribute('changefreq', $loc['changefreq']); } // priority if (isset($loc['priority'])) { $xml->writeAttribute('priority', $loc['priority']); } $xml->endElement(); } $xml->endElement(); $xml->endDocument(); $markup = $xml->outputMemory(true); file_put_contents($outputPath, $markup); }
/** * Parse a relative URI and returns information about it. */ public static function parseUri(IPieCrust $pieCrust, $uri, $uriTypes = self::PAGE_URI_ANY) { if (strpos($uri, '..') !== false) { throw new PieCrustException('404'); } $uri = '/' . trim($uri, '/'); $pageNumber = 1; $matches = array(); if (preg_match('/\\/(\\d+)\\/?$/', $uri, $matches)) { // Requesting a page other than the first for this article. $uri = substr($uri, 0, strlen($uri) - strlen($matches[0])); $pageNumber = intval($matches[1]); } $uri = ltrim($uri, '/'); $pageInfo = array('uri' => $uri, 'page' => $pageNumber, 'type' => IPage::TYPE_REGULAR, 'blogKey' => null, 'key' => null, 'date' => null, 'path' => null, 'was_path_checked' => false); // Try first with a regular page path. if (($uriTypes & self::PAGE_URI_REGULAR) != 0 and UriParser::tryParsePageUri($pieCrust, $uri, $pageInfo)) { return $pageInfo; } $blogKeys = $pieCrust->getConfig()->getValueUnchecked('site/blogs'); // Try with a post. if (($uriTypes & self::PAGE_URI_POST) != 0) { foreach ($blogKeys as $blogKey) { if (UriParser::tryParsePostUri($pieCrust, $blogKey, $uri, $pageInfo)) { return $pageInfo; } } } // Try with special pages (tag & category) if (($uriTypes & (self::PAGE_URI_CATEGORY | self::PAGE_URI_TAG)) != 0) { foreach ($blogKeys as $blogKey) { if (($uriTypes & self::PAGE_URI_TAG) != 0 and UriParser::tryParseTagUri($pieCrust, $blogKey, $uri, $pageInfo)) { return $pageInfo; } if (($uriTypes & self::PAGE_URI_CATEGORY) != 0 and UriParser::tryParseCategoryUri($pieCrust, $blogKey, $uri, $pageInfo)) { return $pageInfo; } } } // No idea what that URI is... return null; }
/** * @dataProvider parseAutoFormatUrisDataProvider */ public function testParseAutoFormatUris($config, $uri, $expectedUriInfo) { if (!isset($config['site'])) { $config['site'] = array(); } $config['site']['category_url'] = 'cat/%category%'; $config['site']['auto_formats'] = array('md' => 'markdown', 'text' => 'textile'); // We have to use a "real" mock FS (i.e. it will use real files instead // of vfsStream) because that's the place in the PieCrust code where we // need to use `glob()`, which isn't supported with virtual streams. $fs = MockFileSystem::create(true, true)->withConfig($config)->withPost('some-post', 3, 2, 2011, array(), 'Blah.', null, 'md')->withPost('other-post', 4, 2, 2011, array(), 'Blah.', null, 'text')->withPage('_index.md')->withPage('_category.md')->withPage('_tag.md')->withPage('textile/page.text')->withPage('markdown/page.md')->withPage('normal/page.html'); $pc = $fs->getApp(); $uriInfo = UriParser::parseUri($pc, $uri); if ($expectedUriInfo != null && isset($expectedUriInfo['path'])) { $pagesDir = $fs->url('kitchen/_content/pages/'); $postsDir = $fs->url('kitchen/_content/posts/'); $expectedUriInfo['path'] = str_replace(array('%pages_dir%', '%posts_dir%'), array($pagesDir, $postsDir), $expectedUriInfo['path']); } $this->assertEquals($expectedUriInfo, $uriInfo, 'The URI info was not what was expected.'); }
/** * Creates a new Page instance given a fully qualified URI. */ public static function createFromUri(IPieCrust $pieCrust, $uri, $useRepository = true) { if ($uri == null) { throw new InvalidArgumentException("The given URI is null."); } $uriInfo = UriParser::parseUri($pieCrust, $uri); if ($uriInfo == null or !$uriInfo['was_path_checked'] and !is_file($uriInfo['path'])) { if ($uriInfo['type'] == IPage::TYPE_TAG) { throw new PieCrustException("Tried to show posts with tag '{$uriInfo['key']}' but the special tag listing page was not found."); } if ($uriInfo['type'] == IPage::TYPE_CATEGORY) { throw new PieCrustException("Tried to show the posts in category '{$uriInfo['key']}' but the special category listing page was not found."); } throw new PieCrustException('404'); } if ($useRepository) { $pageRepository = $pieCrust->getEnvironment()->getPageRepository(); return $pageRepository->getOrCreatePage($uriInfo['uri'], $uriInfo['path'], $uriInfo['type'], $uriInfo['blogKey'], $uriInfo['key'], $uriInfo['page'], $uriInfo['date']); } else { return new Page($pieCrust, $uriInfo['uri'], $uriInfo['path'], $uriInfo['type'], $uriInfo['blogKey'], $uriInfo['key'], $uriInfo['page'], $uriInfo['date']); } }