Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ancestor and Inherited functions for Page & Pages #1362

Merged
merged 8 commits into from
Apr 10, 2017
68 changes: 68 additions & 0 deletions system/src/Grav/Common/Page/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -2282,6 +2282,74 @@ public function root()
}
}

/**
* Helper method to return an ancestor page.
*
* @param string $url The url of the page
* @param bool $lookup Name of the parent folder
*
* @return \Grav\Common\Page\Page page you were looking for if it exists
*/
public function ancestor($lookup = null)
{
/** @var Pages $pages */
$pages = Grav::instance()['pages'];

return $pages->ancestor($this->route, $lookup);
}

/**
* Helper method to return an ancestor page to inherit from. The current
* page object is returned.
*
* @param string $field Name of the parent folder
*
* @return Page
*/
public function inherited($field)
{
list($inherited, $currentParams) = $this->getInheritedParams($field);

$this->modifyHeader($field, $currentParams);

return $inherited;
}
/**
* Helper method to return an ancestor field only to inherit from. The
* first occurrence of an ancestor field will be returned if at all.
*
* @param string $field Name of the parent folder
*
* @return array
*/
public function inheritedField($field)
{
list($inherited, $currentParams) = $this->getInheritedParams($field);

return $currentParams;
}

/**
* Method that contains shared logic for inherited() and inheritedField()
*
* @param string $field Name of the parent folder
*
* @return array
*/
protected function getInheritedParams($field)
{
$pages = Grav::instance()['pages'];

/** @var Pages $pages */
$inherited = $pages->inherited($this->route, $field);
$inheritedParams = (array) $inherited->value('header.' . $field);
$currentParams = (array) $this->value('header.' . $field);
if($inheritedParams && is_array($inheritedParams)) {
$currentParams = array_replace_recursive($inheritedParams, $currentParams);
}
return [$inherited, $currentParams];
}

/**
* Helper method to return a page.
*
Expand Down
87 changes: 74 additions & 13 deletions system/src/Grav/Common/Page/Pages.php
Original file line number Diff line number Diff line change
Expand Up @@ -291,37 +291,82 @@ public function children($path)
return new Collection($children, [], $this);
}

/**
* Get a page ancestor.
*
* @param string $route The relative URL of the page
* @param string $path The relative path of the ancestor folder
*
* @return Page|null
*/
public function ancestor($route, $path = null)
{
if (!is_null($path)) {

$page = $this->getPage($route);

if ($page->path() == $path) {
return $page;
} elseif (!$page->parent()->root()) {
return $this->ancestor($page->parent()->route(), $path);
}
}

return null;
}

/**
* Get a page ancestor trait.
*
* @param string $route The relative route of the page
* @param string $field The field name of the ancestor to query for
*
* @return Page|null
*/
public function inherited($route, $field = null)
{
if (!is_null($field)) {

$page = $this->getPage($route);

$ancestorField = $page->parent()->value('header.' . $field);

if ($ancestorField != null) {
return $page->parent();
} elseif (!$page->parent()->root()) {
return $this->inherited($page->parent()->route(), $field);
}
}

return null;
}

/**
* alias method to return find a page.
*
* @param string $url The relative URL of the page
* @param string $route The relative URL of the page
* @param bool $all
*
* @return Page|null
*/
public function find($url, $all = false)
public function find($route, $all = false)
{
return $this->dispatch($url, $all, false);
return $this->dispatch($route, $all, false);
}

/**
* Dispatch URI to a page.
*
* @param string $url The relative URL of the page
* @param string $route The relative URL of the page
* @param bool $all
*
* @param bool $redirect
* @return Page|null
* @throws \Exception
*/
public function dispatch($url, $all = false, $redirect = true)
public function dispatch($route, $all = false, $redirect = true)
{
// Fetch page if there's a defined route to it.
$page = isset($this->routes[$url]) ? $this->get($this->routes[$url]) : null;
// Try without trailing slash
if (!$page && Utils::endsWith($url, '/')) {
$page = isset($this->routes[rtrim($url, '/')]) ? $this->get($this->routes[rtrim($url, '/')]) : null;
}
$page = $this->getPage($route);

// Are we in the admin? this is important!
$not_admin = !isset($this->grav['admin']);
Expand All @@ -340,13 +385,13 @@ public function dispatch($url, $all = false, $redirect = true)
$config = $this->grav['config'];

// See if route matches one in the site configuration
$route = $config->get("site.routes.{$url}");
$route = $config->get("site.routes.{$route}");
if ($route) {
$page = $this->dispatch($route, $all);
} else {
// Try Regex style redirects
$uri = $this->grav['uri'];
$source_url = $url;
$source_url = $route;
$extension = $uri->extension();
if (isset($extension) && !Utils::endsWith($uri->url(), $extension)) {
$source_url.= '.' . $extension;
Expand Down Expand Up @@ -389,6 +434,22 @@ public function dispatch($url, $all = false, $redirect = true)
return $page;
}

/**
* Retrieve page instance based on the route
*
* @return Page
*/
protected function getPage($route) {
// Fetch page if there's a defined route to it.
$page = isset($this->routes[$route]) ? $this->get($this->routes[$route]) : null;
// Try without trailing slash
if (!$page && Utils::endsWith($route, '/')) {
$page = isset($this->routes[rtrim($route, '/')]) ? $this->get($this->routes[rtrim($route, '/')]) : null;
}

return $page;
}

/**
* Get root page.
*
Expand Down