/**
  * Set-up default vars
  */
 public static function init()
 {
     // make sure config vars exist
     if (!Config::getOption("patternExtension")) {
         Console::writeError("the pattern extension config option needs to be set...");
     }
     if (!Config::getOption("styleguideKit")) {
         Console::writeError("the styleguideKit config option needs to be set...");
     }
     // set-up config vars
     $patternExtension = Config::getOption("patternExtension");
     $pluginDir = Config::getOption("packagesDir");
     $sourceDir = Config::getOption("sourceDir");
     $styleguideKit = Config::getOption("styleguideKit");
     // load pattern-lab's resources
     $partialPath = $pluginDir . "/" . $styleguideKit . "/views/partials";
     self::$htmlHead = file_get_contents($partialPath . "/general-header." . $patternExtension);
     self::$htmlFoot = file_get_contents($partialPath . "/general-footer." . $patternExtension);
     // gather the user-defined header and footer information
     $patternHeadPath = $sourceDir . "/_meta/_00-head." . $patternExtension;
     $patternFootPath = $sourceDir . "/_meta/_01-foot." . $patternExtension;
     self::$patternHead = file_exists($patternHeadPath) ? file_get_contents($patternHeadPath) : "";
     self::$patternFoot = file_exists($patternFootPath) ? file_get_contents($patternFootPath) : "";
     // add the filesystemLoader
     $patternEngineBasePath = PatternEngine::getInstance()->getBasePath();
     $filesystemLoaderClass = $patternEngineBasePath . "\\Loaders\\FilesystemLoader";
     $options = array();
     $options["templatePath"] = $pluginDir . "/" . $styleguideKit . "/views";
     $options["partialsPath"] = $pluginDir . "/" . $styleguideKit . "/views/partials";
     self::$filesystemLoader = new $filesystemLoaderClass($options);
     $stringLoaderClass = $patternEngineBasePath . "\\Loaders\\StringLoader";
     self::$stringLoader = new $stringLoaderClass();
     // i can't remember why i chose to implement the pattern loader directly in classes
     // i figure i had a good reason which is why it's not showing up here
 }
