Пример #1
0
 public function run(ChefContext $context)
 {
     $logger = $context->getLog();
     $pieCrust = $context->getApp();
     $result = $context->getResult();
     // Site title.
     $title = $pieCrust->getConfig()->getValue('site/title');
     if ($title == null) {
         $title = "[Unknown Website Title]";
     }
     // Compute the page count.
     $pageCount = 0;
     $callback = function ($page) use(&$pageCount) {
         $pageCount++;
     };
     PageHelper::processPages($pieCrust, $callback);
     // Compute the post count.
     $postCounts = array();
     $blogKeys = $pieCrust->getConfig()->getValueUnchecked('site/blogs');
     foreach ($blogKeys as $blogKey) {
         $postCounts[$blogKey] = count($pieCrust->getEnvironment()->getPostInfos($blogKey));
     }
     $logger->info("Stats for '{$title}':");
     $logger->info("Root  : {$pieCrust->getRootDir()}");
     $logger->info("Pages : {$pageCount}");
     foreach ($blogKeys as $blogKey) {
         $logger->info("Posts : {$postCounts[$blogKey]} (in '{$blogKey}')");
     }
     return 0;
 }
Пример #2
0
 /**
  * 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(IPage $page, $config)
 {
     if (!$config) {
         $config = array();
     }
     // Add the default page config values.
     $pieCrustConfig = $page->getApp()->getConfig();
     $blogKeys = $pieCrustConfig->getValueUnchecked('site/blogs');
     $layoutName = PieCrustDefaults::DEFAULT_PAGE_TEMPLATE_NAME;
     if (PageHelper::isPost($page)) {
         $layoutName = PieCrustDefaults::DEFAULT_POST_TEMPLATE_NAME;
         if ($page->getBlogKey()) {
             // If this is a post in a multi-blog environment, make it use
             // the `<blogname>/post.html` layout first by default, and
             // then fallback on `post.html` if that doesn't exist.
             $layoutName = $page->getBlogKey() . '/' . PieCrustDefaults::DEFAULT_POST_TEMPLATE_NAME . ',' . $layoutName;
         }
     }
     $validatedConfig = array_merge(array('layout' => $layoutName, 'format' => $pieCrustConfig->getValueUnchecked('site/default_format'), 'template_engine' => $pieCrustConfig->getValueUnchecked('site/default_template_engine'), 'content_type' => 'html', 'title' => 'Untitled Page', 'blog' => $page->getBlogKey() != null ? $page->getBlogKey() : $blogKeys[0], 'segments' => array()), $config);
     // Detect common problems.
     if (isset($validatedConfig['category'])) {
         if (is_array($validatedConfig['category'])) {
             throw new PieCrustException("Page '{$page->getUri()}': `category` is an array -- it must be a string. For multiple values, use `tags` instead.");
         }
     }
     if (isset($validatedConfig['tags'])) {
         if (!is_array($validatedConfig['tags'])) {
             $validatedConfig['tags'] = array($validatedConfig['tags']);
         }
     }
     if (isset($validatedConfig['single_page'])) {
         throw new PieCrustException("Page '{$page->getUri()}': `single_page` has been deprecated. Use `blog.posts` with some limits if you want a single page showing the most recent posts.");
     }
     return $validatedConfig;
 }
Пример #3
0
 public function run(ChefContext $context)
 {
     $logger = $context->getLog();
     $pieCrust = $context->getApp();
     $result = $context->getResult();
     // Validate options.
     if ($result->command->options['order_by_name'] && $result->command->options['order_by_count']) {
         throw new PieCrustException("Can't specify both '--order-name' and '--order-count'.");
     }
     $blogKeys = $pieCrust->getConfig()->getValue('site/blogs');
     if ($result->command->args['blog']) {
         foreach ($result->command->args['blog'] as $blogKey) {
             if (!in_array($blogKey, $blogKeys)) {
                 throw new PieCrustException("No such blog in the website : {$blogKey}");
             }
         }
         $blogKeys = $result->command->args['blog'];
     }
     $categories = array();
     foreach ($blogKeys as $blogKey) {
         $callback = function ($post) use(&$categories) {
             $c = $post->getConfig()->getValue('category');
             if ($c) {
                 if (!isset($categories[$c])) {
                     $categories[$c] = 0;
                 }
                 $categories[$c] += 1;
             }
         };
         PageHelper::processPosts($context->getApp(), $blogKey, $callback);
     }
     // Only print the count?
     if ($result->command->options['count']) {
         $logger->info(count($categories));
         return 0;
     }
     // Sort appropriately.
     $reverse = $result->command->options['reverse'];
     if ($result->command->options['order_by_name']) {
         if ($reverse) {
             krsort($categories);
         } else {
             ksort($categories);
         }
     } else {
         if ($result->command->options['order_by_count']) {
             if ($reverse) {
                 array_multisort($categories, SORT_DESC);
             } else {
                 array_multisort($categories, SORT_ASC);
             }
         }
     }
     // Print the list.
     $logger->info(count($categories) . " categories.");
     foreach ($categories as $c => $count) {
         $logger->info("{$c} ({$count} posts)");
     }
 }
Пример #4
0
 public function formatContents(array $rawSegments)
 {
     try {
         return $this->formatContentsUnsafe($rawSegments);
     } catch (Exception $e) {
         $relativePath = PageHelper::getRelativePath($this->page);
         throw new PieCrustException("Error formatting page '{$relativePath}': {$e->getMessage()}", 0, $e);
     }
 }
Пример #5
0
 public function testGetSimpleSitePages()
 {
     $fs = MockFileSystem::create()->withPage('_index', array(), 'Blah.');
     $app = $fs->getApp();
     $pages = $app->getEnvironment()->getPages();
     $this->assertEquals(1, count($pages));
     $this->assertEquals('_index.html', PageHelper::getRelativePath($pages[0]));
     $this->assertEquals(str_replace('\\', '/', $fs->url('kitchen/_content/pages/_index.html')), str_replace('\\', '/', $pages[0]->getPath()));
 }
 /**
  * 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(IPage $page, $config)
 {
     if (!$config) {
         $config = array();
     }
     // Add the default page config values.
     $pieCrustConfig = $page->getApp()->getConfig();
     $blogKeys = $pieCrustConfig->getValueUnchecked('site/blogs');
     $validatedConfig = array_merge(array('layout' => PageHelper::isPost($page) ? PieCrustDefaults::DEFAULT_POST_TEMPLATE_NAME : PieCrustDefaults::DEFAULT_PAGE_TEMPLATE_NAME, 'format' => $pieCrustConfig->getValueUnchecked('site/default_format'), 'template_engine' => $pieCrustConfig->getValueUnchecked('site/default_template_engine'), 'content_type' => 'html', 'title' => 'Untitled Page', 'blog' => $page->getBlogKey() != null ? $page->getBlogKey() : $blogKeys[0], 'segments' => array()), $config);
     return $validatedConfig;
 }
Пример #7
0
 protected function addCustomValues()
 {
     $post = $this->page;
     $pieCrust = $this->page->getApp();
     $blogKey = $this->page->getConfig()->getValueUnchecked('blog');
     $postsDateFormat = PageHelper::getConfigValueUnchecked($this->page, 'date_format', $blogKey);
     // Add the easy values to the values array.
     $this->values['url'] = PieCrustHelper::formatUri($pieCrust, $post->getUri());
     $this->values['slug'] = $post->getUri();
     $this->values['timestamp'] = $post->getDate();
     //TODO: do we need to move this to the lazy-loaded values?
     $this->values['date'] = date($postsDateFormat, $post->getDate());
     // Add some lazy-loading functions for stuff
     // that would load the page's contents.
     $this->lazyValues[self::WILDCARD] = 'loadContent';
 }
Пример #8
0
 protected function addCustomValues()
 {
     $post = $this->page;
     $pieCrust = $post->getApp();
     $blogKey = $post->getConfig()->getValueUnchecked('blog');
     $postsDateFormat = PageHelper::getConfigValueUnchecked($post, 'date_format', $blogKey);
     // Add the easy values to the values array.
     $this->values['url'] = PieCrustHelper::formatUri($pieCrust, $post->getUri());
     $this->values['slug'] = $post->getUri();
     $this->values['timestamp'] = $post->getDate(true);
     $this->values['date'] = date($postsDateFormat, $post->getDate(true));
     // Make it possible to access assets.
     $assetor = new Assetor($post);
     $this->values['assets'] = $assetor;
     // Add some lazy-loading functions for stuff
     // that would load the page's contents.
     $this->lazyValues[self::WILDCARD] = 'loadContent';
 }
Пример #9
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;
     }
 }
Пример #10
0
 protected function bakePosts()
 {
     if ($this->bakeRecord == null) {
         throw new PieCrustException("Can't bake posts without a bake-record active.");
     }
     $blogKeys = $this->pieCrust->getConfig()->getValue('site/blogs');
     foreach ($blogKeys as $blogKey) {
         $posts = PageHelper::getPosts($this->pieCrust, $blogKey);
         foreach ($posts as $post) {
             $this->bakePost($post);
         }
     }
 }
Пример #11
0
 /**
  * Gets the page's data for page rendering.
  *
  * It's better to call IPage::getData, which calls this function, because it
  * will also cache the results. It's useful for example when pagination
  * results needs to be re-used.
  */
 public static function getPageData(IPage $page)
 {
     $pieCrust = $page->getApp();
     $paginator = new Paginator($page);
     $assetor = new Assetor($page);
     $linker = new Linker($page);
     if ($page->getPaginationDataSource() != null) {
         $paginator->setPaginationDataSource($page->getPaginationDataSource());
     }
     $data = array('page' => $page->getConfig()->get(), 'asset' => $assetor, 'pagination' => $paginator, 'link' => $linker);
     $data['page']['url'] = PieCrustHelper::formatUri($pieCrust, $page->getUri());
     $data['page']['slug'] = $page->getUri();
     $data['page']['timestamp'] = $page->getDate();
     $dateFormat = PageHelper::getConfigValueUnchecked($page, 'date_format', $page->getConfig()->getValueUnchecked('blog'));
     $data['page']['date'] = date($dateFormat, $page->getDate());
     switch ($page->getPageType()) {
         case IPage::TYPE_TAG:
             if (is_array($page->getPageKey())) {
                 $data['tag'] = implode(' + ', $page->getPageKey());
             } else {
                 $data['tag'] = $page->getPageKey();
             }
             break;
         case IPage::TYPE_CATEGORY:
             $data['category'] = $page->getPageKey();
             break;
     }
     $extraData = $page->getExtraPageData();
     if ($extraData) {
         if (is_array($extraData)) {
             $data = Configuration::mergeArrays($data, $extraData);
         } else {
             $data['extra'] = $extraData;
         }
     }
     return $data;
 }
