Example #1
0
 public function testMerge()
 {
     $pc = new Configuration(array('site' => array('title' => "Untitled", 'root' => "/")));
     $this->assertEquals("Untitled", $pc->getValue('site/title'));
     $this->assertEquals("/", $pc->getValue('site/root'));
     $this->assertEquals(null, $pc->getValue('site/other'));
     $this->assertEquals(null, $pc->getValue('foo/bar'));
     $this->assertEquals(null, $pc->getValue('simple'));
     $pc->merge(array('site' => array('title' => "Merged Title", 'root' => "http://root", 'other' => "Something"), 'foo' => array('bar' => "FOO BAR!"), 'simple' => "simple value"));
     $this->assertEquals("Merged Title", $pc->getValue('site/title'));
     $this->assertEquals("http://root", $pc->getValue('site/root'));
     $this->assertEquals("Something", $pc->getValue('site/other'));
     $this->assertEquals("FOO BAR!", $pc->getValue('foo/bar'));
     $this->assertEquals("simple value", $pc->getValue('simple'));
 }
Example #2
0
 public function __construct(IPage $page, array $config = null, $validate = true)
 {
     $this->page = $page;
     // This needs to be set first because if $validate is 'true',
     // we'll need access to the page's PieCrust application for
     // validating configuration values.
     parent::__construct($config, $validate);
 }
Example #3
0
 protected function convertPage($relative, $outputPath, $isTemplate = false)
 {
     $this->logger->debug("Converting {$relative}");
     $pieCrustRelative = PieCrustHelper::getRelativePath($this->pieCrust, $outputPath);
     $this->logger->debug(" -> {$pieCrustRelative}");
     $this->modified[$pieCrustRelative] = array();
     $absolute = $this->rootDir . $relative;
     $contents = file_get_contents($absolute);
     $wrapContentTag = true;
     $header = Configuration::parseHeader($contents);
     $text = substr($contents, $header->textOffset);
     $textBeforeConversion = $text;
     if ($isTemplate) {
         $config = $header->config;
         if (isset($config['layout'])) {
             // Liquid doesn't support template inheritance,
             // but Twig does.
             $text = "{% extends '{$config['layout']}.html' %}\n\n" . "{% block jekyllcontent %}\n" . $text . "\n" . "{% endblock %}\n";
             $wrapContentTag = false;
             $this->modified[$pieCrustRelative]['layout_extends'] = true;
         }
     } else {
         // Convert the config.
         $config = $header->config;
         if (isset($config['layout'])) {
             // PieCrust uses 'none' instead of 'nil'.
             if ($config['layout'] == 'nil') {
                 $config['layout'] = 'none';
             }
         }
         // PieCrust defines everything in the config header,
         // including the format of the text.
         $pathinfo = pathinfo($relative);
         if ($pathinfo['extension'] != 'html') {
             $config['format'] = $pathinfo['extension'];
         } else {
             $config['format'] = 'none';
         }
     }
     // Convert the template stuff we can:
     // - content tag may have to be wrapped in a `jekyllcontent`
     //   because Jekyll uses implicit layout inheritance
     //   placements.
     if ($wrapContentTag) {
         $text = preg_replace('/{{\\s*content\\s*}}/', '{% block jekyllcontent %}{{ content }}{% endblock %}', $text);
     }
     // - list of posts
     $text = preg_replace('/(?<=\\{%|{)([^\\}]*)site.posts/', '\\1blog.posts', $text);
     $text = preg_replace('/(?<=\\{%|{)([^\\}]*)paginator.posts/', '\\1pagination.posts', $text);
     // - list of categories or tags
     $text = preg_replace('/(?<=\\{%|{)([^\\}]*)site.categories/', '\\1blog.categories', $text);
     $text = preg_replace('/(?<=\\{%|{)([^\\}]*)site.tags/', '\\1blog.tags', $text);
     // - list of related posts
     $text = preg_replace('/(?<=\\{%|{)(?<!%\\})site.related_posts/', '\\1pagination.related_posts', $text);
     // - enumeration limits
     $text = preg_replace('/{%\\s*for\\s+([^}]+)\\s+limit\\:\\s*(\\d+)/', '{% for \\1 | slice(0, \\2)', $text);
     $text = preg_replace('/{%\\s*for\\s+([^}]+)\\s+offset\\:\\s*(\\d+)/', '{% for \\1 | slice(\\2)', $text);
     // - code highlighting
     $text = preg_replace('/{%\\s*highlight\\s+([\\w\\d]+)\\s*%}/', '{% geshi \'\\1\' %}', $text);
     $text = preg_replace('/{%\\s*endhighlight\\s*%}/', '{% endgeshi %}', $text);
     // - unless tag
     $text = preg_replace('/{%\\s*unless\\s+([^}]+)\\s*%}/', '{% if not \\1 %}', $text);
     $text = preg_replace('/{%\\s*endunless\\s*%}/', '{% endif %}', $text);
     // - variable assignment
     $text = preg_replace('/\\{%\\s*assign\\s+/', '{% set ', $text);
     // - include tag
     $text = preg_replace('/\\{%\\s*include\\s+([\\w\\d\\.\\-_]+)\\s*%}/', '{% include "\\1" %}', $text);
     // - truncate filter
     $text = preg_replace('/\\|\\s*truncate\\:\\s*(\\d+)/', '|slice(0, \\1)', $text);
     // - date filter
     $text = preg_replace('/\\|\\s*date\\:\\s*"([^"]+)"/', '|date("\\1")', $text);
     // - some filters we don't need
     $text = preg_replace('/\\|\\s*date_to_string/', '', $text);
     // Create the destination directory if needed.
     if (!is_dir(dirname($outputPath))) {
         mkdir(dirname($outputPath), 0755, true);
     }
     // Create a backup file if we converted a lot of stuff.
     if ($text != $textBeforeConversion) {
         $this->modified[$pieCrustRelative]['liquid_to_twig'] = true;
         // Add a backup of the original content.
         $backupPath = $outputPath . '.original';
         file_put_contents($backupPath, $contents);
     }
     // Save the converted contents.
     $convertedContents = '';
     if (!$isTemplate and count($config) > 0) {
         $convertedContents .= "---\n";
         $convertedContents .= Yaml::dump($config, 3);
         $convertedContents .= "---\n";
     }
     $convertedContents .= $text;
     file_put_contents($outputPath, $convertedContents);
 }
