Add support for nested wizards

The amount of vertical dimensions is not limited as well as the location a
nested wizard can occur in the main wizard's order. In case a custom
implementation is used as nested wizard, all core functionalities are
still being utilized.

refs #8191
This commit is contained in:
Johannes Meyer 2015-01-20 15:54:14 +01:00
parent 9cecc4d690
commit 2288e2a687
1 changed files with 119 additions and 6 deletions

View File

@ -39,6 +39,13 @@ class Wizard
*/
const BTN_PREV = 'btn_prev';
/**
* This wizard's parent
*
* @var Wizard
*/
protected $parent;
/**
* The name of the wizard's current page
*
@ -71,19 +78,55 @@ class Wizard
}
/**
* Return this wizard's parent or null in case it has none
*
* @return Wizard|null
*/
public function getParent()
{
return $this->parent;
}
/**
* Set this wizard's parent
*
* @param Wizard $wizard The parent wizard
*
* @return self
*/
public function setParent(Wizard $wizard)
{
$this->parent = $wizard;
return $this;
}
/**
* Return the pages being part of this wizard
*
* In case this is a nested wizard a flattened array of all contained pages is returned.
*
* @return array
*/
public function getPages()
{
return $this->pages;
$pages = array();
foreach ($this->pages as $page) {
if ($page instanceof self) {
$pages = array_merge($pages, $page->getPages());
} else {
$pages[] = $page;
}
}
return $pages;
}
/**
* Return the page with the given name
*
* Note that it's also possible to retrieve a nested wizard's page by using this method.
*
* @param string $name The name of the page to return
*
* @return null|Form The page or null in case there is no page with the given name
@ -98,22 +141,31 @@ class Wizard
}
/**
* Add a new page to this wizard
* Add a new page or wizard to this wizard
*
* @param Form $page The page to add to the wizard
* @param Form|Wizard $page The page or wizard to add to the wizard
*
* @return self
*/
public function addPage(Form $page)
public function addPage($page)
{
if (! $page instanceof Form && ! $page instanceof self) {
throw InvalidArgumentException(
'The $page argument must be an instance of Icinga\Web\Form '
. 'or Icinga\Web\Wizard but is of type: ' . get_class($page)
);
} elseif ($page instanceof self) {
$page->setParent($this);
}
$this->pages[] = $page;
return $this;
}
/**
* Add multiple pages to this wizard
* Add multiple pages or wizards to this wizard
*
* @param array $pages The pages to add to the wizard
* @param array $pages The pages or wizards to add to the wizard
*
* @return self
*/
@ -148,6 +200,10 @@ class Wizard
*/
public function getCurrentPage()
{
if ($this->parent) {
return $this->parent->getCurrentPage();
}
if ($this->currentPage === null) {
$this->assertHasPages();
$pages = $this->getPages();
@ -202,6 +258,10 @@ class Wizard
{
$page = $this->getCurrentPage();
if (($wizard = $this->findWizard($page)) !== null) {
return $wizard->handleRequest($request);
}
if ($request === null) {
$request = $page->getRequest();
}
@ -238,6 +298,39 @@ class Wizard
return $request;
}
/**
* Return the wizard for the given page or null if its not part of a wizard
*
* @param Form $page The page to return its wizard for
*
* @return Wizard|null
*/
protected function findWizard(Form $page)
{
foreach ($this->getWizards() as $wizard) {
if ($wizard->getPage($page->getName()) === $page) {
return $wizard;
}
}
}
/**
* Return this wizard's child wizards
*
* @return array
*/
protected function getWizards()
{
$wizards = array();
foreach ($this->pages as $pageOrWizard) {
if ($pageOrWizard instanceof self) {
$wizards[] = $pageOrWizard;
}
}
return $wizards;
}
/**
* Return the request data based on given form's request method
*
@ -264,6 +357,10 @@ class Wizard
*/
protected function getRequestedPage(array $requestData)
{
if ($this->parent) {
return $this->parent->getRequestedPage($requestData);
}
if (isset($requestData[static::BTN_NEXT])) {
return $requestData[static::BTN_NEXT];
} elseif (isset($requestData[static::BTN_PREV])) {
@ -280,6 +377,10 @@ class Wizard
*/
protected function getDirection(Request $request = null)
{
if ($this->parent) {
return $this->parent->getDirection($request);
}
$currentPage = $this->getCurrentPage();
if ($request === null) {
@ -312,6 +413,10 @@ class Wizard
*/
protected function getNewPage($requestedPage, Form $originPage)
{
if ($this->parent) {
return $this->parent->getNewPage($requestedPage, $originPage);
}
if (($page = $this->getPage($requestedPage)) !== null) {
$permitted = true;
@ -344,6 +449,10 @@ class Wizard
*/
protected function isLastPage(Form $page)
{
if ($this->parent) {
return $this->parent->isLastPage($page);
}
$pages = $this->getPages();
return $page->getName() === end($pages)->getName();
}
@ -421,6 +530,10 @@ class Wizard
*/
public function getSession()
{
if ($this->parent) {
return $this->parent->getSession();
}
return Session::getSession()->getNamespace(get_class($this));
}