Пример #12
0
 protected function bakeSinglePage(PageRenderer $pageRenderer, array $extraData = null)
 {
     $page = $pageRenderer->getPage();
     // Set the extra template data before the page's data is computed.
     if ($extraData != null) {
         $page->setExtraPageData($extraData);
     }
     // This is usually done in the PieCrustBaker, but we'll do it here too
     // because the `PageBaker` could be used on its own.
     if ($this->parameters['copy_assets']) {
         $page->setAssetUrlBaseRemap("%site_root%%uri%");
     }
     // Figure out the output HTML path.
     $bakePath = $this->getOutputPath($page);
     $this->logger->debug("  p{$page->getPageNumber()} -> {$bakePath}");
     // Figure out if we should re-bake this page.
     $doBake = true;
     if ($this->parameters['smart']) {
         // Don't rebake if the output seems up-to-date, and
         // the page isn't known to be using posts.
         $bakePathTime = @filemtime($bakePath);
         if ($bakePathTime !== false && filemtime($page->getPath()) < $bakePathTime) {
             // TODO: rebake if the page is using pagination and pages/posts were baked this time.
             $doBake = false;
         }
     }
     if (!$doBake) {
         $this->logger->debug("Not baking '{$page->getUri()}/{$page->getPageNumber()}' because '{$bakePath}' is up-to-date.");
         return false;
     }
     // If we're using portable URLs, change the site root to a relative
     // path from the page's directory.
     $savedSiteRoot = $this->setPortableSiteRoot($page->getApp(), $bakePath);
     // Render the page.
     $bakedContents = $pageRenderer->get();
     // Get some objects we need.
     $data = $page->getPageData();
     $assetor = $data['assets'];
     $paginator = $data['pagination'];
     // Copy the page.
     PathHelper::ensureDirectory(dirname($bakePath));
     file_put_contents($bakePath, $bakedContents);
     $this->bakedFiles[] = $bakePath;
     // Copy any used assets for the first sub-page.
     if ($page->getPageNumber() == 1 and $this->parameters['copy_assets']) {
         $prettyUrls = PageHelper::getConfigValue($page, 'pretty_urls', 'site');
         if ($prettyUrls) {
             $bakeAssetDir = dirname($bakePath) . '/';
         } else {
             $bakePathInfo = pathinfo($bakePath);
             $bakeAssetDir = $bakePathInfo['dirname'] . '/' . ($page->getUri() == '' ? '' : $bakePathInfo['filename']) . '/';
         }
         $assetPaths = $assetor->getAssetPathnames();
         if ($assetPaths != null) {
             PathHelper::ensureDirectory($bakeAssetDir);
             foreach ($assetPaths as $assetPath) {
                 $destinationAssetPath = $bakeAssetDir . basename($assetPath);
                 if (@copy($assetPath, $destinationAssetPath) == false) {
                     throw new PieCrustException("Can't copy '{$assetPath}' to '{$destinationAssetPath}'.");
                 }
             }
         }
     }
     // Remember a few things.
     $this->paginationDataAccessed = ($this->paginationDataAccessed or $paginator->wasPaginationDataAccessed());
     // Cleanup.
     if ($savedSiteRoot) {
         $page->getApp()->getConfig()->setValue('site/root', $savedSiteRoot);
     }
     return true;
 }
