示例#1
0
 /**
  * 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);
     }
 }