public function run(ChefContext $context) { $result = $context->getResult(); // Display usage for `chef` along with the list of known additional topics. if (!isset($result->command->args['topic'])) { $this->parser->parent->displayUsage(false); echo "Additional help topics:" . PHP_EOL; foreach (array_keys($this->parser->helpTopics) as $topic) { echo " {$topic}" . PHP_EOL; } echo PHP_EOL; exit(0); } $topic = $result->command->args['topic']; // Look for a help topic. if (isset($this->parser->helpTopics[$topic])) { $helpTopic = $this->parser->helpTopics[$topic]; if (is_callable($helpTopic)) { call_user_func($helpTopic, $context); } else { echo $helpTopic; } exit(0); } // Command help. $parentParser = $this->parser->parent; if (isset($parentParser->commands[$topic])) { echo $parentParser->commands[$topic]->displayUsage(false); exit(0); } throw new PieCrustException("No such command or help topic: " . $topic); }
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; }
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)"); } }
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); } } $result->command->args['pattern'] = $pattern; $foundAny = false; // Find pages. if ($returnAllTypes or $result->command->options['pages']) { $pages = PageHelper::getPages($pieCrust); $foundAny |= $this->findPages($context, $pages); } // Find posts. 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 = PageHelper::getPosts($pieCrust, $blogKey); $pagesIterator = new \ArrayIterator($pages); $sorter = new DateSortIterator($pagesIterator); $pages = iterator_to_array($sorter); $foundAny |= $this->findPages($context, $pages, $blogKey); } } // Find templates. if ($returnAllTypes or $result->command->options['templates']) { $templatesDirs = $pieCrust->getTemplatesDirs(); foreach ($templatesDirs as $dir) { $foundAny |= $this->findTemplates($context, $dir); } } if (!$foundAny) { $pattern = $result->command->args['pattern']; $logger->info("No match found for '{$pattern}'."); } return 0; }
public function run(ChefContext $context) { $result = $context->getResult(); $log = $context->getLog(); $rootDir = $context->getApp()->getRootDir(); $fullAddress = $result->command->args['server']; $matches = array(); if (!preg_match('/^([^:]+)(\\:([^@]+))?@(.*)$/', $fullAddress, $matches)) { throw new PieCrustException("The given upload address was not valid. Must be of form: user:password@domain.tld"); } $user = $matches[1]; $password = $matches[3]; $server = $matches[4]; $remoteRootDir = $result->command->options['remote_root']; if (!$remoteRootDir) { $remoteRootDir = '/'; } $remoteRootDir = rtrim($remoteRootDir, '/\\') . '/'; $passiveMode = $result->command->options['passive']; $syncMode = FTP_SYNC_ALWAYS; switch ($result->command->options['sync_mode']) { case 'time': $syncMode = FTP_SYNC_IF_NEWER; break; case 'time_and_size': $syncMode = FTP_SYNC_IF_NEWER_OR_DIFFERENT_SIZE; break; } $simulate = $result->command->options['simulate']; $log->info("Uploading to '{$server}' [{$remoteRootDir}] as {$user}"); $conn = ftp_connect($server); if ($conn === false) { throw new PieCrustException("Can't connect to FTP server '{$server}'."); } if (!isset($password) or $password == "") { $password = prompt_silent("Password: "******"Connected to FTP server '{$server}'."); if ($passiveMode) { $log->info("Enabling passive mode."); if (!ftp_pasv($conn, true)) { throw new PieCrustException("Can't enable passive mode."); } } sync_ftp($conn, $rootDir, $remoteRootDir, $syncMode, $simulate); } else { throw new PieCrustException("Couldn't connect to FTP server '{$server}', login incorrect."); } } catch (Exception $e) { ftp_close($conn); throw $e; } ftp_close($conn); }
public function run(ChefContext $context) { $this->log = $context->getLog(); $result = $context->getResult(); $rootDir = $result->command->args['destination']; if (!$rootDir) { $rootDir = getcwd(); } $this->initializeWebsite($rootDir, array('apache' => $result->command->options['apache'], 'iis' => $result->command->options['iis'])); }
public function run(ChefContext $context) { $cacheDir = $context->getApp()->getCacheDir(); if (!$cacheDir) { throw new PieCrustException("The website seems to have caching disabled."); } if (!is_dir($cacheDir)) { throw new PieCrustException("The cache directory doesn't exist: {$cacheDir}"); } $context->getLog()->info("Purging cache: {$cacheDir}"); PathHelper::deleteDirectoryContents($cacheDir); }
public function run(ChefContext $context) { $result = $context->getResult(); $app = $context->getApp(); $log = $context->getLog(); // Create the posts directory if it doesn't exist. if ($app->getPostsDir() == false) { $postsDir = $app->getRootDir() . PieCrustDefaults::CONTENT_POSTS_DIR; $log->info("Creating posts directory: {$postsDir}"); mkdir($postsDir, 0777, true); $app->setPostsDir($postsDir); } // Create the relative path of the new post by using the // path format of the website's post file-system. $slug = $result->command->command->args['slug']; $captureGroups = array('day' => date('d'), 'month' => date('m'), 'year' => date('Y'), 'slug' => $slug, 'ext' => 'html'); // Figure out which blog to create this post for (if the website // is hosting several blogs). $blogKey = $result->command->command->options['blog']; $blogKeys = $app->getConfig()->getValue('site/blogs'); if ($blogKey == null) { $blogKey = $blogKeys[0]; } else { if (!in_array($blogKey, $blogKeys)) { throw new PieCrustException("Specified blog '{$blogKey}' is not one of the known blogs in this website: " . implode(', ', $blogKeys)); } } // Create the full path. $fs = $app->getEnvironment()->getFileSystem(); $pathInfo = $fs->getPostPathInfo($blogKey, $captureGroups, FileSystem::PATHINFO_CREATING); $fullPath = $pathInfo['path']; $relativePath = PieCrustHelper::getRelativePath($app, $fullPath); if (file_exists($fullPath)) { throw new PieCrustException("Post already exists: {$relativePath}"); } $log->info("Creating new post: {$relativePath}"); // Create the title and time of post. $title = preg_replace('/[\\-_]+/', ' ', $slug); $title = ucwords($title); $time = date('H:i:s'); // Write the contents. if (!is_dir(dirname($fullPath))) { mkdir(dirname($fullPath), 0777, true); } $f = fopen($fullPath, 'w'); fwrite($f, "---\n"); fwrite($f, "title: {$title}\n"); fwrite($f, "time: {$time}\n"); fwrite($f, "---\n"); fwrite($f, "My new blog post!\n"); fclose($f); }
public function run(ChefContext $context) { $result = $context->getResult(); // Validate arguments. $format = $result->command->args['format']; $source = $result->command->args['source']; if (!$format or !$source) { // Warning for the old syntax. throw new PieCrustException("The syntax for this command has changed: specify the format and the source as arguments. See `chef import -h` for help."); } // Start importing! $importer = new PieCrustImporter($context->getApp(), $context->getLog()); $importer->import($format, $source, $result->command->options); }
public function run(ChefContext $context) { $pieCrust = $context->getApp(); $result = $context->getResult(); $outputDir = $result->command->options['output']; // Warn about deprecated stuff. if ($result->command->options['file_urls']) { $context->getLog()->warning("The `--fileurls` option has been deprecated. Please use `--portable` instead."); $result->command->options['portable_urls'] = true; } if ($result->command->options['pretty_urls_old']) { $context->getLog()->err("The `--prettyurls` option has been deprecated. Please use a config variant instead."); return; } if ($result->command->options['root_url_old']) { $context->getLog()->err("The `--rooturl` option has been deprecated. Please use a config variant instead."); return; } // Set-up the app and the baker. $bakerParameters = array('smart' => !$result->command->options['force'], 'clean_cache' => $result->command->options['force'], 'info_only' => $result->command->options['info_only'], 'config_variant' => $result->command->options['config_variant']); $baker = new PieCrustBaker($pieCrust, $bakerParameters, $context->getLog()); if ($outputDir) { $baker->setBakeDir($outputDir); } if ($result->command->options['portable_urls']) { $pieCrust->getConfig()->setValue('baker/portable_urls', true); // Also disable pretty URLs because it doesn't make much sense // when there's no web server handling default documents. $pieCrust->getConfig()->setValue('site/pretty_urls', false); } // Start baking! $baker->bake(); }
protected function installThemes(ChefContext $context) { $app = $context->getApp(); $log = $context->getLog(); $result = $context->getResult(); $sources = $this->getSources($app, $log); $themeName = $result->command->command->args['name']; $themes = $this->getThemeMetadata($app, $sources, $themeName, true, $log); if (count($themes) != 1) { throw new PieCrustException("Can't find a single theme named: {$themeName}"); } $theme = $themes[0]; $log->debug("Installing '{$theme['name']}' from: {$theme['source']}"); $className = $theme['repository_class']; $repository = new $className(); $context = new ThemeInstallContext($app, $log); $repository->installTheme($theme, $context); $log->info("Theme {$theme['name']} is now installed."); }
protected function installPlugins(ChefContext $context) { $app = $context->getApp(); $log = $context->getLog(); $result = $context->getResult(); $sources = $this->getSources($app, $log); $pluginName = $result->command->command->args['name']; $plugins = $this->getPluginMetadata($app, $sources, $pluginName, true, $log); if (count($plugins) != 1) { throw new PieCrustException("Can't find a single plugin named: {$pluginName}"); } $plugin = $plugins[0]; $log->debug("Installing '{$plugin['name']}' from: {$plugin['source']}"); $className = $plugin['repository_class']; $repository = new $className(); $context = new PluginInstallContext($app, $log); $repository->installPlugin($plugin, $context); $log->info("Plugin {$plugin['name']} is now installed."); }
public function run(ChefContext $context) { $app = $context->getApp(); $result = $context->getResult(); $log = $context->getLog(); $environment = $app->getEnvironment(); if (!$environment instanceof ChefEnvironment) { throw new PieCrustException("Can't run the `prepare` command without a Chef environment."); } $extensionName = $result->command->command_name; $extensions = $environment->getCommandExtensions($this->getName()); foreach ($extensions as $ext) { if ($ext->getName() == $extensionName) { $ext->run($context); return; } } throw new PieCrustException("No such extension for the `prepare` command: " . $extensionName); }
public function run(ChefContext $context) { $result = $context->getResult(); // Warn about deprecated stuff. if ($result->command->options['run_browser_old']) { $context->getLog()->warning("The `--nobrowser` option has been renamed to `--no-browser`."); $result->command->options['run_browser'] = false; } $rootDir = $context->getApp()->getRootDir(); $port = intval($result->command->options['port']); $address = $result->command->options['address']; $runBrowser = $result->command->options['run_browser']; $logFile = $result->command->options['log_file']; $debug = $result->command->options['debug']; $nocache = $result->command->options['no_cache']; // Start serving! $server = new PieCrustServer($rootDir, array('port' => $port, 'address' => $address, 'log_file' => $logFile, 'debug' => $debug, 'cache' => !$nocache), $context->getLog()); $server->run(array('list_directories' => false, 'run_browser' => $runBrowser)); }
public function run(ChefContext $context) { $logger = $context->getLog(); $pieCrust = $context->getApp(); $result = $context->getResult(); $path = $result->command->args['path']; if ($path) { $configToShow = $pieCrust->getConfig()->getValue($path); } else { $configToShow = $pieCrust->getConfig()->get(); } if ($configToShow) { if (is_array($configToShow)) { $this->printConfig($configToShow, $logger); } else { $logger->info($configToShow); } } }
public function run(ChefContext $context) { $pieCrust = $context->getApp(); $result = $context->getResult(); // Set-up the app and the baker. $bakerParameters = array('smart' => !$result->command->options['force'], 'clean_cache' => $result->command->options['force'], 'config_variant' => $result->command->options['config_variant']); if ($result->command->options['output']) { $bakerParameters['output'] = $result->command->options['output']; } $baker = new PieCrustBaker($pieCrust, $bakerParameters); if ($result->command->options['portable_urls']) { $pieCrust->getConfig()->setValue('baker/portable_urls', true); // Also disable pretty URLs because it doesn't make much sense // when there's no web server handling default documents. $pieCrust->getConfig()->setValue('site/pretty_urls', false); } // Start baking! $baker->bake(); }
public function run(ChefContext $context) { $result = $context->getResult(); $app = $context->getApp(); $log = $context->getLog(); // Create the pages directory if it doesn't exist. if ($app->getPagesDir() == false) { $pagesDir = $app->getRootDir() . PieCrustDefaults::CONTENT_PAGES_DIR; $log->info("Creating pages directory: {$pagesDir}"); mkdir($pagesDir, 0777, true); $app->setPagesDir($pagesDir); } // Create the path of the feed. $slug = $result->command->command->args['url']; $slug = ltrim($slug, '/\\'); $fullPath = $app->getPagesDir() . $slug; if (!preg_match('/\\.[a-z0-9]+$/i', $slug)) { $fullPath .= '.html'; } $relativePath = PieCrustHelper::getRelativePath($app, $fullPath); if (file_exists($fullPath)) { throw new PieCrustException("Page already exists: {$relativePath}"); } $log->info("Creating feed: {$relativePath}"); // Get the feed template. $templatePath = PieCrustDefaults::RES_DIR() . 'prepare/rss.html'; if ($result->command->command->options['use_atom']) { $templatePath = PieCrustDefaults::RES_DIR() . 'prepare/atom.html'; } $template = file_get_contents($templatePath); // Write the contents. if (!is_dir(dirname($fullPath))) { mkdir(dirname($fullPath), 0777, true); } $f = fopen($fullPath, 'w'); fwrite($f, $template); fclose($f); $fullUrl = $app->getConfig()->getValue('site/root') . $slug; $log->info("Don't forget to add a link into your main page's header like so:"); $log->info("<link rel=\"alternate\" type=\"application/rss+xml\" href=\"{$fullUrl}\" />"); }
public function run(ChefContext $context) { $result = $context->getResult(); $app = $context->getApp(); $log = $context->getLog(); // Create the pages directory if it doesn't exist. if ($app->getPagesDir() == false) { $pagesDir = $app->getRootDir() . PieCrustDefaults::CONTENT_PAGES_DIR; $log->info("Creating pages directory: {$pagesDir}"); mkdir($pagesDir, 0777, true); $app->setPagesDir($pagesDir); } // Create the path of the new page. $slug = $result->command->command->args['slug']; $slug = ltrim($slug, '/\\'); $fullPath = $app->getPagesDir() . $slug; if (!preg_match('/\\.[a-z0-9]+$/i', $slug)) { $fullPath .= '.html'; } $relativePath = PieCrustHelper::getRelativePath($app, $fullPath); if (file_exists($fullPath)) { throw new PieCrustException("Page already exists: {$relativePath}"); } $log->info("Creating new page: {$relativePath}"); // Create the title and date/time of post. $title = preg_replace('/[\\-_]+/', ' ', $slug); $title = ucwords($title); $date = date('Y-m-d H:i'); // Write the contents. if (!is_dir(dirname($fullPath))) { mkdir(dirname($fullPath), 0777, true); } $f = fopen($fullPath, 'w'); fwrite($f, "---\n"); fwrite($f, "title: {$title}\n"); fwrite($f, "date: {$date}\n"); fwrite($f, "---\n"); fwrite($f, "A new page.\n"); fclose($f); }
/** * Runs Chef given some command-line arguments. */ public function runUnsafe($userArgc = null, $userArgv = null) { // Get the arguments. if ($userArgc == null || $userArgv == null) { $getopt = new \Console_Getopt(); $userArgv = $getopt->readPHPArgv(); // `readPHPArgv` returns a `PEAR_Error` (or something like it) if // it can't figure out the CLI arguments. if (!is_array($userArgv)) { throw new PieCrustException($userArgv->getMessage()); } $userArgc = count($userArgv); } // Find whether the '--root' parameter was given. $rootDir = null; foreach ($userArgv as $arg) { if (substr($arg, 0, strlen('--root=')) == '--root=') { $rootDir = substr($arg, strlen('--root=')); break; } } if ($rootDir == null) { // No root given. Find it ourselves. $rootDir = PathHelper::getAppRootDir(getcwd()); } else { // The root was given. $rootDir = PathHelper::getAbsolutePath($rootDir); if (!is_dir($rootDir)) { throw new PieCrustException("The given root directory doesn't exist: " . $rootDir); } } // Build the appropriate app. if ($rootDir == null) { $pieCrust = new NullPieCrust(); } else { $pieCrust = new PieCrust(array('root' => $rootDir, 'cache' => !in_array('--no-cache', $userArgv))); } // Set up the command line parser. $parser = new \Console_CommandLine(array('name' => 'chef', 'description' => 'The PieCrust chef manages your website.', 'version' => PieCrustDefaults::VERSION)); // Sort commands by name. $sortedCommands = $pieCrust->getPluginLoader()->getCommands(); usort($sortedCommands, function ($c1, $c2) { return strcmp($c1->getName(), $c2->getName()); }); // Add commands to the parser. foreach ($sortedCommands as $command) { $commandParser = $parser->addCommand($command->getName()); $command->setupParser($commandParser, $pieCrust); $this->addCommonOptionsAndArguments($commandParser); } // Parse the command line. try { $result = $parser->parse($userArgc, $userArgv); } catch (Exception $e) { $parser->displayError($e->getMessage()); return 1; } // If no command was given, use `help`. if (empty($result->command_name)) { $result = $parser->parse(2, array('chef', 'help')); } // Create the log. $debugMode = $result->command->options['debug']; $quietMode = $result->command->options['quiet']; if ($debugMode && $quietMode) { $parser->displayError("You can't specify both --debug and --quiet."); return 1; } $log = \Log::singleton('console', 'Chef', '', array('lineFormat' => '%{message}')); // Make the log available for debugging purposes. $GLOBALS['__CHEF_LOG'] = $log; // Handle deprecated stuff. if ($result->command->options['no_cache_old']) { $log->warning("The `--nocache` option has been renamed `--no-cache`."); $result->command->options['no_cache'] = true; } // Run the command. foreach ($pieCrust->getPluginLoader()->getCommands() as $command) { if ($command->getName() == $result->command_name) { try { if ($rootDir == null && $command->requiresWebsite()) { $cwd = getcwd(); throw new PieCrustException("No PieCrust website in '{$cwd}' ('_content/config.yml' not found!)."); } $context = new ChefContext($pieCrust, $result, $log); $context->setVerbosity($debugMode ? 'debug' : ($quietMode ? 'quiet' : 'default')); $command->run($context); return; } catch (Exception $e) { $log->emerg(self::getErrorMessage($e, $debugMode)); return 1; } } } }
/** * Runs Chef given some command-line arguments. */ public function runUnsafe($userArgc = null, $userArgv = null) { // Get the arguments. if ($userArgc == null || $userArgv == null) { $getopt = new \Console_Getopt(); $userArgv = $getopt->readPHPArgv(); // `readPHPArgv` returns a `PEAR_Error` (or something like it) if // it can't figure out the CLI arguments. if (!is_array($userArgv)) { throw new PieCrustException($userArgv->getMessage()); } $userArgc = count($userArgv); } // Find if whether the `--root` or `--config` parameters were given. $rootDir = null; $isThemeSite = false; $configVariant = null; for ($i = 1; $i < count($userArgv); ++$i) { $arg = $userArgv[$i]; if (substr($arg, 0, strlen('--root=')) == '--root=') { $rootDir = substr($arg, strlen('--root=')); if (substr($rootDir, 0, 1) == '~') { $rootDir = getenv("HOME") . substr($rootDir, 1); } } elseif ($arg == '--root') { $rootDir = $userArgv[$i + 1]; ++$i; } elseif (substr($arg, 0, strlen('--config=')) == '--config=') { $configVariant = substr($arg, strlen('--config=')); } elseif ($arg == '--config') { $configVariant = $userArgv[$i + 1]; ++$i; } elseif ($arg == '--theme') { $isThemeSite = true; } else { if ($arg[0] != '-') { // End of the global arguments sections. This is // the command name. break; } } } if ($rootDir == null) { // No root given. Find it ourselves. $rootDir = PathHelper::getAppRootDir(getcwd(), $isThemeSite); } else { // The root was given. $rootDir = trim($rootDir, " \""); if (!is_dir($rootDir)) { throw new PieCrustException("The given root directory doesn't exist: " . $rootDir); } } // Build the appropriate app. if ($rootDir == null) { $pieCrust = new NullPieCrust(); } else { $environment = new ChefEnvironment(); $pieCrust = new PieCrust(array('root' => $rootDir, 'cache' => !in_array('--no-cache', $userArgv), 'environment' => $environment, 'theme_site' => $isThemeSite)); } // Pre-load the correct config variant if any was specified. if ($configVariant != null) { // You can't apply a config variant if there's no website. if ($rootDir == null) { $cwd = getcwd(); throw new PieCrustException("No PieCrust website in '{$cwd}' ('_content/config.yml' not found!)."); } $configVariant = trim($configVariant, " \""); $pieCrust->getConfig()->applyVariant('variants/' . $configVariant); } // Set up the command line parser. $parser = new \Console_CommandLine(array('name' => 'chef', 'description' => 'The PieCrust chef manages your website.', 'version' => PieCrustDefaults::VERSION)); $parser->renderer = new ChefCommandLineRenderer($parser); $this->addCommonOptionsAndArguments($parser); // Sort commands by name. $sortedCommands = $pieCrust->getPluginLoader()->getCommands(); usort($sortedCommands, function ($com1, $com2) { return strcmp($com1->getName(), $com2->getName()); }); // Add commands to the parser. foreach ($sortedCommands as $command) { $commandParser = $parser->addCommand($command->getName()); $command->setupParser($commandParser, $pieCrust); } // Parse the command line. try { $result = $parser->parse($userArgc, $userArgv); } catch (Exception $e) { $parser->displayError($e->getMessage(), false); return 3; } // If no command was given, use `help`. if (empty($result->command_name)) { $result = $parser->parse(2, array('chef', 'help')); } // Create the log. $debugMode = $result->options['debug']; $quietMode = $result->options['quiet']; if ($debugMode && $quietMode) { $parser->displayError("You can't specify both --debug and --quiet.", false); return 1; } $log = new ChefLog('Chef'); // Log to a file. if ($result->options['log']) { $log->addFileLog($result->options['log']); } // Make the log available to PieCrust. if ($rootDir != null) { $environment->setLog($log); } // Make the log available for debugging purposes. $GLOBALS['__CHEF_LOG'] = $log; // Run the command. foreach ($pieCrust->getPluginLoader()->getCommands() as $command) { if ($command->getName() == $result->command_name) { try { if ($rootDir == null && $command->requiresWebsite()) { $cwd = getcwd(); throw new PieCrustException("No PieCrust website in '{$cwd}' ('_content/config.yml' not found!)."); } if ($debugMode) { $log->debug("PieCrust v." . PieCrustDefaults::VERSION); $log->debug(" Website: {$rootDir}"); } $context = new ChefContext($pieCrust, $result, $log); $context->setVerbosity($debugMode ? 'debug' : ($quietMode ? 'quiet' : 'default')); $command->run($context); return; } catch (Exception $e) { $log->exception($e, $debugMode); return 1; } } } }
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; }
protected function installRequirements(array $theme, ChefContext $context) { if (!isset($theme['requires'])) { return; } $log = $context->getLog(); $requirements = $theme['requires']; if (isset($requirements['plugins'])) { $requiredPlugins = $requirements['plugins']; if (!is_array($requiredPlugins)) { $requiredPlugins = array($requiredPlugins); } $log->info("Installing required plugins: "); $installer = new PluginsCommand(); foreach ($requiredPlugins as $pluginName) { $log->debug("Installing {$pluginName}..."); $installer->installPlugin($pluginName, $context); } } }
protected function updatePlugins(ChefContext $context) { $app = $context->getApp(); $log = $context->getLog(); $result = $context->getResult(); $pluginName = $result->command->command->args['name']; // Right now we do it the brute force way: update everything. // TODO: keep some metadata on the installed version so we don't overwrite with the exact same. $pluginLoader = $app->getPluginLoader(); foreach ($pluginLoader->getPlugins() as $plugin) { $curName = $plugin->getName(); if ($curName != '__builtin__' && ($curName == $pluginName || !$pluginName)) { $log->info("Updating {$curName}..."); // First, rename the existing directory. $pluginMeta = $pluginLoader->getPluginMeta($curName); $pluginDir = $pluginMeta->directory; $pluginDirBackup = $pluginDir . '__backup'; if (!rename($pluginDir, $pluginDirBackup)) { throw new PieCrustException("Can't rename plugin directory: {$pluginDir}"); } // Then, update. try { $plugin = $this->installPlugin($curName, $context); } catch (\Exception $e) { $log->debug("Error encountered, restoring backup directory."); rename($pluginDirBackup, $pluginDir); throw new PieCrustException("Error updating plugin '{$curName}'.", 0, $e); } // Last, cleanup backup directory. $log->debug("Cleaning up backup directory: {$pluginDirBackup}"); PathHelper::deleteDirectoryContents($pluginDirBackup); rmdir($pluginDirBackup); } } }
public function run(ChefContext $context) { $app = $context->getApp(); $result = $context->getResult(); $log = $context->getLog(); $matches = array(); $dryRun = false; $requirePhar = true; $fromVersion = PieCrustDefaults::VERSION; $targetVersion = $result->command->args['target']; if (substr($targetVersion, 0, 1) == ':' && preg_match("#" . "(\\:from\\:([^:]+))?" . "(\\:to\\:([^:]+))?" . "(\\:dry)?" . "#", $targetVersion, $matches)) { // Secret syntax to debug this whole shit. $fromVersion = $matches[2]; $targetVersion = $matches[4]; $dryRun = (bool) $matches[5]; $requirePhar = false; if ($fromVersion) { $log->info("OVERRIDE: from = {$fromVersion}"); } if ($targetVersion) { $log->info("OVERRIDE: to = {$targetVersion}"); } if ($dryRun) { $log->info("OVERRIDE: dry run"); } } if (!$targetVersion) { $targetVersion = $this->getNextVersion($fromVersion, $requirePhar, $log); } if (!$targetVersion) { $log->info("PieCrust is already up-to-date."); return 0; } $log->info("Updating to version {$targetVersion}..."); if ($targetVersion == 'master' or $targetVersion == 'dev') { // Aliases for the `default` Mercurial branch. $targetVersion = 'default'; } $thisPath = Phar::running(false); if (!$requirePhar and !$thisPath) { $thisPath = getcwd() . '/piecrust.phar'; } if (!$thisPath) { throw new PieCrustException("The self-update command can only be run from an installed PieCrust."); } $tempPath = $thisPath . '.downloading'; if (!is_writable(dirname($thisPath))) { throw new PieCrustException("PieCrust binary directory is not writable."); } if (is_file($thisPath) and !is_writable($thisPath)) { throw new PieCrustException("PieCrust binary is not writable."); } $pharUrl = "http://backend.bolt80.com/piecrust/{$targetVersion}/piecrust.phar"; $log->debug("Downloading: {$pharUrl}"); if ($dryRun) { return 0; } // Download the file. $fout = fopen($tempPath, 'wb'); if ($fout === false) { throw new PieCrustException("Can't write to temporary file: {$tempPath}"); } $fin = fopen($pharUrl, 'rb'); if ($fin === false) { throw new PieCrustException("Can't download binary file: {$pharUrl}"); } while (!feof($fin)) { $data = fread($fin, 8192); fwrite($fout, $data); } fclose($fin); fclose($fout); // Test the downloaded file. $log->debug("Checking downloaded file: {$tempPath}"); try { chmod($tempPath, 0777 & ~umask()); $phar = new \Phar($tempPath); // Free the variable to unlock the file. unset($phar); } catch (\Exception $e) { @unlink($tempPath); if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) { throw $e; } $log->err("The downloaded binary seems to be corrupted: {$e->getMessage()}"); $log->err("Please try running the self update command again."); return 1; } // Replace the current binary with the download. $log->debug("Replacing running binary with downloaded file."); rename($tempPath, $thisPath); }
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)"); } }
public function run(ChefContext $context) { // Don't use the context logger because we want this to be the "pure" value // so it can be re-used in other shell commands. echo rtrim($context->getApp()->getRootDir(), '/\\') . PHP_EOL; }