Пример #13
0
 protected function ensureLinksCache()
 {
     if ($this->linksCache === null) {
         try {
             $pieCrust = $this->page->getApp();
             $pageRepository = $pieCrust->getEnvironment()->getPageRepository();
             $this->linksCache = array();
             $skipNames = array('Thumbs.db');
             $it = new FilesystemIterator($this->baseDir);
             foreach ($it as $item) {
                 $basename = $item->getBasename();
                 // Skip dot files, Thumbs.db, etc.
                 if (!$basename or $basename[0] == '.') {
                     continue;
                 }
                 if (in_array($item->getFilename(), $skipNames)) {
                     continue;
                 }
                 if ($item->isDir()) {
                     $linker = new Linker($this->page, $item->getPathname());
                     $this->linksCache[$basename . '_'] = $linker;
                     // We add '_' at the end of the directory name to avoid
                     // collisions with a possibly existing page with the same
                     // name (since we strip out the '.html' extension).
                     // This means the user must access directories with
                     // 'link.dirname_' instead of 'link.dirname' but hey, if
                     // you have a better idea, send me an email!
                 } else {
                     $path = $item->getPathname();
                     try {
                         $relativePath = PageHelper::getRelativePath($this->page);
                         $uri = UriBuilder::buildUri($relativePath);
                         // To get the link's page, we need to be careful with the case
                         // where that page is the currently rendering one. This is
                         // because it could be rendering a sub-page -- but we would be
                         // requesting the default first page, which would effectively
                         // change the page number *while* we're rendering, which leads
                         // to all kinds of bad things!
                         // TODO: obviously, there needs to be some design changes to
                         // prevent this kind of chaotic behaviour.
                         if ($path == $this->page->getPath()) {
                             $page = $this->page;
                         } else {
                             $page = $pageRepository->getOrCreatePage($uri, $path);
                         }
                         $key = str_replace('.', '_', $item->getBasename('.html'));
                         $this->linksCache[$key] = array('uri' => $uri, 'name' => $key, 'is_dir' => false, 'is_self' => $basename == $this->selfName, 'page' => new PaginationData($page));
                     } catch (Exception $e) {
                         throw new PieCrustException("Error while loading page '{$path}' for linking from '{$this->page->getUri()}': " . $e->getMessage(), 0, $e);
                     }
                 }
             }
             if ($this->sortByName) {
                 if (false === usort($this->linksCache, array($this, 'sortByCustom'))) {
                     throw new PieCrustException("Error while sorting pages with the specified setting: {$this->sortByName}");
                 }
             }
             if ($this->selfName != null) {
                 // Add special stuff only for the original Linker
                 // (the one directly created by the current page).
                 if (PageHelper::isRegular($this->page)) {
                     // Add a link to go up to the parent directory, but stay inside
                     // the app's pages directory.
                     $parentBaseDir = dirname($this->baseDir);
                     if (strlen($parentBaseDir) >= strlen($pieCrust->getPagesDir())) {
                         $linker = new Linker($this->page, dirname($this->baseDir));
                         $this->linksCache['_'] = $linker;
                     }
                 } else {
                     if (PageHelper::isPost($this->page)) {
                         // Add a link to go up to the parent directory, but stay inside
                         // the app's posts directory.
                         $parentBaseDir = dirname($this->baseDir);
                         if (strlen($parentBaseDir) >= strlen($pieCrust->getPostsDir())) {
                             $linker = new Linker($this->page, dirname($this->baseDir));
                             $this->linksCache['_'] = $linker;
                         }
                     }
                 }
                 if ($pieCrust->getPagesDir()) {
                     // Add a shortcut to the pages directory.
                     $linker = new Linker($this->page, $pieCrust->getPagesDir());
                     $this->linksCache['_pages_'] = $linker;
                 }
                 if ($pieCrust->getPostsDir()) {
                     // Add a shortcut to the posts directory.
                     $linker = new Linker($this->page, $pieCrust->getPostsDir());
                     $this->linksCache['_posts_'] = $linker;
                 }
             }
         } catch (Exception $e) {
             throw new PieCrustException("Error while building the links from page '{$this->page->getUri()}': " . $e->getMessage(), 0, $e);
         }
     }
 }
