/** * Returns a validated version of the given site configuration. * * This is exposed as a public static function for convenience (unit tests, * etc.) */ public static function getValidatedConfig($config) { // Validate defaults. if (!$config) { $config = array(); } if (!isset($config['site'])) { $config['site'] = array(); } $config['site'] = array_merge(array('title' => 'Untitled PieCrust Website', 'root' => null, 'theme_root' => null, 'default_format' => PieCrustDefaults::DEFAULT_FORMAT, 'default_template_engine' => PieCrustDefaults::DEFAULT_TEMPLATE_ENGINE, 'enable_gzip' => false, 'pretty_urls' => false, 'slugify' => 'transliterate|lowercase', 'timezone' => false, 'locale' => false, 'posts_fs' => PieCrustDefaults::DEFAULT_POSTS_FS, 'date_format' => PieCrustDefaults::DEFAULT_DATE_FORMAT, 'blogs' => array(PieCrustDefaults::DEFAULT_BLOG_KEY), 'plugins_sources' => array(PieCrustDefaults::DEFAULT_PLUGIN_SOURCE), 'themes_sources' => array(PieCrustDefaults::DEFAULT_THEME_SOURCE), 'auto_formats' => array(), 'cache_time' => 28800, 'display_errors' => true, 'enable_debug_info' => true), $config['site']); $siteConfig =& $config['site']; // Validate the site root URL, and remember if it was specified in the // source config.yml, because we won't be able to tell the difference from // the completely validated cache version. if ($siteConfig['root'] == null) { $siteConfig['root'] = ServerHelper::getSiteRoot($_SERVER); $siteConfig['is_auto_root'] = true; } else { $siteConfig['root'] = rtrim($siteConfig['root'], '/') . '/'; $siteConfig['is_auto_root'] = false; } // Validate auto-format extensions: make sure the HTML extension is in // there. if (!is_array($siteConfig['auto_formats'])) { throw new PieCrustException("The 'site/auto_formats' configuration setting must be an array."); } $siteConfig['auto_formats'] = array_filter(array_merge(array('html' => '', 'md' => 'markdown', 'textile' => 'textile'), $siteConfig['auto_formats']), function ($item) { return $item !== false; }); // Validate the plugins sources. if (!is_array($siteConfig['plugins_sources'])) { $siteConfig['plugins_sources'] = array($siteConfig['plugins_sources']); } // Validate the themes sources. if (!is_array($siteConfig['themes_sources'])) { $siteConfig['themes_sources'] = array($siteConfig['themes_sources']); } // Validate multi-blogs settings. if (in_array(PieCrustDefaults::DEFAULT_BLOG_KEY, $siteConfig['blogs']) and count($siteConfig['blogs']) > 1) { throw new PieCrustException("'" . PieCrustDefaults::DEFAULT_BLOG_KEY . "' cannot be specified as a blog key for multi-blog configurations. Please pick custom keys."); } // Add default values for the blogs configurations, or use values // defined at the site level for easy site-wide configuration of multiple blogs // and backwards compatibility. $defaultValues = array('post_url' => '%year%/%month%/%day%/%slug%', 'tag_url' => 'tag/%tag%', 'category_url' => '%category%', 'posts_per_page' => 5); foreach (array_keys($defaultValues) as $key) { if (isset($siteConfig[$key])) { $defaultValues[$key] = $siteConfig[$key]; } } foreach ($siteConfig['blogs'] as $blogKey) { $prefix = ''; if ($blogKey != PieCrustDefaults::DEFAULT_BLOG_KEY) { $prefix = $blogKey . '/'; } if (!isset($config[$blogKey])) { $config[$blogKey] = array(); } $config[$blogKey] = array_merge(array('post_url' => $prefix . $defaultValues['post_url'], 'tag_url' => $prefix . $defaultValues['tag_url'], 'category_url' => $prefix . $defaultValues['category_url'], 'posts_per_page' => $defaultValues['posts_per_page'], 'date_format' => $siteConfig['date_format']), $config[$blogKey]); } // Validate the slugify mode and optional flags. $slugifySetting = preg_split("/[\\s\\|,]+/", $siteConfig['slugify']); $slugifyModes = array('none' => UriBuilder::SLUGIFY_MODE_NONE, 'transliterate' => UriBuilder::SLUGIFY_MODE_TRANSLITERATE, 'encode' => UriBuilder::SLUGIFY_MODE_ENCODE, 'dash' => UriBuilder::SLUGIFY_MODE_DASHES, 'iconv' => UriBuilder::SLUGIFY_MODE_ICONV); $slugifyFlags = array('lowercase' => UriBuilder::SLUGIFY_FLAG_LOWERCASE); $finalSlugify = 0; foreach ($slugifySetting as $i => $m) { if ($i == 0) { if (!isset($slugifyModes[$m])) { throw new PieCrustException("Unsupported slugify mode: {$m}"); } $finalSlugify |= $slugifyModes[$m]; } else { if (!isset($slugifyFlags[$m])) { throw new PieCrustException("Unsupported slugify flag: {$m}"); } $finalSlugify |= $slugifyFlags[$m]; } } // We always want to slugify the `.` (dot) character, at least for tags // and categories, because it would screw up how we figure out what // extension to use for output files. $finalSlugify |= UriBuilder::SLUGIFY_FLAG_DOT_TO_DASH; $siteConfig['slugify_flags'] = $finalSlugify; return $config; }
/** * Returns a validated version of the given site configuration. * * This is exposed as a public static function for convenience (unit tests, * etc.) */ public static function getValidatedConfig($config) { // Validate defaults. if (!$config) { $config = array(); } if (!isset($config['site'])) { $config['site'] = array(); } $config['site'] = array_merge(array('title' => 'Untitled PieCrust Website', 'root' => null, 'theme_root' => null, 'default_format' => PieCrustDefaults::DEFAULT_FORMAT, 'default_template_engine' => PieCrustDefaults::DEFAULT_TEMPLATE_ENGINE, 'enable_gzip' => false, 'pretty_urls' => false, 'posts_fs' => PieCrustDefaults::DEFAULT_POSTS_FS, 'date_format' => PieCrustDefaults::DEFAULT_DATE_FORMAT, 'blogs' => array(PieCrustDefaults::DEFAULT_BLOG_KEY), 'plugins_sources' => array(PieCrustDefaults::DEFAULT_PLUGIN_SOURCE), 'themes_sources' => array(PieCrustDefaults::DEFAULT_THEME_SOURCE), 'cache_time' => 28800, 'display_errors' => false, 'enable_debug_info' => true), $config['site']); // Validate the site root URL, and remember if it was specified in the // source config.yml, because we won't be able to tell the difference from // the completely validated cache version. if ($config['site']['root'] == null) { $config['site']['root'] = ServerHelper::getSiteRoot($_SERVER); $config['site']['is_auto_root'] = true; } else { $config['site']['root'] = rtrim($config['site']['root'], '/') . '/'; $config['site']['is_auto_root'] = false; } // Validate the plugins sources. if (!is_array($config['site']['plugins_sources'])) { $config['site']['plugins_sources'] = array($config['site']['plugins_sources']); } if (!in_array(PieCrustDefaults::DEFAULT_PLUGIN_SOURCE, $config['site']['plugins_sources'])) { $config['site']['plugins_sources'][] = PieCrustDefaults::DEFAULT_PLUGIN_SOURCE; } // Validate the themes sources. if (!is_array($config['site']['themes_sources'])) { $config['site']['themes_sources'] = array($config['site']['themes_sources']); } if (!in_array(PieCrustDefaults::DEFAULT_THEME_SOURCE, $config['site']['themes_sources'])) { $config['site']['themes_sources'][] = PieCrustDefaults::DEFAULT_THEME_SOURCE; } // Validate multi-blogs settings. if (in_array(PieCrustDefaults::DEFAULT_BLOG_KEY, $config['site']['blogs']) and count($config['site']['blogs']) > 1) { throw new PieCrustException("'" . PieCrustDefaults::DEFAULT_BLOG_KEY . "' cannot be specified as a blog key for multi-blog configurations. Please pick custom keys."); } // Add default values for the blogs configurations, or use values // defined at the site level for easy site-wide configuration of multiple blogs // and backwards compatibility. $defaultValues = array('post_url' => '%year%/%month%/%day%/%slug%', 'tag_url' => 'tag/%tag%', 'category_url' => '%category%', 'posts_per_page' => 5); foreach (array_keys($defaultValues) as $key) { if (isset($config['site'][$key])) { $defaultValues[$key] = $config['site'][$key]; } } foreach ($config['site']['blogs'] as $blogKey) { $prefix = ''; if ($blogKey != PieCrustDefaults::DEFAULT_BLOG_KEY) { $prefix = $blogKey . '/'; } if (!isset($config[$blogKey])) { $config[$blogKey] = array(); } $config[$blogKey] = array_merge(array('post_url' => $prefix . $defaultValues['post_url'], 'tag_url' => $prefix . $defaultValues['tag_url'], 'category_url' => $prefix . $defaultValues['category_url'], 'posts_per_page' => $defaultValues['posts_per_page'], 'date_format' => $config['site']['date_format']), $config[$blogKey]); } return $config; }
/** * 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; } }
/** * @dataProvider getRequestUriDataProvider */ public function testGetRequestUri($server, $prettyUrls, $expectedRequestUri) { $actualUri = ServerHelper::getRequestUri($server, $prettyUrls); $this->assertEquals($expectedRequestUri, $actualUri, 'The request URI was not what was expected.'); }