ORIENT/plugins/rainlab/pages/classes/PageList.php

237 lines
7.0 KiB
PHP

<?php namespace RainLab\Pages\Classes;
use Cms\Classes\Meta;
use RainLab\Pages\Classes\Page;
/**
* The page list class reads and manages the static page hierarchy.
*
* @package rainlab\pages
* @author Alexey Bobkov, Samuel Georges
*/
class PageList
{
protected $theme;
protected static $configCache = false;
/**
* Creates the page list object.
* @param \Cms\Classes\Theme $theme Specifies a parent theme.
*/
public function __construct($theme)
{
$this->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();
}
}