Пример #14
0
 protected function getPaginationFilter()
 {
     $filter = new PaginationFilter();
     $filterInfo = $this->page->getConfig()->getValue('posts_filters');
     if ($filterInfo == 'none' or $filterInfo == 'nil' or $filterInfo == '') {
         $filterInfo = null;
     }
     if (PageHelper::isTag($this->page) or PageHelper::isCategory($this->page)) {
         // If the current page is a tag/category page, add filtering
         // for that.
         $filter->addPageClauses($this->page, $filterInfo);
     } else {
         if ($filterInfo != null) {
             // Add custom filtering clauses specified by the user in the
             // page configuration header.
             $filter->addClauses($filterInfo);
         }
     }
     return $filter;
 }
Пример #15
0
 protected function bakeSinglePage(PageRenderer $pageRenderer, array $extraData = null)
 {
     $page = $pageRenderer->getPage();
     // Set the extra template data before the page's data is computed.
     if ($extraData != null) {
         $page->setExtraPageData($extraData);
     }
     // This is usually done in the PieCrustBaker, but we'll do it here too
     // because the `PageBaker` could be used on its own.
     if ($this->parameters['copy_assets']) {
         $page->setAssetUrlBaseRemap("%site_root%%uri%");
     }
     // Figure out the output HTML path.
     $bakePath = $this->getOutputPath($page);
     // Figure out if we should re-bake this page.
     $doBake = true;
     if (is_file($bakePath) && $this->parameters['smart']) {
         // Don't rebake if the output seems up-to-date, and
         // the page isn't known to be using posts.
         if (filemtime($page->getPath()) < filemtime($bakePath)) {
             $bakeRecord = $this->parameters['bake_record'];
             if ($bakeRecord) {
                 $relativePath = PageHelper::getRelativePath($page);
                 if (!$bakeRecord->wasAnyPostBaked() || !$bakeRecord->isPageUsingPosts($relativePath)) {
                     $doBake = false;
                 }
             }
         }
     }
     if (!$doBake) {
         $this->logger->debug("Not baking '{$page->getUri()}/{$page->getPageNumber()}' because '{$bakePath}' is up-to-date.");
         return false;
     }
     // Backward compatibility warning and file-copy.
     // [TODO] Remove in a couple of versions.
     $copyToOldPath = false;
     $contentType = $page->getConfig()->getValue('content_type');
     $nativeExtension = pathinfo($page->getPath(), PATHINFO_EXTENSION);
     if ($contentType != 'html' && $nativeExtension == 'html') {
         $copyToOldPath = $this->bakeDir . $page->getUri();
         if ($page->getPageNumber() > 1) {
             $copyToOldPath .= $page->getPageNumber() . '/';
         }
         $copyToOldPath .= '.' . $contentType;
     }
     // If we're using portable URLs, change the site root to a relative
     // path from the page's directory.
     $savedSiteRoot = $this->setPortableSiteRoot($page->getApp(), $bakePath);
     // Render the page.
     $bakedContents = $pageRenderer->get();
     // Get some objects we need.
     $data = $page->getPageData();
     $assetor = $data['asset'];
     $paginator = $data['pagination'];
     // Copy the page.
     PathHelper::ensureDirectory(dirname($bakePath));
     file_put_contents($bakePath, $bakedContents);
     $this->bakedFiles[] = $bakePath;
     // [TODO] See previous TODO.
     if ($copyToOldPath) {
         $this->logger->warning("Page '{$page->getUri()}' has 'content_type' specified but is an HTML file.");
         $this->logger->warning("Changing a baked file's extension using 'content_type' is deprecated and will be removed in a future version.");
         $this->logger->warning("For backwards compatibility, the page will also be baked to: " . substr($copyToOldPath, strlen($this->bakeDir)));
         $this->logger->warning("To fix the problem, change the source file's extension to the desired output extension.");
         $this->logger->warning("Otherwise, just ignore these messages.");
         file_put_contents($copyToOldPath, $bakedContents);
     }
     // Copy any used assets for the first sub-page.
     if ($page->getPageNumber() == 1 and $this->parameters['copy_assets']) {
         $prettyUrls = PageHelper::getConfigValue($page, 'pretty_urls', 'site');
         if ($prettyUrls) {
             $bakeAssetDir = dirname($bakePath) . '/';
         } else {
             $bakePathInfo = pathinfo($bakePath);
             $bakeAssetDir = $bakePathInfo['dirname'] . '/' . ($page->getUri() == '' ? '' : $bakePathInfo['filename']) . '/';
         }
         $assetPaths = $assetor->getAssetPathnames();
         if ($assetPaths != null) {
             PathHelper::ensureDirectory($bakeAssetDir);
             foreach ($assetPaths as $assetPath) {
                 $destinationAssetPath = $bakeAssetDir . basename($assetPath);
                 if (@copy($assetPath, $destinationAssetPath) == false) {
                     throw new PieCrustException("Can't copy '" . $assetPath . "' to '" . $destinationAssetPath . "'.");
                 }
             }
         }
     }
     // Remember a few things.
     $this->paginationDataAccessed = ($this->paginationDataAccessed or $paginator->wasPaginationDataAccessed());
     // Cleanup.
     if ($savedSiteRoot) {
         $page->getApp()->getConfig()->setValue('site/root', $savedSiteRoot);
     }
     return true;
 }