Example #4
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;
 }
Example #5
0
 protected function loadUnsafe()
 {
     if ($this->wasCached()) {
         // Get the page from the cache.
         $configText = $this->cache->read($this->page->getUri(), 'json');
         $config = json_decode($configText, true);
         $this->page->getConfig()->set($config, false);
         // false = No need to validate this.
         if (!$this->page->getConfig()->hasValue('segments')) {
             throw new PieCrustException("Can't get segments list from cache.");
         }
         $contents = array();
         foreach ($config['segments'] as $key) {
             $contents[$key] = json_decode($this->cache->read($this->page->getUri(), $key . '.json'), true);
         }
         return $contents;
     } else {
         // Load the page from disk.
         $rawContents = file_get_contents($this->page->getPath());
         $parsedContents = Configuration::parseHeader($rawContents);
         // Set the configuration.
         $config = $this->page->getConfig();
         $config->set($parsedContents['config']);
         // Set the raw content with the unparsed content segments.
         $rawSegmentsOffset = $parsedContents['text_offset'];
         $contents = $this->parseContentSegments($rawContents, $rawSegmentsOffset);
         // Add the list of known segments to the configuration.
         foreach ($contents as $key => $segment) {
             $config->appendValue('segments', $key);
         }
         // Cache that shit out.
         if ($this->cache != null) {
             $yamlMarkup = json_encode($config->get());
             $this->cache->write($this->page->getUri(), 'json', $yamlMarkup);
             $keys = $config['segments'];
             foreach ($keys as $key) {
                 $this->cache->write($this->page->getUri() . '.' . $key, 'json', json_encode($contents[$key]));
             }
         }
         return $contents;
     }
 }
Example #6
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;
 }
Example #7
0
 protected function loadUnsafe()
 {
     if ($this->wasCached()) {
         // Get the page from the cache.
         $configText = $this->cache->read($this->page->getUri(), 'json');
         $config = json_decode($configText, true);
         $this->page->getConfig()->set($config, false);
         // false = No need to validate this.
         if (!$this->page->getConfig()->hasValue('segments')) {
             throw new PieCrustException("Can't get segments list from cache.");
         }
         $contents = array();
         foreach ($config['segments'] as $key) {
             $segmentText = $this->cache->read($this->page->getUri() . '.' . $key, 'json');
             $contents[$key] = json_decode($segmentText);
             // The deserialized JSON object is not of type `ContentSegment` but will
             // have the same attributes so it should work all fine.
             // Sanity test: if the first content segment is null, it may mean that the
             // original page file was in a non-supported encoding.
             if (count($contents[$key]) > 0 && $contents[$key]->parts[0]->content === null) {
                 throw new PieCrustException("Corrupted cache: is the page not saved in UTF-8 encoding?");
             }
         }
         return $contents;
     } else {
         // Load the page from disk.
         $rawContents = file_get_contents($this->page->getPath());
         $rawContents = PageLoader::removeUnicodeBOM($rawContents);
         $header = Configuration::parseHeader($rawContents);
         // Set the format from the file extension.
         if (!isset($header->config['format'])) {
             $app = $this->page->getApp();
             $autoFormats = $app->getConfig()->getValueUnchecked('site/auto_formats');
             $extension = pathinfo($this->page->getPath(), PATHINFO_EXTENSION);
             if (isset($autoFormats[$extension])) {
                 $format = $autoFormats[$extension];
                 if ($format) {
                     $header->config['format'] = $autoFormats[$extension];
                 }
             }
         }
         // Set the configuration.
         $config = $this->page->getConfig();
         $config->set($header->config);
         // Set the raw content with the unparsed content segments.
         $contents = $this->parseContentSegments($rawContents, $header->textOffset);
         // Add the list of known segments to the configuration.
         foreach ($contents as $key => $segment) {
             $config->appendValue('segments', $key);
         }
         // Cache that shit out.
         if ($this->cache != null) {
             $cacheUri = $this->page->getUri();
             if ($cacheUri == '') {
                 $cacheUri = '_index';
             }
             $configText = json_encode($config->get());
             $this->cache->write($cacheUri, 'json', $configText);
             $keys = $config['segments'];
             foreach ($keys as $key) {
                 $segmentText = json_encode($contents[$key]);
                 $this->cache->write($cacheUri . '.' . $key, 'json', $segmentText);
             }
         }
         return $contents;
     }
 }