Beispiel #2
0
 /**
  * Write out the time tracking file so the content sync service will work. A holdover
  * from how I put together the original AJAX polling set-up.
  */
 public static function updateChangeTime()
 {
     if (is_dir(Config::getOption("publicDir"))) {
         file_put_contents(Config::getOption("publicDir") . "/latest-change.txt", time());
     } else {
         Console::writeError("the public directory for Pattern Lab doesn't exist...");
     }
 }
 public function run()
 {
     if (Console::findCommandOption("list")) {
         // get all of the options
         $options = Config::getOptions();
         // sort 'em alphabetically
         ksort($options);
         // find length of longest option
         $lengthLong = 0;
         foreach ($options as $optionName => $optionValue) {
             $lengthLong = strlen($optionName) > $lengthLong ? strlen($optionName) : $lengthLong;
         }
         // iterate over each option and spit it out
         foreach ($options as $optionName => $optionValue) {
             $optionValue = is_array($optionValue) ? implode(", ", $optionValue) : $optionValue;
             $optionValue = !$optionValue ? "false" : $optionValue;
             $spacer = Console::getSpacer($lengthLong, strlen($optionName));
             Console::writeLine("<info>" . $optionName . ":</info>" . $spacer . $optionValue);
         }
     } else {
         if (Console::findCommandOption("get")) {
             // figure out which optino was passed
             $searchOption = Console::findCommandOptionValue("get");
             $optionValue = Config::getOption($searchOption);
             // write it out
             if (!$optionValue) {
                 Console::writeError("the --get value you provided, <info>" . $searchOption . "</info>, does not exists in the config...");
             } else {
                 $optionValue = is_array($optionValue) ? implode(", ", $optionValue) : $optionValue;
                 $optionValue = !$optionValue ? "false" : $optionValue;
                 Console::writeInfo($searchOption . ": <ok>" . $optionValue . "</ok>");
             }
         } else {
             if (Console::findCommandOption("set")) {
                 // find the value that was passed
                 $updateOption = Console::findCommandOptionValue("set");
                 $updateOptionBits = explode("=", $updateOption);
                 if (count($updateOptionBits) == 1) {
                     Console::writeError("the --set value should look like <info>optionName=\"optionValue\"</info>. nothing was updated...");
                 }
                 // set the name and value that were passed
                 $updateName = $updateOptionBits[0];
                 $updateValue = $updateOptionBits[1][0] == "\"" || $updateOptionBits[1][0] == "'" ? substr($updateOptionBits[1], 1, strlen($updateOptionBits[1]) - 1) : $updateOptionBits[1];
                 // make sure the option being updated already exists
                 $currentValue = Config::getOption($updateName);
                 if (!$currentValue) {
                     Console::writeError("the --set option you provided, <info>" . $updateName . "</info>, does not exists in the config. nothing will be updated...");
                 } else {
                     Config::updateConfigOption($updateName, $updateValue);
                 }
             } else {
                 // no acceptable options were passed so write out the help
                 Console::writeHelpCommand($this->command);
             }
         }
     }
 }
 /**
  * Pulls together a bunch of functions from builder.lib.php in an order that makes sense
  * @param  {Boolean}       decide if CSS should be parsed and saved. performance hog.
  * @param  {Boolean}       decide if static files like CSS and JS should be moved
  */
 public function generate($options = array())
 {
     // double-checks options was properly set
     if (empty($options)) {
         Console::writeError("need to pass options to generate...");
     }
     // set the default vars
     $moveStatic = isset($options["moveStatic"]) ? $options["moveStatic"] : true;
     $noCacheBuster = isset($options["noCacheBuster"]) ? $options["noCacheBuster"] : false;
     $exportFiles = isset($options["exportFiles"]) ? $options["exportFiles"] : false;
     $exportClean = isset($options["exportClean"]) ? $options["exportClean"] : false;
     $watchMessage = isset($options["watchMessage"]) ? $options["watchMessage"] : false;
     $watchVerbose = isset($options["watchVerbose"]) ? $options["watchVerbose"] : false;
     $update = isset($options["update"]) ? $options["update"] : false;
     Config::setOption("update", $update);
     if ($noCacheBuster) {
         Config::updateOption("cacheBuster", 0);
     }
     FileChangeList::init(Config::getOption("publicDir") . DIRECTORY_SEPARATOR . "fileChangeList.csv");
     // gather up all of the data to be used in patterns
     Data::gather();
     // gather all of the various pattern info
     $options = array();
     $options["exportClean"] = $exportClean;
     $options["exportFiles"] = $exportFiles;
     PatternData::gather($options);
     // gather the annotations
     Annotations::gather();
     // clean the public directory to remove old files
     if (Config::getOption("cleanPublic") == "true" && $moveStatic) {
         FileUtil::cleanPublic();
     }
     // render out the index and style guide
     $this->generateIndex();
     $this->generateStyleguide();
     $this->generateViewAllPages();
     // render out the patterns and move them to public/patterns
     $options = array();
     $options["exportFiles"] = $exportFiles;
     $this->generatePatterns($options);
     // render the annotations as a js file
     $this->generateAnnotations();
     // move all of the files unless pattern only is set
     if ($moveStatic) {
         $this->moveStatic();
     }
     // update the change time so the auto-reload will fire (doesn't work for the index and style guide)
     Util::updateChangeTime();
     FileChangeList::write();
     if ($watchVerbose && $watchMessage) {
         Console::writeLine($watchMessage);
     } else {
         Console::writeLine("your site has been generated...");
         Timer::stop();
     }
 }
 /**
  * Make a directory
  * @param  {String}       directory to be made
  */
 public static function makeDir($dir)
 {
     $fs = new Filesystem();
     try {
         $fs->mkdir($dir);
     } catch (IOExceptionInterface $e) {
         Console::writeError("an error occurred while creating your directory at <path>" . $e->getPath() . "</path>...");
     }
     unset($fs);
 }
 /**
  * Returns the last error message when building a JSON file. Mimics json_last_error_msg() from PHP 5.5
  * @param  {String}       the file that generated the error
  */
 public static function lastErrorMsg($file, $message, $data)
 {
     Console::writeLine(PHP_EOL . "<error>The JSON file, " . $file . ", wasn't loaded. The error: " . $message . "</error>");
     if ($message == "Syntax error, malformed JSON") {
         Console::writeLine("");
         $parser = new JsonLint\JsonParser();
         $error = $parser->lint($data);
         Console::writeError($error->getMessage(), false, true);
     }
 }
 /**
  * Spawn the passed commands and those collected from plugins
  * @param  {Array}       a list of commands to spawn
  * @param  {Boolean}     if this should be run in quiet mode
  */
 public function spawn($commands = array(), $quiet = false)
 {
     // set-up a default
     $processes = array();
     // add the default processes sent to the spawner
     if (!empty($commands)) {
         foreach ($commands as $command) {
             $processes[] = $this->buildProcess($command);
         }
     }
     // add the processes sent to the spawner from plugins
     foreach ($this->pluginProcesses as $pluginProcess) {
         $processes[] = $this->buildProcess($pluginProcess);
     }
     // if there are processes to spawn do so
     if (!empty($processes)) {
         // start the processes
         foreach ($processes as $process) {
             $process["process"]->start();
         }
         // check on them and produce output
         while (true) {
             foreach ($processes as $process) {
                 try {
                     if ($process["process"]->isRunning()) {
                         $process["process"]->checkTimeout();
                         if (!$quiet && $process["output"]) {
                             print $process["process"]->getIncrementalOutput();
                             $cmd = $process["process"]->getCommandLine();
                             if (strpos($cmd, "router.php") != strlen($cmd) - 10) {
                                 print $process["process"]->getIncrementalErrorOutput();
                             }
                         }
                     }
                 } catch (ProcessTimedOutException $e) {
                     if ($e->isGeneralTimeout()) {
                         Console::writeError("pattern lab processes should never time out. yours did...");
                     } else {
                         if ($e->isIdleTimeout()) {
                             Console::writeError("pattern lab processes automatically time out if their is no command line output in 30 minutes...");
                         }
                     }
                 }
             }
             usleep(100000);
         }
     }
 }
 /**
  * Load all of the rules related to Pattern Engines. They're located in the plugin dir
  */
 public static function loadRules()
 {
     // default var
     $configDir = Config::getOption("configDir");
     // make sure the pattern engine data exists
     if (file_exists($configDir . "/patternengines.json")) {
         // get pattern engine list data
         $patternEngineList = json_decode(file_get_contents($configDir . "/patternengines.json"), true);
         // get the pattern engine info
         foreach ($patternEngineList["patternengines"] as $patternEngineName) {
             self::$rules[] = new $patternEngineName();
         }
     } else {
         Console::writeError("The pattern engines list isn't available in <path>" . $configDir . "</path>...");
     }
 }
 /**
  * Load all of the rules related to Pattern Engines. They're located in the plugin dir
  */
 public static function loadRules()
 {
     // default var
     $packagesDir = Config::getOption("packagesDir");
     // see if the package dir exists. if it doesn't it means composer hasn't been run
     if (!is_dir($packagesDir)) {
         Console::writeError("you haven't fully set-up Pattern Lab yet. please add a pattern engine...");
     }
     // make sure the pattern engine data exists
     if (file_exists($packagesDir . "/patternengines.json")) {
         // get pattern engine list data
         $patternEngineList = json_decode(file_get_contents($packagesDir . "/patternengines.json"), true);
         // get the pattern engine info
         foreach ($patternEngineList["patternengines"] as $patternEngineName) {
             self::$rules[] = new $patternEngineName();
         }
     } else {
         Console::writeError("The pattern engines list isn't available in <path>" . $packagesDir . "</path>...");
     }
 }
 /**
  * Set-up default vars
  */
 public static function init()
 {
     // make sure config vars exist
     if (!Config::getOption("patternExtension")) {
         Console::writeError("the pattern extension config option needs to be set...");
     }
     if (!Config::getOption("styleguideKit")) {
         Console::writeError("the styleguideKit config option needs to be set...");
     }
     // set-up config vars
     $patternExtension = Config::getOption("patternExtension");
     $metaDir = Config::getOption("metaDir");
     $styleguideKit = Config::getOption("styleguideKit");
     $styleguideKitPath = Config::getOption("styleguideKitPath");
     if (!$styleguideKitPath || !is_dir($styleguideKitPath)) {
         Console::writeError("your styleguide won't render because i can't find your styleguide files. are you sure they're at <path>" . Console::getHumanReadablePath($styleguideKitPath) . "</path>? you can fix this in <path>./config/config.yml</path> by editing styleguideKitPath...");
     }
     // load pattern-lab's resources
     $partialPath = $styleguideKitPath . DIRECTORY_SEPARATOR . "views" . DIRECTORY_SEPARATOR . "partials";
     $generalHeaderPath = $partialPath . DIRECTORY_SEPARATOR . "general-header." . $patternExtension;
     $generalFooterPath = $partialPath . DIRECTORY_SEPARATOR . "general-footer." . $patternExtension;
     self::$htmlHead = file_exists($generalHeaderPath) ? file_get_contents($generalHeaderPath) : "";
     self::$htmlFoot = file_exists($generalFooterPath) ? file_get_contents($generalFooterPath) : "";
     // gather the user-defined header and footer information
     $patternHeadPath = $metaDir . DIRECTORY_SEPARATOR . "_00-head." . $patternExtension;
     $patternFootPath = $metaDir . DIRECTORY_SEPARATOR . "_01-foot." . $patternExtension;
     self::$patternHead = file_exists($patternHeadPath) ? file_get_contents($patternHeadPath) : "";
     self::$patternFoot = file_exists($patternFootPath) ? file_get_contents($patternFootPath) : "";
     // add the filesystemLoader
     $patternEngineBasePath = PatternEngine::getInstance()->getBasePath();
     $filesystemLoaderClass = $patternEngineBasePath . "\\Loaders\\FilesystemLoader";
     $options = array();
     $options["templatePath"] = $styleguideKitPath . DIRECTORY_SEPARATOR . "views";
     $options["partialsPath"] = $options["templatePath"] . DIRECTORY_SEPARATOR . "partials";
     self::$filesystemLoader = new $filesystemLoaderClass($options);
     $stringLoaderClass = $patternEngineBasePath . "\\Loaders\\StringLoader";
     self::$stringLoader = new $stringLoaderClass();
     // i can't remember why i chose to implement the pattern loader directly in classes
     // i figure i had a good reason which is why it's not showing up here
 }
 public function run()
 {
     // find the value given to the command
     $package = Console::findCommandOptionValue("p|package");
     if ($package) {
         // if <prompt> was passed ask the user for the package name
         if ($package == "prompt") {
             $prompt = "what is the name of the package you want to fetch?";
             $options = "(ex. pattern-lab/plugin-kss)";
             $package = Console::promptInput($prompt, $options);
         }
         // make sure it looks like a valid package
         if (strpos($package, "/") === false) {
             Console::writeError("that wasn't a valid package name. it should look like <info>pattern-lab/plugin-kss</info>...");
         }
         // run composer via fetch
         $f = new Fetch();
         $f->fetchPackage($package);
     } else {
         Console::writeHelpCommand($this->command);
     }
 }
 public function run()
 {
     // load default vars
     $patternExtension = Config::getOption("patternExtension");
     $patternSourceDir = Config::getOption("patternSourceDir");
     // load the pattern data
     $store = PatternData::get();
     // iterate to get raw data loaded into the PatternData Store
     foreach ($store as $patternStoreKey => $patternStoreData) {
         if ($patternStoreData["category"] == "pattern" && !$patternStoreData["hidden"]) {
             // figure out the source path for the pattern to render
             $srcPath = isset($patternStoreData["pseudo"]) ? PatternData::getPatternOption($patternStoreData["original"], "pathName") : $patternStoreData["pathName"];
             // load the raw data so it can be modified/rendered
             $path = $patternSourceDir . "/" . $srcPath . "." . $patternExtension;
             if (file_exists($path)) {
                 PatternData::setPatternOption($patternStoreKey, "patternRaw", file_get_contents($path));
             } else {
                 Console::writeError($patternStoreData["partial"] . " wasn't found for loading. the given path: " . $path);
             }
         }
     }
 }
 /**
  * Stop the timer
  */
 public static function stop()
 {
     // make sure start time is set
     if (empty(self::$startTime)) {
         Console::writeError("the timer wasn't started...");
     }
     // get the current time
     $endTime = self::getTime();
     // get the data for the output
     $totalTime = $endTime - self::$startTime;
     $mem = round(memory_get_peak_usage(true) / 1024 / 1024, 2);
     // figure out what tag to show
     $timeTag = "info";
     if ($totalTime > 0.5) {
         $timeTag = "error";
     } else {
         if ($totalTime > 0.3) {
             $timeTag = "warning";
         }
     }
     // write out time/mem stats
     Console::writeLine("site generation took <" . $timeTag . ">" . $totalTime . "</" . $timeTag . "> seconds and used <info>" . $mem . "MB</info> of memory...");
 }