Пример #16
0
 protected function ensurePostsCached($blogKey)
 {
     if ($this->posts == null) {
         $this->posts = array();
     }
     if (!isset($this->posts[$blogKey])) {
         $pageRepository = $this->getPageRepository();
         $postInfos = $this->getPostInfos($blogKey);
         $postUrlFormat = $this->pieCrust->getConfig()->getValue($blogKey . '/post_url');
         $posts = array();
         foreach ($postInfos as $postInfo) {
             $uri = UriBuilder::buildPostUri($postUrlFormat, $postInfo);
             $page = $pageRepository->getOrCreatePage($uri, $postInfo['path'], IPage::TYPE_POST, $blogKey);
             $page->setDate(PageHelper::getPostDate($postInfo));
             $posts[] = $page;
         }
         $this->posts[$blogKey] = $posts;
     }
 }
 protected function ensureLoaded()
 {
     if ($this->values != null) {
         return;
     }
     // Gather all posts sorted by the property we want.
     $dataSources = array();
     $posts = PageHelper::getPosts($this->page->getApp(), $this->blogKey);
     foreach ($posts as $post) {
         $this->addPageValue($post, $dataSources);
     }
     // Now for each property bucket, create a pagination iterator.
     $this->values = array();
     foreach ($dataSources as $property => $dataSource) {
         $this->values[$property] = new PagePropertyData($this->page, $this->blogKey, $property, $dataSource);
     }
     ksort($this->values);
 }
Пример #18
0
 private function findPages($context, $pages, $fromBlog = false)
 {
     $logger = $context->getLog();
     $pieCrust = $context->getApp();
     $result = $context->getResult();
     $rootDir = $pieCrust->getRootDir();
     $rootDir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $rootDir);
     $exact = $result->command->options['exact'];
     $pattern = $result->command->args['pattern'];
     $fullPath = $result->command->options['full_path'];
     $returnComponents = $result->command->options['page_components'];
     $foundAny = false;
     foreach ($pages as $page) {
         if ($result->command->options['no_special']) {
             // Skip special pages.
             if ($page->getUri() == PieCrustDefaults::CATEGORY_PAGE_NAME or $page->getUri() == PieCrustDefaults::TAG_PAGE_NAME) {
                 continue;
             }
         }
         if ($exact) {
             // Match the path exactly, or pass.
             if (str_replace('\\', '/', $pattern) != str_replace('\\', '/', $page->getPath())) {
                 continue;
             }
         } else {
             if ($pattern) {
                 // Match the regex, or pass.
                 if (!preg_match($pattern, $page->getUri())) {
                     continue;
                 }
             }
         }
         $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $page->getPath());
         if (!$fullPath) {
             if (substr($path, 0, strlen($rootDir)) == $rootDir) {
                 $path = PieCrustHelper::getRelativePath($pieCrust, $path);
             }
         }
         if ($returnComponents) {
             $components = array('path' => $path, 'type' => 'page', 'uri' => $page->getUri(), 'slug' => $page->getUri());
             if (PageHelper::isPost($page)) {
                 $timestamp = $page->getDate(true);
                 $components['type'] = 'post';
                 $components['year'] = date('Y', $timestamp);
                 $components['month'] = date('m', $timestamp);
                 $components['day'] = date('d', $timestamp);
                 $components['hour'] = date('H', $timestamp);
                 $components['minute'] = date('i', $timestamp);
                 $components['second'] = date('s', $timestamp);
                 $matches = array();
                 $postsPattern = UriBuilder::buildPostUriPattern($pieCrust->getConfig()->getValue($fromBlog . '/post_url'), $fromBlog);
                 if (preg_match($postsPattern, $page->getUri(), $matches)) {
                     $components['slug'] = $matches['slug'];
                 }
             }
             foreach ($components as $k => $v) {
                 $logger->info("{$k}: {$v}");
             }
             $logger->info("");
             $foundAny = true;
         } else {
             $logger->info($path);
             $foundAny = true;
         }
     }
     return $foundAny;
 }
