theme = $theme; } /** * Returns a list of static pages in the specified theme. * This method is used internally by the system. * @param boolean $skipCache Indicates if objects should be reloaded from the disk bypassing the cache. * @return array Returns an array of static pages. */ public function listPages($skipCache = false) { return Page::listInTheme($this->theme, $skipCache); } /** * Returns a list of top-level pages with subpages. * The method uses the theme's meta/static-pages.yaml file to build the hierarchy. The pages are returned * in the order defined in the YAML file. The result of the method is used for building the back-end UI * and for generating the menus. * @param boolean $skipCache Indicates if objects should be reloaded from the disk bypassing the cache. * @return array Returns a nested array of objects: object('page': $pageObj, 'subpages'=>[...]) */ public function getPageTree($skipCache = false) { $pages = $this->listPages($skipCache); $config = $this->getPagesConfig(); // Make the $pages collection an associative array for performance $pagesArray = $pages->keyBy(function ($page) { return $page->getBaseFileName(); })->all(); $iterator = function($configPages) use (&$iterator, $pagesArray) { $result = []; foreach ($configPages as $fileName => $subpages) { if (isset($pagesArray[$fileName])) { $result[] = (object) [ 'page' => $pagesArray[$fileName], 'subpages' => $iterator($subpages), ]; } } return $result; }; return $iterator($config['static-pages']); } /** * Returns the parent name of the specified page. * @param \Cms\Classes\Page $page Specifies a page object. * @param string Returns the parent page name. */ public function getPageParent($page) { $pagesConfig = $this->getPagesConfig(); $requestedFileName = $page->getBaseFileName(); $parent = null; $iterator = function($configPages) use (&$iterator, &$parent, $requestedFileName) { foreach ($configPages as $fileName => $subpages) { if ($fileName == $requestedFileName) { return true; } if ($iterator($subpages) == true && is_null($parent)) { $parent = $fileName; return true; } } }; $iterator($pagesConfig['static-pages']); return $parent; } /** * Returns a part of the page hierarchy starting from the specified page. * @param \Cms\Classes\Page $page Specifies a page object. * @param array Returns a nested array of page names. */ public function getPageSubTree($page) { $pagesConfig = $this->getPagesConfig(); $requestedFileName = $page->getBaseFileName(); $subTree = []; $iterator = function($configPages) use (&$iterator, &$subTree, $requestedFileName) { if (is_array($configPages)) { foreach ($configPages as $fileName => $subpages) { if ($fileName == $requestedFileName) { $subTree = $subpages; return true; } if ($iterator($subpages) === true) { return true; } } } }; $iterator($pagesConfig['static-pages']); return $subTree; } /** * Appends page to the page hierarchy. * The page can be added to the end of the hierarchy or as a subpage to any existing page. */ public function appendPage($page) { $parent = $page->parentFileName; $originalData = $this->getPagesConfig(); $structure = $originalData['static-pages']; if (!strlen($parent)) { $structure[$page->getBaseFileName()] = []; } else { $iterator = function(&$configPages) use (&$iterator, $parent, $page) { foreach ($configPages as $fileName => &$subpages) { if ($fileName == $parent) { $subpages[$page->getBaseFileName()] = []; return true; } if ($iterator($subpages) == true) return true; } }; $iterator($structure); } $this->updateStructure($structure); } /** * Removes a part of the page hierarchy starting from the specified page. * @param \Cms\Classes\Page $page Specifies a page object. */ public function removeSubtree($page) { $pagesConfig = $this->getPagesConfig(); $requestedFileName = $page->getBaseFileName(); $tree = []; $iterator = function($configPages) use (&$iterator, &$pages, $requestedFileName) { $result = []; foreach ($configPages as $fileName => $subpages) { if ($requestedFileName != $fileName) { $result[$fileName] = $iterator($subpages); } } return $result; }; $updatedStructure = $iterator($pagesConfig['static-pages']); $this->updateStructure($updatedStructure); } /** * Returns the parsed meta/static-pages.yaml file contents. * @return mixed */ protected function getPagesConfig() { if (self::$configCache !== false) { return self::$configCache; } $config = Meta::loadCached($this->theme, 'static-pages.yaml'); if (!$config) { $config = new Meta(); $config->fileName = 'static-pages.yaml'; $config['static-pages'] = []; $config->save(); } if (!isset($config->attributes['static-pages'])) { $config['static-pages'] = []; } return self::$configCache = $config; } /** * Updates the page hierarchy structure in the theme's meta/static-pages.yaml file. * @param array $structure A nested associative array representing the page structure */ public function updateStructure($structure) { $config = $this->getPagesConfig(); $config['static-pages'] = $structure; $config->save(); } }