Beispiel #14
0
 /**
  * Break up the package path
  * @param  {String}    path of the GitHub repo
  *
  * @return {Array}     the parts of the package path
  */
 protected function getPackageInfo($package)
 {
     $org = "";
     $repo = "";
     $tag = "master";
     if (strpos($package, "#") !== false) {
         list($package, $tag) = explode("#", $package);
     }
     if (strpos($package, "/") !== false) {
         list($org, $repo) = explode("/", $package);
     } else {
         Console::writeError("please provide a real path to a package...");
     }
     return array($org, $repo, $tag);
 }
 /**
  * Write out the new config option value
  * @param  {String}       the name of the option to be changed
  * @param  {String}       the new value of the option to be changed
  */
 protected static function writeUpdateConfigOption($optionName, $optionValue)
 {
     // parse the YAML options
     try {
         $options = Yaml::parse(file_get_contents(self::$userConfigPath));
     } catch (ParseException $e) {
         Console::writeError("Config parse error in <path>" . self::$userConfigPath . "</path>: " . $e->getMessage());
     }
     if (isset($options[$optionName]) && is_array($options[$optionName])) {
         $optionValue = is_array($optionValue) ? $optionValue : array($optionValue);
         $options[$optionName] = array_merge($options[$optionName], $optionValue);
     } else {
         $options[$optionName] = $optionValue;
     }
     // dump the YAML
     $configOutput = Yaml::dump($options, 3);
     // write out the new config file
     file_put_contents(self::$userConfigPath, $configOutput);
 }