Пример #19
0
 protected function ensureMonths()
 {
     if ($this->months) {
         return;
     }
     // Get all the blog posts.
     $posts = PageHelper::getPosts($this->page->getApp(), $this->blogKey);
     // Sort them by month.
     $monthsInfos = array();
     $currentMonthAndYear = null;
     foreach ($posts as $post) {
         $timestamp = $post->getDate();
         $pageMonthAndYear = date('F Y', $timestamp);
         if (!isset($monthsInfos[$pageMonthAndYear])) {
             $pageYear = intval(date('Y', $timestamp));
             $pageMonth = intval(date('m', $timestamp));
             $monthsInfos[$pageMonthAndYear] = array('name' => $pageMonthAndYear, 'timestamp' => mktime(0, 0, 0, $pageMonth, 1, $pageYear), 'data_source' => array());
         }
         $monthsInfos[$pageMonthAndYear]['data_source'][] = $post;
     }
     // For each month, create the data class.
     $this->months = array();
     foreach ($monthsInfos as $month => $monthInfo) {
         $this->months[$month] = new PageTimeData($this->page, $this->blogKey, $monthInfo['name'], $monthInfo['timestamp'], $monthInfo['data_source']);
     }
     // Sort the months in inverse chronological order.
     uasort($this->months, array('PieCrust\\Data\\BlogData', 'sortByReverseTimestamp'));
 }
Пример #20
0
 protected function ensureMonths()
 {
     if ($this->months) {
         return;
     }
     $blogPosts = PageHelper::getPosts($this->page->getApp(), $this->blogKey);
     $this->months = array();
     $currentMonthAndYear = null;
     foreach ($blogPosts as $post) {
         $timestamp = $post->getDate();
         $pageMonthAndYear = date('Y m', $timestamp);
         if ($currentMonthAndYear == null or $pageMonthAndYear != $currentMonthAndYear) {
             $pageYear = intval(date('Y', $timestamp));
             $pageMonth = intval(date('m', $timestamp));
             $this->months[$pageMonthAndYear] = array('name' => date('F Y', $timestamp), 'timestamp' => mktime(0, 0, 0, $pageMonth, 1, $pageYear), 'posts' => array());
             $currentMonthAndYear = $pageMonthAndYear;
         }
         $this->months[$currentMonthAndYear]['posts'][] = new PaginationData($post);
     }
     ksort($this->months);
 }
Пример #21
0
 public function run(ChefContext $context)
 {
     $logger = $context->getLog();
     $pieCrust = $context->getApp();
     $result = $context->getResult();
     // Warn about deprecated stuff.
     if ($result->command->options['order_by_name_old']) {
         $context->getLog()->warning("The `--orderbyname` option has been renamed to `--order-name`.");
         $result->command->options['order_by_name'] = true;
     }
     if ($result->command->options['order_by_count_old']) {
         $context->getLog()->warning("The `--orderbycount` option has been renamed to `--order-count`.");
         $result->command->options['order_by_count'] = true;
     }
     // Validate options.
     if ($result->command->options['order_by_name'] && $result->command->options['order_by_count']) {
         throw new PieCrustException("Can't specify both '--order-name' and '--order-count'.");
     }
     $blogKeys = $pieCrust->getConfig()->getValue('site/blogs');
     if ($result->command->args['blog']) {
         foreach ($result->command->args['blog'] as $blogKey) {
             if (!in_array($blogKey, $blogKeys)) {
                 throw new PieCrustException("No such blog in the website : {$blogKey}");
             }
         }
         $blogKeys = $result->command->args['blog'];
     }
     $tags = array();
     foreach ($blogKeys as $blogKey) {
         $callback = function ($post) use(&$tags) {
             $postTags = $post->getConfig()->getValue('tags');
             if ($postTags) {
                 if (!is_array($postTags)) {
                     $postTags = array($postTags);
                 }
                 foreach ($postTags as $t) {
                     if (!isset($tags[$t])) {
                         $tags[$t] = 0;
                     }
                     $tags[$t] += 1;
                 }
             }
         };
         PageHelper::processPosts($pieCrust, $blogKey, $callback);
     }
     // Only print the count?
     if ($result->command->options['count']) {
         $logger->info(count($tags));
         return 0;
     }
     // Sort appropriately.
     $reverse = $result->command->options['reverse'];
     if ($result->command->options['order_by_name']) {
         if ($reverse) {
             krsort($tags);
         } else {
             ksort($tags);
         }
     } else {
         if ($result->command->options['order_by_count']) {
             if ($reverse) {
                 array_multisort($tags, SORT_DESC);
             } else {
                 array_multisort($tags, SORT_ASC);
             }
         }
     }
     // Print the list.
     $logger->info(count($tags) . " tags.");
     foreach ($tags as $t => $count) {
         $logger->info("{$t} ({$count} posts)");
     }
 }
Пример #22
0
 protected function getPaginationFilter()
 {
     $filter = new PaginationFilter();
     $filterInfo = $this->page->getConfig()->getValue('posts_filters');
     if ($filterInfo == 'none' or $filterInfo == 'nil' or $filterInfo == '') {
         $filterInfo = null;
     }
     if (PageHelper::isTag($this->page) or PageHelper::isCategory($this->page)) {
         // If the current page is a tag/category page, add filtering
         // for that.
         if ($filterInfo != null) {
             throw new PieCrustException("The `posts_filters` setting cannot be used on a tag or category listing page -- the filter will be automatically set to posts matching the request tag or category.");
         }
         $filter->addPageClauses($this->page);
     } else {
         if ($filterInfo != null) {
             // Add custom filtering clauses specified by the user in the
             // page configuration header.
             $filter->addClauses($filterInfo);
         }
     }
     return $filter;
 }
