base = $base; $this->project = $project; $this->cacheFactory = $cacheFactory; } /** * @param bool $includeTests Include tests in the manifest * @param bool $forceRegen Force the manifest to be regenerated. */ public function init($includeTests = false, $forceRegen = false) { // build cache from factory if ($this->cacheFactory) { $this->cache = $this->cacheFactory->create( CacheInterface::class . '.thememanifest', [ 'namespace' => 'thememanifest' . ($includeTests ? '_tests' : '') ] ); } $this->cacheKey = $this->getCacheKey($includeTests); if (!$forceRegen && $this->cache && ($data = $this->cache->get($this->cacheKey))) { $this->themes = $data; } else { $this->regenerate($includeTests); } } /** * @return string */ public function getBase() { return $this->base; } /** * Generate a unique cache key to avoid manifest cache collisions. * We compartmentalise based on the base path, the given project, and whether * or not we intend to include tests. * * @param bool $includeTests * @return string */ public function getCacheKey($includeTests = false) { return sha1(sprintf( "manifest-%s-%s-%u", $this->base, $this->project, $includeTests )); } /** * @return \string[] */ public function getThemes() { return $this->themes; } /** * Regenerates the manifest by scanning the base path. * * @param bool $includeTests */ public function regenerate($includeTests = false) { $finder = new ManifestFileFinder(); $finder->setOptions(array( 'include_themes' => false, 'ignore_dirs' => array('node_modules', THEMES_DIR), 'ignore_tests' => !$includeTests, 'dir_callback' => array($this, 'handleDirectory') )); $this->themes = []; $modules = ModuleLoader::inst()->getManifest()->getModules(); foreach ($modules as $module) { $finder->find($module->getPath()); } if ($this->cache) { $this->cache->set($this->cacheKey, $this->themes); } } /** * Add a directory to the manifest * * @param string $basename * @param string $pathname * @param int $depth */ public function handleDirectory($basename, $pathname, $depth) { if ($basename !== self::TEMPLATES_DIR) { return; } $dir = trim(substr(dirname($pathname), strlen($this->base)), '/\\'); $this->themes[] = "/" . $dir; } /** * Sets the project * * @param string $project * @return $this */ public function setProject($project) { $this->project = $project; return $this; } }