From 2288e2a687bc2a1c62cf798e1f712333cd85cc54 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 20 Jan 2015 15:54:14 +0100 Subject: [PATCH] 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 --- library/Icinga/Web/Wizard.php | 125 ++++++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 6 deletions(-) diff --git a/library/Icinga/Web/Wizard.php b/library/Icinga/Web/Wizard.php index 2cc4abe5a..811374259 100644 --- a/library/Icinga/Web/Wizard.php +++ b/library/Icinga/Web/Wizard.php @@ -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)); }