Пример #23
0
 protected function ensurePostsCached($blogKey)
 {
     if ($this->posts == null) {
         $this->posts = array();
     }
     if (!isset($this->posts[$blogKey])) {
         $this->getLog()->debug("Indexing '{$blogKey}' posts...");
         $fs = $this->getFileSystem();
         $postInfos = $fs->getPostFiles($blogKey);
         $this->getLog()->debug("Creating '{$blogKey}' posts...");
         $pageRepository = $this->getPageRepository();
         $posts = array();
         foreach ($postInfos as $postInfo) {
             $uri = UriBuilder::buildPostUri($this->pieCrust, $blogKey, $postInfo);
             $page = $pageRepository->getOrCreatePage($uri, $postInfo->path, IPage::TYPE_POST, $blogKey);
             $page->setDate(PageHelper::getPostDate($postInfo));
             $posts[] = $page;
         }
         $this->posts[$blogKey] = $posts;
     }
 }
Пример #24
0
 protected static function buildUrlBase(IPage $page, $assetUrlBaseRemap)
 {
     $siteRoot = $page->getApp()->getConfig()->getValueUnchecked('site/root');
     $relativePath = str_replace('\\', '/', PieCrustHelper::getRelativePath($page->getApp(), $page->getPath(), true));
     $uri = $page->getUri();
     $prettyUrls = PageHelper::getConfigValue($page, 'pretty_urls', 'site');
     if (!$prettyUrls) {
         // Remove the extension from the URI (if any), because without 'pretty URLs',
         // we want to copy assets to a directory named after the page's filename
         // (without the extension). See `PageBaker` for more information.
         $uriInfo = pathinfo($uri);
         $uri = $uriInfo['dirname'];
         if ($uri == '.') {
             $uri = '';
         } else {
             $uri .= '/';
         }
         $uri .= $uriInfo['filename'];
     }
     $replacements = array('%site_root%' => $siteRoot, '%path%' => $relativePath, '%uri%' => $uri);
     return str_replace(array_keys($replacements), array_values($replacements), $assetUrlBaseRemap);
 }
Пример #25
0
 protected function bakePosts()
 {
     $blogKeys = $this->pieCrust->getConfig()->getValue('site/blogs');
     foreach ($blogKeys as $blogKey) {
         $posts = PageHelper::getPosts($this->pieCrust, $blogKey);
         foreach ($posts as $post) {
             $this->bakePost($post);
         }
     }
 }
Пример #26
0
 public function run(ChefContext $context)
 {
     $logger = $context->getLog();
     $pieCrust = $context->getApp();
     $result = $context->getResult();
     // Get some options.
     $exact = $result->command->options['exact'];
     $fullPath = $result->command->options['full_path'];
     // If no type filters are given, return all types.
     $returnAllTypes = ($result->command->options['pages'] == false and $result->command->options['posts'] == false and $result->command->options['templates'] == false);
     // Validate the argument.
     $pattern = $result->command->args['pattern'];
     if ($exact) {
         // Check we have a path to match, and get its absolute value.
         if (!$pattern) {
             throw new PieCrustException("You need to specify a path when using the `--exact` option.");
         }
         $pattern = PathHelper::getAbsolutePath($pattern);
     } else {
         // If a pattern was given, get the Regex'd version.
         if ($pattern) {
             $pattern = PathHelper::globToRegex($pattern);
         }
     }
     // Get the pages and posts.
     $pages = array();
     if ($returnAllTypes or $result->command->options['pages']) {
         $pages = PageHelper::getPages($pieCrust);
     }
     if ($returnAllTypes or $result->command->options['posts']) {
         $blogKeys = $pieCrust->getConfig()->getValue('site/blogs');
         if ($result->command->options['blog']) {
             $blogKeys = array($result->command->options['blog']);
         }
         foreach ($blogKeys as $blogKey) {
             $pages = array_merge($pages, PageHelper::getPosts($pieCrust, $blogKey));
         }
     }
     // Get some other stuff.
     $returnComponents = $result->command->options['page_components'];
     // Get a regex for the posts file-naming convention.
     $fs = FileSystem::create($pieCrust);
     $pathComponentsRegex = preg_quote($fs->getPostPathFormat(), '/');
     $pathComponentsRegex = str_replace(array('%year%', '%month%', '%day%', '%slug%'), array('(\\d{4})', '(\\d{2})', '(\\d{2})', '(.+)'), $pathComponentsRegex);
     $pathComponentsRegex = '/' . $pathComponentsRegex . '/';
     // Print the matching pages.
     foreach ($pages as $page) {
         if ($result->command->options['no_special']) {
             // Skip special pages.
             if ($page->getUri() == PieCrustDefaults::CATEGORY_PAGE_NAME or $page->getUri() == PieCrustDefaults::TAG_PAGE_NAME) {
                 continue;
             }
         }
         if ($exact) {
             // Match the path exactly, or pass.
             if (str_replace('\\', '/', $pattern) != str_replace('\\', '/', $page->getPath())) {
                 continue;
             }
         } else {
             if ($pattern) {
                 // Match the regex, or pass.
                 if (!preg_match($pattern, $page->getUri())) {
                     continue;
                 }
             }
         }
         $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $page->getPath());
         if (!$fullPath) {
             $path = PieCrustHelper::getRelativePath($pieCrust, $path);
         }
         if ($returnComponents) {
             $components = array('path' => $path, 'type' => 'page', 'uri' => $page->getUri(), 'slug' => $page->getUri());
             if (PageHelper::isPost($page)) {
                 $matches = array();
                 if (preg_match($pathComponentsRegex, str_replace('\\', '/', $path), $matches) !== 1) {
                     throw new PieCrustException("Can't extract path components from path: {$path}");
                 }
                 $components['type'] = 'post';
                 $components['year'] = $matches[1];
                 $components['month'] = $matches[2];
                 $components['day'] = $matches[3];
                 $components['slug'] = $matches[4];
             }
             $str = '';
             foreach ($components as $k => $v) {
                 $str .= $k . ': ' . $v . PHP_EOL;
             }
             $logger->info($str);
         } else {
             $logger->info($path);
         }
     }
     // Get the template files and print them.
     if ($returnAllTypes or $result->command->options['templates']) {
         $templatesDirs = $pieCrust->getTemplatesDirs();
         foreach ($templatesDirs as $dir) {
             $dirIt = new \RecursiveDirectoryIterator($dir);
             $it = new \RecursiveIteratorIterator($dirIt);
             foreach ($it as $path) {
                 if ($it->isDot()) {
                     continue;
                 }
                 $relativePath = PieCrustHelper::getRelativePath($pieCrust, $path->getPathname());
                 if ($exact) {
                     // Match the path exactly, or pass.
                     if (str_replace('\\', '/', $pattern) != str_replace('\\', '/', $path->getPathname())) {
                         continue;
                     }
                 } else {
                     if ($pattern) {
                         // Match the regex, or pass.
                         if (!preg_match($pattern, $relativePath)) {
                             continue;
                         }
                     }
                 }
                 // Get the path to print.
                 $finalPath = $relativePath;
                 if ($fullPath) {
                     $finalPath = $path->getPathname();
                 }
                 $finalPath = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $finalPath);
                 // Print the information!
                 if ($returnComponents) {
                     $logger->info("path: {$finalPath}");
                     $logger->info("type: template");
                 } else {
                     $logger->info($finalPath);
                 }
             }
         }
     }
     return 0;
 }