Beispiel #16
0
 /**
  * Write out the new config option value
  * @param  {String}       the name of the option to be changed
  * @param  {String}       the new value of the option to be changed
  */
 protected static function writeUpdateConfigOption($optionName, $optionValue)
 {
     // parse the YAML options
     try {
         $options = Yaml::parse(file_get_contents(self::$userConfigPath));
     } catch (ParseException $e) {
         Console::writeError("Config parse error in <path>" . self::$userConfigPath . "</path>: " . $e->getMessage());
     }
     // set this option for the current running of the app
     self::setOption($optionName, $optionValue);
     // modify the yaml file results
     $arrayFinder = new ArrayFinder($options);
     $arrayFinder->set($optionName, $optionValue);
     $options = $arrayFinder->get();
     // dump the YAML
     $configOutput = Yaml::dump($options, 3);
     // write out the new config file
     file_put_contents(self::$userConfigPath, $configOutput);
 }
 protected function starterKitSuggestions()
 {
     Console::writeLine("");
     $composerPath = Config::getOption("baseDir") . "/composer.json";
     if (file_exists($composerPath)) {
         $json = file_get_contents($composerPath);
         $data = json_decode($json, true);
         if ($jsonErrorMessage = JSON::hasError()) {
             JSON::lastErrorMsg(Console::getHumanReadablePath($oldStyleAnnotationsPath), $jsonErrorMessage, $data);
         }
         if (isset($data["extra"]) && isset($data["extra"]["patternlab"]) && isset($data["extra"]["patternlab"]["starterKitSuggestions"])) {
             $starterKitSuggestions = $data["extra"]["patternlab"]["starterKitSuggestions"];
             Console::writeInfo("suggested starterkits that work with this edition:", false, true);
             foreach ($starterKitSuggestions as $i => $suggestion) {
                 $num = $i + 1;
                 Console::writeLine($num . ": " . $suggestion, true);
             }
             // hack around installer util feature in Console::promptInput
             InstallerUtil::$isInteractive = true;
             // prompt for input on the suggestions
             Console::writeLine("");
             $prompt = "choose an option or hit return to cancel:";
             $options = "(ex. 1)";
             $input = Console::promptInput($prompt, $options, "1");
             $result = (int) $input - 1;
             if (isset($starterKitSuggestions[$result])) {
                 Console::writeLine("");
                 $f = new Fetch();
                 $result = $f->fetchStarterKit($starterKitSuggestions[$result]);
             }
         } else {
             Console::writeWarning("this edition has no starterkits to suggested...", false, true);
         }
     } else {
         Console::writeError("can't find composer.json to get suggestions...", false, true);
     }
 }
 /**
  * Watch the source/ directory for any changes to existing files. Will run forever if given the chance.
  * @param  {Boolean}       decide if the reload server should be turned on
  * @param  {Boolean}       decide if static files like CSS and JS should be moved
  */
 public function watch($options = array())
 {
     // double-checks options was properly set
     if (empty($options)) {
         Console::writeError("need to pass options to generate...");
     }
     // set default attributes
     $moveStatic = isset($options["moveStatic"]) ? $options["moveStatic"] : true;
     $noCacheBuster = isset($options["noCacheBuster"]) ? $options["noCacheBuster"] : false;
     // make sure a copy of the given options are saved for using when running generate
     $this->options = $options;
     // set-up the Dispatcher
     $dispatcherInstance = Dispatcher::getInstance();
     $dispatcherInstance->dispatch("watcher.start");
     if ($noCacheBuster) {
         Config::setOption("cacheBuster", 0);
     }
     $c = false;
     // track that one loop through the pattern file listing has completed
     $o = new \stdClass();
     // create an object to hold the properties
     $cp = new \stdClass();
     // create an object to hold a clone of $o
     $o->patterns = new \stdClass();
     Console::writeLine("watching your site for changes...");
     // default vars
     $publicDir = Config::getOption("publicDir");
     $sourceDir = Config::getOption("sourceDir");
     $patternSourceDir = Config::getOption("patternSourceDir");
     $ignoreExts = Config::getOption("ie");
     $ignoreDirs = Config::getOption("id");
     $patternExt = Config::getOption("patternExtension");
     // build the file extensions based on the rules
     $fileExtensions = array();
     $patternRules = PatternData::getRules();
     foreach ($patternRules as $patternRule) {
         $extensions = $patternRule->getProp("extProp");
         if (strpos($extensions, "&&") !== false) {
             $extensions = explode("&&", $extensions);
         } else {
             if (strpos($extensions, "||") !== false) {
                 $extensions = explode("||", $extensions);
             } else {
                 $extensions = array($extensions);
             }
         }
         foreach ($extensions as $extension) {
             if (!in_array($extension, $fileExtensions)) {
                 $fileExtensions[] = $extension;
             }
         }
     }
     // run forever
     while (true) {
         // clone the patterns so they can be checked in case something gets deleted
         $cp = clone $o->patterns;
         // iterate over the patterns & related data and regenerate the entire site if they've changed
         $patternObjects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($patternSourceDir), \RecursiveIteratorIterator::SELF_FIRST);
         // make sure dots are skipped
         $patternObjects->setFlags(\FilesystemIterator::SKIP_DOTS);
         foreach ($patternObjects as $name => $object) {
             // clean-up the file name and make sure it's not one of the pattern lab files or to be ignored
             $fileName = str_replace($patternSourceDir . DIRECTORY_SEPARATOR, "", $name);
             $fileNameClean = str_replace(DIRECTORY_SEPARATOR . "_", DIRECTORY_SEPARATOR, $fileName);
             if ($object->isFile() && in_array($object->getExtension(), $fileExtensions)) {
                 // make sure this isn't a hidden pattern
                 $patternParts = explode(DIRECTORY_SEPARATOR, $fileName);
                 $pattern = isset($patternParts[2]) ? $patternParts[2] : $patternParts[1];
                 // make sure the pattern still exists in source just in case it's been deleted during the iteration
                 if (file_exists($name)) {
                     $mt = $object->getMTime();
                     if (isset($o->patterns->{$fileName}) && $o->patterns->{$fileName} != $mt) {
                         $o->patterns->{$fileName} = $mt;
                         $this->updateSite($fileName, "changed");
                     } else {
                         if (!isset($o->patterns->{$fileName}) && $c) {
                             $o->patterns->{$fileName} = $mt;
                             $this->updateSite($fileName, "added");
                             if ($object->getExtension() == $patternExt) {
                                 $patternSrcPath = str_replace("." . $patternExt, "", $fileName);
                                 $patternDestPath = str_replace("/", "-", $patternSrcPath);
                                 $render = $pattern[0] != "_" ? true : false;
                                 $this->patternPaths[$patternParts[0]][$pattern] = array("patternSrcPath" => $patternSrcPath, "patternDestPath" => $patternDestPath, "render" => $render);
                             }
                         } else {
                             if (!isset($o->patterns->{$fileName})) {
                                 $o->patterns->{$fileName} = $mt;
                             }
                         }
                     }
                     if ($c && isset($o->patterns->{$fileName})) {
                         unset($cp->{$fileName});
                     }
                 } else {
                     // the file was removed during the iteration so remove references to the item
                     unset($o->patterns->{$fileName});
                     unset($cp->{$fileName});
                     unset($this->patternPaths[$patternParts[0]][$pattern]);
                     $this->updateSite($fileName, "removed");
                 }
             }
         }
         // make sure old entries are deleted
         // will throw "pattern not found" errors if an entire directory is removed at once but that shouldn't be a big deal
         if ($c) {
             foreach ($cp as $fileName => $mt) {
                 unset($o->patterns->{$fileName});
                 $patternParts = explode(DIRECTORY_SEPARATOR, $fileName);
                 $pattern = isset($patternParts[2]) ? $patternParts[2] : $patternParts[1];
                 unset($this->patternPaths[$patternParts[0]][$pattern]);
                 $this->updateSite($fileName, "removed");
             }
         }
         // iterate over annotations, data, meta and any other _ dirs
         $watchDirs = glob($sourceDir . DIRECTORY_SEPARATOR . "_*", GLOB_ONLYDIR);
         foreach ($watchDirs as $watchDir) {
             if ($watchDir != $patternSourceDir) {
                 // iterate over the data files and regenerate the entire site if they've changed
                 $objects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($watchDir), \RecursiveIteratorIterator::SELF_FIRST);
                 // make sure dots are skipped
                 $objects->setFlags(\FilesystemIterator::SKIP_DOTS);
                 foreach ($objects as $name => $object) {
                     $fileName = str_replace($sourceDir . DIRECTORY_SEPARATOR, "", $name);
                     $mt = $object->getMTime();
                     if (!isset($o->{$fileName})) {
                         $o->{$fileName} = $mt;
                         if ($c) {
                             $this->updateSite($fileName, "added");
                         }
                     } else {
                         if ($o->{$fileName} != $mt) {
                             $o->{$fileName} = $mt;
                             if ($c) {
                                 $this->updateSite($fileName, "changed");
                             }
                         }
                     }
                 }
             }
         }
         // iterate over all of the other files in the source directory and move them if their modified time has changed
         if ($moveStatic) {
             $objects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($sourceDir . DIRECTORY_SEPARATOR), \RecursiveIteratorIterator::SELF_FIRST);
             // make sure dots are skipped
             $objects->setFlags(\FilesystemIterator::SKIP_DOTS);
             foreach ($objects as $name => $object) {
                 // clean-up the file name and make sure it's not one of the pattern lab files or to be ignored
                 $fileName = str_replace($sourceDir . DIRECTORY_SEPARATOR, "", $name);
                 if ($fileName[0] != "_" && !in_array($object->getExtension(), $ignoreExts) && !in_array($object->getFilename(), $ignoreDirs)) {
                     // catch directories that have the ignored dir in their path
                     $ignoreDir = FileUtil::ignoreDir($fileName);
                     // check to see if it's a new directory
                     if (!$ignoreDir && $object->isDir() && !isset($o->{$fileName}) && !is_dir($publicDir . "/" . $fileName)) {
                         mkdir($publicDir . "/" . $fileName);
                         $o->{$fileName} = "dir created";
                         // placeholder
                         Console::writeLine($fileName . "/ directory was created...");
                     }
                     // check to see if it's a new file or a file that has changed
                     if (file_exists($name)) {
                         $mt = $object->getMTime();
                         if (!$ignoreDir && $object->isFile() && !isset($o->{$fileName}) && !file_exists($publicDir . "/" . $fileName)) {
                             $o->{$fileName} = $mt;
                             FileUtil::moveStaticFile($fileName, "added");
                             if ($object->getExtension() == "css") {
                                 $this->updateSite($fileName, "changed", 0);
                                 // make sure the site is updated for MQ reasons
                             }
                         } else {
                             if (!$ignoreDir && $object->isFile() && isset($o->{$fileName}) && $o->{$fileName} != $mt) {
                                 $o->{$fileName} = $mt;
                                 FileUtil::moveStaticFile($fileName, "changed");
                                 if ($object->getExtension() == "css") {
                                     $this->updateSite($fileName, "changed", 0);
                                     // make sure the site is updated for MQ reasons
                                 }
                             } else {
                                 if (!isset($o->fileName)) {
                                     $o->{$fileName} = $mt;
                                 }
                             }
                         }
                     } else {
                         unset($o->{$fileName});
                     }
                 }
             }
         }
         $c = true;
         // taking out the garbage. basically killing mustache after each run.
         if (gc_enabled()) {
             gc_collect_cycles();
         }
         // pause for .05 seconds to give the CPU a rest
         usleep(50000);
     }
 }
 /**
  * Set the given option to the given value
  */
 protected function setOption()
 {
     // find the value that was passed
     $updateOption = Console::findCommandOptionValue("set");
     $updateOptionBits = explode("=", $updateOption);
     if (count($updateOptionBits) == 1) {
         Console::writeError("the --set value should look like <info>optionName=\"optionValue\"</info>. nothing was updated...");
     }
     // set the name and value that were passed
     $updateName = $updateOptionBits[0];
     $updateValue = $updateOptionBits[1][0] == "\"" || $updateOptionBits[1][0] == "'" ? substr($updateOptionBits[1], 1, strlen($updateOptionBits[1]) - 1) : $updateOptionBits[1];
     // make sure the option being updated already exists
     $currentValue = Config::getOption($updateName);
     if (!$currentValue) {
         Console::writeError("the --set option you provided, <info>" . $updateName . "</info>, does not exists in the config. nothing will be updated...");
     } else {
         Config::updateConfigOption($updateName, $updateValue);
         Console::writeInfo("config option updated...");
     }
 }
