function ensure_cache($cacheDir, $ensureClean = true) { if ($cacheDir == null or $cacheDir == '') { throw new Exception('Need a valid cache directory.'); } if ($ensureClean and is_dir($cacheDir)) { PathHelper::deleteDirectoryContents($cacheDir); } PathHelper::ensureDirectory($cacheDir); }
public static function unzip($zipfile, $destination, $logger = null) { $destination = rtrim($destination, '/\\') . '/'; $zip = zip_open($zipfile); if (!is_resource($zip)) { throw new PieCrustException("Error opening ZIP file: {$zipfile}"); } while ($entry = zip_read($zip)) { zip_entry_open($zip, $entry); $entryName = zip_entry_name($entry); if ($logger) { $logger->debug("Extracting {$entryName}..."); } $path = $destination . $entryName; $contents = zip_entry_read($entry, zip_entry_filesize($entry)); PathHelper::ensureDirectory(dirname($path)); file_put_contents($path, $contents); zip_entry_close($entry); } zip_close($zip); }
public function __construct($withDefaultStructure = true, $useRealPath = false) { $this->isRootReal = (bool) $useRealPath; if ($useRealPath) { $this->root = PIECRUST_UNITTESTS_MOCK_DIR . 'root_' . rand(); PathHelper::ensureDirectory($this->root, true); if ($withDefaultStructure) { mkdir($this->root . '/kitchen'); mkdir($this->root . '/kitchen/_content'); file_put_contents($this->root . '/kitchen/_content/config.yml', "site:\n title: Mock Website"); mkdir($this->root . '/counter'); } } else { $this->root = 'root_' . rand(); $structure = array(); if ($withDefaultStructure) { $structure['kitchen'] = array('_content' => array('config.yml' => "site:\n title: Mock Website")); $structure['counter'] = array(); } vfsStream::setup($this->root, null, $structure); } }
protected function processNode($node) { // Get the input path. $nodeRootDir = $this->getNodeRootDir($node); $path = $nodeRootDir . $node->getPath(); // Get the output directory. // (all outputs of a node go to the same directory, so we // can just get the directory of the first output node). $nodeOutputs = $node->getOutputs(); $outputRootDir = $this->getNodeRootDir($nodeOutputs[0]); $outputChildDir = dirname($node->getPath()); if ($outputChildDir == '.') { $outputChildDir = ''; } $outputDir = $outputRootDir . $outputChildDir; if ($outputChildDir != '') { $outputDir .= '/'; } $relativeOutputDir = PathHelper::getRelativePath($this->rootDir, $outputDir); PathHelper::ensureDirectory($outputDir, true); // If we need to, re-process the node! $didBake = false; try { $start = microtime(true); $processor = $node->getProcessor(); if ($processor->process($path, $outputDir) !== false) { $end = microtime(true); $processTime = sprintf('%8.1f ms', ($end - $start) * 1000.0); $this->printProcessingTreeNode($node, "-> '{$relativeOutputDir}' [{$processTime}]."); $didBake = true; } else { $this->printProcessingTreeNode($node, "-> '{$relativeOutputDir}' [clean]."); } } catch (Exception $e) { throw new PieCrustException("Error processing '{$node->getPath()}': {$e->getMessage()}", 0, $e); } return $didBake; }
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; }
protected function createDirectory($rootDir, $dir, $makeWritable = false) { PathHelper::ensureDirectory($rootDir . $dir, $makeWritable); }
protected function ensureLevel0Cache() { PathHelper::ensureDirectory($this->pieCrust->getCacheDir() . 'bake_t/0', true); }
public static function serialize($obj, $filename) { PathHelper::ensureDirectory(dirname($filename), true); $data = self::serializeData($obj); file_put_contents($filename, $data); }
protected function processNode($node) { // Get the input path. $nodeRootDir = $this->getNodeRootDir($node); $path = $nodeRootDir . $node->getPath(); // If the processor for this node wants to bypass structured // processing altogether, run it now and exit. $processor = $node->getProcessor(); if ($processor->isBypassingStructuredProcessing()) { try { $start = microtime(true); $processor->process($path, $this->outDir); $end = microtime(true); $processTime = sprintf('%.1f ms', ($end - $start) * 1000.0); $this->printProcessingTreeNode($node, " (bypassing structured processing) [{$processTime}]."); } catch (Exception $e) { throw new PieCrustException("Error processing '{$node->getPath()}'.", 0, $e); } return true; } // Get the output directory. // (all outputs of a node go to the same directory, so we // can just get the directory of the first output node). $nodeOutputs = $node->getOutputs(); $outputRootDir = $this->getNodeRootDir($nodeOutputs[0]); $outputChildDir = dirname($node->getPath()); if ($outputChildDir == '.') { $outputChildDir = ''; } $outputDir = $outputRootDir . $outputChildDir; if ($outputChildDir != '') { $outputDir .= '/'; } $relativeOutputDir = PathHelper::getRelativePath($this->rootDir, $outputDir); PathHelper::ensureDirectory($outputDir, true); // Now process the node! $didBake = false; try { $start = microtime(true); $processResult = $processor->process($path, $outputDir); $end = microtime(true); $processTime = sprintf('%.1f ms', ($end - $start) * 1000.0); if ($processResult !== false) { $this->printProcessingTreeNode($node, "-> '{$relativeOutputDir}' [{$processTime}]."); $didBake = true; } else { $this->printProcessingTreeNode($node, "-> '{$relativeOutputDir}' [clean, {$processTime}]."); } } catch (Exception $e) { throw new PieCrustException("Error processing '{$node->getPath()}'.", 0, $e); } return $didBake; }
protected function ensureWebServer() { if ($this->server != null) { return; } PathHelper::ensureDirectory($this->bakeCacheDir); // Set-up the stupid web server. $this->server = new StupidHttp_WebServer($this->bakeCacheDir, $this->options['port'], $this->options['address']); if ($this->options['log_file']) { $this->server->setLog(StupidHttp_PearLog::fromSingleton('file', $this->options['log_file'])); } elseif ($this->logger != null && !$this->logger instanceof \Log_null) { $this->server->setLog(new StupidHttp_PearLog($this->logger)); } else { $this->server->setLog(new StupidHttp_ConsoleLog(StupidHttp_Log::TYPE_INFO)); } foreach ($this->options['mime_types'] as $ext => $mime) { $this->server->setMimeType($ext, $mime); } // Mount the `_content` directory so that we can see page assets. $this->server->mount($this->rootDir . DIRECTORY_SEPARATOR . '_content', '_content'); $self = $this; // Workaround for $this not being capturable in closures. $this->server->onPattern('GET', '.*')->call(function ($context) use($self) { $self->_runPieCrustRequest($context); }); $this->server->setPreprocessor(function ($req) use($self) { $self->_preprocessRequest($req); }); }
protected function extractRepository($context, $destination, $userName, $repoSlug, $rev = 'default') { $app = $context->getApp(); $log = $context->getLog(); $cacheDir = $app->getCacheDir(); if (!$cacheDir) { // If the cache doesn't exist or the application is running // with caching disabled, we still need to create a cache directory // to download the archive somewhere. $cacheDir = $app->getRootDir() . PieCrustDefaults::CACHE_DIR; PathHelper::ensureDirectory($cacheDir, true); } $url = "https://bitbucket.org/{$userName}/{$repoSlug}/get/{$rev}.zip"; $log->info("Downloading archive..."); $log->debug("Fetching '{$url}'..."); $contents = file_get_contents($url); $tempZip = $cacheDir . $repoSlug . '.zip'; file_put_contents($tempZip, $contents); $log->info("Extracting..."); $log->debug("Unzipping into: {$cacheDir}"); ArchiveHelper::unzip($tempZip, $cacheDir, $log); $globbed = glob($cacheDir . $userName . '-' . $repoSlug . '-*', GLOB_ONLYDIR | GLOB_MARK); if (count($globbed) != 1) { throw new PieCrustException("Can't find extracted directory for downloaded archive!"); } $archiveDir = $globbed[0]; if (is_dir($destination)) { $log->debug("Cleaning destination: {$destination}"); PathHelper::deleteDirectoryContents($destination); } if (!is_dir(dirname($destination))) { mkdir(dirname($destination)); } $log->debug("Moving extracted files into: {$destination}"); rename($archiveDir, $destination); $log->debug("Cleaning up..."); unlink($tempZip); }
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; }