Пример #27
0
 /**
  * Gets the page's data for page rendering.
  *
  * It's better to call IPage::getData, which calls this function, because it
  * will also cache the results. It's useful for example when pagination
  * results needs to be re-used.
  */
 public static function getPageData(IPage $page)
 {
     $pieCrust = $page->getApp();
     $paginator = new Paginator($page);
     $assetor = new Assetor($page);
     $linker = new Linker($page);
     $recursiveLinker = new RecursiveLinkerIterator($linker);
     if ($page->getPaginationDataSource() != null) {
         $paginator->setPaginationDataSource($page->getPaginationDataSource());
     }
     $data = array('page' => $page->getConfig()->get(), 'assets' => $assetor, 'pagination' => $paginator, 'siblings' => $linker, 'family' => $recursiveLinker);
     $data['page']['url'] = PieCrustHelper::formatUri($pieCrust, $page->getUri());
     $data['page']['slug'] = $page->getUri();
     $data['page']['timestamp'] = $page->getDate(true);
     $dateFormat = PageHelper::getConfigValueUnchecked($page, 'date_format', $page->getConfig()->getValueUnchecked('blog'));
     $data['page']['date'] = date($dateFormat, $page->getDate(true));
     switch ($page->getPageType()) {
         case IPage::TYPE_TAG:
             if (is_array($page->getPageKey())) {
                 $data['tag'] = implode(' + ', $page->getPageKey());
             } else {
                 $data['tag'] = $page->getPageKey();
             }
             if (strpos($data['tag'], '-') >= 0) {
                 // The tag may have been slugified. Let's cheat a bit by looking at
                 // the first tag that matches in the first pagination post, and
                 // using that instead.
                 $paginationPosts = $paginator->posts();
                 if (count($paginationPosts) > 0) {
                     $firstPost = $paginationPosts[0];
                     $firstPostTags = $firstPost['tags'];
                     if (!is_array($firstPostTags)) {
                         $firstPostTags = array($firstPostTags);
                     }
                     $flags = $pieCrust->getConfig()->getValue('site/slugify_flags');
                     if (is_array($page->getPageKey())) {
                         $pageKey = $page->getPageKey();
                         foreach ($firstPostTags as $t) {
                             $st = UriBuilder::slugify($t, $flags);
                             foreach ($pageKey as &$pk) {
                                 if ($st == $pk) {
                                     $pk = $t;
                                     break;
                                 }
                             }
                         }
                         if ($page->getPageKey() == null) {
                             $page->setPageKey($pageKey);
                         }
                         $data['tag'] = implode(' + ', $pageKey);
                     } else {
                         foreach ($firstPostTags as $t) {
                             if (UriBuilder::slugify($t, $flags) == $data['tag']) {
                                 if ($page->getPageKey() == null) {
                                     $page->setPageKey($t);
                                 }
                                 $data['tag'] = $t;
                                 break;
                             }
                         }
                     }
                 }
             }
             break;
         case IPage::TYPE_CATEGORY:
             $data['category'] = $page->getPageKey();
             if (strpos($page->getPageKey(), '-') >= 0) {
                 // Same remark as for tags.
                 $paginationPosts = $paginator->posts();
                 if (count($paginationPosts) > 0) {
                     $firstPost = $paginationPosts[0];
                     if ($page->getPageKey() == null) {
                         $page->setPageKey($firstPost['category']);
                     }
                     $data['category'] = $firstPost['category'];
                 }
             }
             break;
     }
     $extraData = $page->getExtraPageData();
     if ($extraData) {
         if (is_array($extraData)) {
             $data = Configuration::mergeArrays($data, $extraData);
         } else {
             $data['extra'] = $extraData;
         }
     }
     return $data;
 }