Beispiel #20
0
 public function watchStarterKit()
 {
     // double-checks options was properly set
     $starterKit = Config::getOption("starterKit");
     if (!$starterKit) {
         Console::writeError("need to have a starterkit set in the config...");
     }
     // set-up the full starterkit path
     $starterKitPath = Config::getOption("packagesDir") . DIRECTORY_SEPARATOR . $starterKit . DIRECTORY_SEPARATOR . "dist";
     if (!is_dir($starterKitPath)) {
         Console::writeError("the starterkit doesn't seem to exist...");
     }
     // default vars
     $sourceDir = Config::getOption("sourceDir");
     $packagesDir = Config::getOption("packagesDir");
     $fs = new Filesystem();
     $c = false;
     // track that one loop through the pattern file listing has completed
     $o = new \stdClass();
     // create an object to hold the properties
     $cp = new \stdClass();
     // create an object to hold a clone of $o
     $o->patterns = new \stdClass();
     Console::writeLine("watching your starterkit for changes...");
     // run forever
     while (true) {
         // clone the patterns so they can be checked in case something gets deleted
         $cp = clone $o->patterns;
         $objects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($starterKitPath), \RecursiveIteratorIterator::SELF_FIRST);
         // make sure dots are skipped
         $objects->setFlags(\FilesystemIterator::SKIP_DOTS);
         foreach ($objects as $name => $object) {
             // clean-up the file name and make sure it's not one of the pattern lab files or to be ignored
             $fileName = str_replace($starterKitPath . DIRECTORY_SEPARATOR, "", $name);
             // check to see if it's a new directory
             if ($object->isDir() && !isset($o->{$fileName}) && !is_dir($starterKitPath . "/" . $fileName)) {
                 mkdir($sourceDir . "/" . $fileName);
                 $o->{$fileName} = "dir created";
                 // placeholder
                 Console::writeLine($fileName . "/ directory was created...");
             }
             // check to see if it's a new file or a file that has changed
             if (file_exists($name)) {
                 $mt = $object->getMTime();
                 if ($object->isFile() && !isset($o->{$fileName}) && !file_exists($sourceDir . DIRECTORY_SEPARATOR . $fileName)) {
                     $o->{$fileName} = $mt;
                     $fs->copy($starterKitPath . DIRECTORY_SEPARATOR . $fileName, $sourceDir . DIRECTORY_SEPARATOR . $fileName);
                     Console::writeInfo($fileName . " added...");
                 } else {
                     if ($object->isFile() && isset($o->{$fileName}) && $o->{$fileName} != $mt) {
                         $o->{$fileName} = $mt;
                         $fs->copy($starterKitPath . DIRECTORY_SEPARATOR . $fileName, $sourceDir . DIRECTORY_SEPARATOR . $fileName);
                         Console::writeInfo($fileName . " changed...");
                     } else {
                         if (!isset($o->fileName)) {
                             $o->{$fileName} = $mt;
                         }
                     }
                 }
             } else {
                 unset($o->{$fileName});
             }
         }
         $c = true;
         // taking out the garbage. basically killing mustache after each run.
         if (gc_enabled()) {
             gc_collect_cycles();
         }
         // pause for .05 seconds to give the CPU a rest
         usleep(50000);
     }
 }
 /**
  * Gather all of the information related to the patterns
  */
 public static function gather($options = array())
 {
     // set default vars
     $exportClean = isset($options["exportClean"]) ? $options["exportClean"] : false;
     $exportFiles = isset($options["exportClean"]) ? $options["exportFiles"] : false;
     $dispatcherInstance = Dispatcher::getInstance();
     // cleaning the var for use below, i know this is stupid
     $options = array();
     // dispatch that the data gather has started
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.gatherStart", $event);
     // load up the rules for parsing patterns and the directories
     self::loadRules($options);
     // dispatch that the rules are loaded
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.rulesLoaded", $event);
     // iterate over the patterns & related data and regenerate the entire site if they've changed
     // seems a little silly to use symfony finder here. not really giving me any power
     if (!is_dir(Config::getOption("patternSourceDir"))) {
         Console::writeError("having patterns is important. please make sure you've installed a starterkit and/or that " . Console::getHumanReadablePath(Config::getOption("patternSourceDir")) . " exists...");
     }
     $patternObjects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(Config::getOption("patternSourceDir")), \RecursiveIteratorIterator::SELF_FIRST);
     $patternObjects->setFlags(\FilesystemIterator::SKIP_DOTS);
     // sort the returned objects
     $patternObjects = iterator_to_array($patternObjects);
     ksort($patternObjects);
     $patternSourceDir = Config::getOption("patternSourceDir");
     foreach ($patternObjects as $name => $object) {
         $ext = $object->getExtension();
         $isDir = $object->isDir();
         $isFile = $object->isFile();
         $path = str_replace($patternSourceDir . DIRECTORY_SEPARATOR, "", $object->getPath());
         $pathName = str_replace($patternSourceDir . DIRECTORY_SEPARATOR, "", $object->getPathname());
         $name = $object->getFilename();
         $depth = substr_count($pathName, DIRECTORY_SEPARATOR);
         // iterate over the rules and see if the current file matches one, if so run the rule
         foreach (self::$rules as $rule) {
             if ($rule->test($depth, $ext, $isDir, $isFile, $name)) {
                 $rule->run($depth, $ext, $path, $pathName, $name);
             }
         }
     }
     // dispatch that the data is loaded
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.dataLoaded", $event);
     // make sure all of the appropriate pattern data is pumped into $this->d for rendering patterns
     $dataLinkExporter = new DataLinkExporter();
     $dataLinkExporter->run();
     // make sure all of the appropriate pattern data is pumped into $this->d for rendering patterns
     $dataMergeExporter = new DataMergeExporter();
     $dataMergeExporter->run();
     // dispatch that the raw pattern helper is about to start
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.rawPatternHelperStart", $event);
     // add the lineage info to PatternData::$store
     $rawPatternHelper = new RawPatternHelper();
     $rawPatternHelper->run();
     // dispatch that the raw pattern helper is ended
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.rawPatternHelperEnd", $event);
     // dispatch that the lineage helper is about to start
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.lineageHelperStart", $event);
     // add the lineage info to PatternData::$store
     $lineageHelper = new LineageHelper();
     $lineageHelper->run();
     // dispatch that the lineage helper is ended
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.lineageHelperEnd", $event);
     // dispatch that the pattern state helper is about to start
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.patternStateHelperStart", $event);
     // using the lineage info update the pattern states on PatternData::$store
     $patternStateHelper = new PatternStateHelper();
     $patternStateHelper->run();
     // dispatch that the pattern state helper is ended
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.patternStateHelperEnd", $event);
     // set-up code pattern paths
     $ppdExporter = new PatternPathSrcExporter();
     $patternPathSrc = $ppdExporter->run();
     $options = array();
     $options["patternPaths"] = $patternPathSrc;
     // dispatch that the code helper is about to start
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.codeHelperStart", $event);
     // render out all of the patterns and store the generated info in PatternData::$store
     $options["exportFiles"] = $exportFiles;
     $options["exportClean"] = $exportClean;
     $patternCodeHelper = new PatternCodeHelper($options);
     $patternCodeHelper->run();
     // dispatch that the pattern code helper is ended
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.patternCodeHelperEnd", $event);
     // dispatch that the gather has ended
     $event = new PatternDataEvent($options);
     $dispatcherInstance->dispatch("patternData.gatherEnd", $event);
 }
 /**
  * Generates the data that powers the index page
  */
 protected function generateIndex()
 {
     // bomb if missing index.html
     if (!file_exists(Config::getOption("publicDir") . "/index.html")) {
         $index = Console::getHumanReadablePath(Config::getOption("publicDir")) . DIRECTORY_SEPARATOR . "index.html";
         Console::writeError("<path>" . $index . "</path> is missing. grab a copy from your StyleguideKit...");
     }
     // set-up the dispatcher
     $dispatcherInstance = Dispatcher::getInstance();
     // note the start of the operation
     $dispatcherInstance->dispatch("builder.generateIndexStart");
     // default var
     $dataDir = Config::getOption("publicDir") . "/styleguide/data";
     // double-check that the data directory exists
     if (!is_dir($dataDir)) {
         FileUtil::makeDir($dataDir);
     }
     $output = "";
     // load and write out the config options
     $config = array();
     $exposedOptions = Config::getOption("exposedOptions");
     foreach ($exposedOptions as $exposedOption) {
         $config[$exposedOption] = Config::getOption($exposedOption);
     }
     $output .= "var config = " . json_encode($config) . ";\n";
     // load the ish Controls
     $ishControls = array();
     $controlsToHide = array();
     $ishControlsHide = Config::getOption("ishControlsHide");
     if ($ishControlsHide) {
         foreach ($ishControlsHide as $controlToHide) {
             $controlsToHide[$controlToHide] = "true";
         }
     }
     $ishControls["ishControlsHide"] = $controlsToHide;
     $output .= "var ishControls = " . json_encode($ishControls) . ";\n";
     // load and write out the items for the navigation
     $niExporter = new NavItemsExporter();
     $navItems = $niExporter->run();
     $output .= "var navItems = " . json_encode($navItems) . ";\n";
     // load and write out the items for the pattern paths
     $patternPaths = array();
     $ppdExporter = new PatternPathDestsExporter();
     $patternPaths = $ppdExporter->run();
     $output .= "var patternPaths = " . json_encode($patternPaths) . ";\n";
     // load and write out the items for the view all paths
     $viewAllPaths = array();
     $vapExporter = new ViewAllPathsExporter();
     $viewAllPaths = $vapExporter->run($navItems);
     $output .= "var viewAllPaths = " . json_encode($viewAllPaths) . ";\n";
     // gather plugin package information
     $packagesInfo = array();
     $componentDir = Config::getOption("componentDir");
     if (!is_dir($componentDir)) {
         mkdir($componentDir);
     }
     $componentPackagesDir = $componentDir . "/packages";
     if (!is_dir($componentDir . "/packages")) {
         mkdir($componentDir . "/packages");
     }
     $finder = new Finder();
     $finder->files()->name("*.json")->in($componentPackagesDir);
     $finder->sortByName();
     foreach ($finder as $file) {
         $filename = $file->getFilename();
         if ($filename[0] != "_") {
             $javascriptPaths = array();
             $packageInfo = json_decode(file_get_contents($file->getPathname()), true);
             foreach ($packageInfo["templates"] as $templateKey => $templatePath) {
                 $templatePathFull = $componentDir . "/" . $packageInfo["name"] . "/" . $templatePath;
                 $packageInfo["templates"][$templateKey] = file_exists($templatePathFull) ? file_get_contents($templatePathFull) : "";
             }
             foreach ($packageInfo["javascripts"] as $key => $javascriptPath) {
                 $javascriptPaths[] = "patternlab-components/" . $packageInfo["name"] . "/" . $javascriptPath;
             }
             $packageInfo["javascripts"] = $javascriptPaths;
             $packagesInfo[] = $packageInfo;
         }
     }
     $output .= "var plugins = " . json_encode($packagesInfo) . ";";
     // write out the data
     file_put_contents($dataDir . "/patternlab-data.js", $output);
     // note the end of the operation
     $dispatcherInstance->dispatch("builder.generateIndexEnd");
 }
 /**
  * Prompt the user for some input
  * @param  {String}        the text for the prompt
  * @param  {String}        the text for the options
  * @param  {Boolean}       if we should lowercase the input before sending it back
  * @param  {String}        the tag that should be used when drawing the content
  *
  * @return {String}        trimmed input given by the user
  */
 public static function promptInput($prompt = "", $options = "", $lowercase = true, $tag = "info")
 {
     // check prompt
     if (empty($prompt)) {
         Console::writeError("an input prompt requires prompt text...");
     }
     // if there are suggested options add them
     if (!empty($options)) {
         $prompt .= " <options>" . $options . "</options> >";
     }
     // make sure no end-of-line is added
     $prompt .= " <nophpeol>";
     // open the terminal and wait for feedback
     $stdin = fopen("php://stdin", "r");
     Console::writeTag($tag, $prompt);
     $input = trim(fgets($stdin));
     fclose($stdin);
     // check to see if it should be lowercased before sending back
     return $lowercase ? strtolower($input) : $input;
 }