base = $base; $this->tests = $includeTests; $this->project = $project; $cacheClass = defined('SS_MANIFESTCACHE') ? SS_MANIFESTCACHE : 'SilverStripe\\Core\\Manifest\\ManifestCache_File'; $this->cache = new $cacheClass('thememanifest'.($includeTests ? '_tests' : '')); $this->cacheKey = $this->getCacheKey(); if ($forceRegen) { $this->regenerate(); } } /** * @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. * @return string */ public function getCacheKey() { return sha1(sprintf( "manifest-%s-%s-%u", $this->base, $this->project, $this->tests )); } public function getThemes() { if ($this->themes === null) { $this->init(); } return $this->themes; } /** * Regenerates the manifest by scanning the base path. * * @param bool $cache */ public function regenerate($cache = true) { $finder = new ManifestFileFinder(); $finder->setOptions(array( 'include_themes' => false, 'ignore_dirs' => array('node_modules', THEMES_DIR), 'ignore_tests' => !$this->tests, 'dir_callback' => array($this, 'handleDirectory') )); $this->themes = []; $finder->find($this->base); if ($cache) { $this->cache->save($this->themes, $this->cacheKey); } } /** * 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; } // We only want part of the full path, so split into directories $parts = explode('/', $pathname); // Take the end (the part relative to base), except the very last directory $themeParts = array_slice($parts, -$depth, $depth-1); // Then join again $path = '/'.implode('/', $themeParts); // If this is in the project, add to beginning of list. Else add to end. if ($themeParts[0] == $this->project) { array_unshift($this->themes, $path); } else { array_push($this->themes, $path); } } /** * Initialise the manifest */ protected function init() { if ($data = $this->cache->load($this->cacheKey)) { $this->themes = $data; } else { $this->regenerate(); } } }