Extensible configuration system

Add configuration tab builder parts to register
free configuration tab items

refs #4300
This commit is contained in:
Marius Hein 2013-06-27 16:06:38 +02:00
parent b403721c11
commit 1ede8df2af
10 changed files with 474 additions and 19 deletions

View File

@ -4,35 +4,35 @@
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use \Icinga\Web\ActionController;
use Icinga\Application\Benchmark;
use Icinga\Authentication\Manager;
use Icinga\Web\ActionController;
use Icinga\Web\Hook\Configuration\ConfigurationTab;
use Icinga\Web\Hook\Configuration\ConfigurationTabBuilder;
/**
* Class ConfigurationController
*/
class ConfigurationController extends ActionController
{
public function init()
{
parent::init();
}
/**
* Index action
*/
public function indexAction()
{
$this->view->tabs = $this->createTabs();
}
/**
* @return \Icinga\Web\Widget
*/
protected function createTabs()
{
$tabs = $this->widget('tabs')->add(
'configuration',
array(
'title' => $this->translate('Overview'),
'url' => 'configuration/index',
)
$tabBuilder = new ConfigurationTabBuilder(
$this->widget('tabs')
);
return $tabs;
$tabBuilder->build();
$this->view->tabs = $tabBuilder->getTabs();
}
}

View File

@ -5,9 +5,9 @@
# namespace Icinga\Application\Controllers;
use Icinga\Web\ActionController;
use Icinga\Application\Icinga;
use Icinga\Web\Hook\Configuration\ConfigurationTabBuilder;
class ModulesController extends ActionController
{
@ -20,6 +20,14 @@ class ModulesController extends ActionController
public function indexAction()
{
$tabBuilder = new ConfigurationTabBuilder(
$this->widget('tabs')
);
$tabBuilder->build();
$this->view->tabs = $tabBuilder->getTabs();
$this->view->modules = $this->manager->select()
->from('modules')
->order('name');

View File

@ -1,5 +1,5 @@
<?= $this->tabs; ?>
<h2>Configuration</h2>
<h3>Configuration</h3>
<p>
This is the configuration over page. Modules can register their handler to

View File

@ -3,6 +3,7 @@ $this->modules->limit(10);
$modules = $this->modules->paginate();
?>
<?= $this->tabs; ?>
<h3>Installed Modules</h3>
<?= $this->paginationControl($modules, null, null, array(
'preserve' => $this->preserve

View File

@ -0,0 +1,140 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Hook\Configuration;
use Icinga\Exception\ProgrammingError;
/**
* Class ConfigurationTab
*
* Hook to represent configuration tabs
*
* @package Icinga\Web\Hook\Configuration
*/
class ConfigurationTab implements ConfigurationTabInterface
{
/**
* Module name
* @var string
*/
private $moduleName;
/**
* Url segment to invoke controller
* @var string
*/
private $url;
/**
* Title of the tab
* @var string
*/
private $title;
function __construct($name = null, $url = null, $title = null)
{
if ($name !== null) {
$this->setModuleName($name);
if ($title === null) {
$this->setTitle($name);
}
}
if ($url !== null) {
$this->setUrl($url);
}
if ($title !== null) {
$this->setTitle($title);
}
}
/**
* Setter for title
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Getter for title
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Setter for url
* @param string $url
*/
public function setUrl($url)
{
$this->url = $url;
}
/**
* Getter for url
* @return string
*/
public function getUrl()
{
return $this->url;
}
/**
* Setter for module name
* @param string $moduleName
*/
public function setModuleName($moduleName)
{
$this->moduleName = $moduleName;
}
private function assertConfiguration()
{
if (!$this->moduleName) {
throw new ProgrammingError('moduleName is missing');
}
if (!$this->getUrl()) {
throw new ProgrammingError('url is missing');
}
if (!$this->getTitle()) {
throw new ProgrammingError('title is missing');
}
}
/**
* Returns a tab configuration to build configuration links
* @return array
*/
public function getTab()
{
$this->assertConfiguration();
return array(
'title' => $this->getTitle(),
'url' => $this->getUrl()
);
}
/**
* Return the tab key
* @return string
*/
public function getModuleName()
{
$this->assertConfiguration();
return $this->moduleName;
}
}

View File

@ -0,0 +1,107 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Hook\Configuration;
use Icinga\Exception\ProgrammingError;
use Icinga\Web\Hook;
use Icinga\Web\Widget\Tabs;
/**
* Class ConfigurationTabBuilder
*
* Glue config tabs together
*
* @package Icinga\Web\Hook\Configuration
*/
class ConfigurationTabBuilder
{
/**
* Namespace for configuration tabs
*/
const HOOK_NAMESPACE = 'Configuration/Tabs';
/**
* Tabs widget
* @var Tabs
*/
private $tabs;
/**
* Create a new instance
* @param Tabs $tabs
*/
public function __construct(Tabs $tabs)
{
$this->setTabs($tabs);
$this->initializeSystemConfigurationTabs();
}
/**
* Setter for tabs
* @param \Icinga\Web\Widget\Tabs $tabs
*/
public function setTabs($tabs)
{
$this->tabs = $tabs;
}
/**
* Getter for tabs
* @return \Icinga\Web\Widget\Tabs
*/
public function getTabs()
{
return $this->tabs;
}
/**
* Build the tabs
*
*/
public function build()
{
/** @var ConfigurationTab $configTab */
$configTab = null;
foreach (Hook::all(self::HOOK_NAMESPACE) as $configTab) {
if (!$configTab instanceof ConfigurationTabInterface) {
throw new ProgrammingError('tab not instance of ConfigTabInterface');
}
$this->getTabs()->add($configTab->getModuleName(), $configTab->getTab());
}
}
/**
* Initialize system configuration tabs
*/
public function initializeSystemConfigurationTabs()
{
$configurationTab = new ConfigurationTab(
'configuration',
'configuration/index',
'Configuration'
);
// Display something about us
Hook::registerObject(
ConfigurationTabBuilder::HOOK_NAMESPACE,
$configurationTab->getModuleName(),
$configurationTab
);
$modulesOverviewTab = new ConfigurationTab(
'modules',
'modules/overview',
'Modules'
);
Hook::registerObject(
ConfigurationTabBuilder::HOOK_NAMESPACE,
$modulesOverviewTab->getModuleName(),
$modulesOverviewTab
);
}
}

View File

@ -0,0 +1,27 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Hook\Configuration;
/**
* Interface ConfigurationTabInterface
*
* Used to register configuration tab settings
*
* @package Icinga\Web\Hook\Configuration
*/
interface ConfigurationTabInterface
{
/**
* Returns a tab configuration to build configuration links
* @return array
*/
public function getTab();
/**
* Return the tab key
* @return string
*/
public function getModuleName();
}

View File

@ -17,7 +17,7 @@ use Icinga\Web\Url;
* @author Icinga-Web Team <info@icinga.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
class Tabs extends AbstractWidget
class Tabs extends AbstractWidget implements \Countable
{
/**
* This is where single tabs added to this container will be stored
@ -240,4 +240,18 @@ class Tabs extends AbstractWidget
$html .= "</ul>\n";
return $html;
}
/**
* Counting registered tabs
* @return int
*/
public function count()
{
return count($this->tabs);
}
public function getTabs()
{
return $this->tabs;
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace Tests\Icinga\Web\Hook\Configuration;
require_once '../../library/Icinga/Web/Hook/Configuration/ConfigurationTabInterface.php';
require_once '../../library/Icinga/Web/Hook/Configuration/ConfigurationTab.php';
require_once '../../library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilder.php';
require_once '../../library/Icinga/Web/Hook.php';
require_once '../../library/Icinga/Web/Widget/AbstractWidget.php';
require_once '../../library/Icinga/Web/Widget/Tabs.php';
require_once '../../library/Icinga/Web/Widget/Tab.php';
require_once '../../library/Icinga/Exception/ProgrammingError.php';
use Icinga\Web\Hook\Configuration\ConfigurationTab;
use Icinga\Web\Hook;
use Icinga\Web\Widget\Tabs;
use PHPUnit_Framework_TestResult;
class ConfigurationTabBuilderTest extends \PHPUnit_Framework_TestCase
{
protected function setUp()
{
parent::setUp();
Hook::clean();
}
protected function tearDown()
{
parent::tearDown();
Hook::clean();
}
public function testDefaultTabs()
{
$widget = new Tabs();
$builder = new Hook\Configuration\ConfigurationTabBuilder($widget);
$array = $builder->build();
$tabs = $builder->getTabs();
$this->assertInstanceOf('Icinga\\Web\\Widget\\Tab', $tabs->get('configuration'));
}
public function testTabCreation1()
{
$widget = new Tabs();
$builder = new Hook\Configuration\ConfigurationTabBuilder($widget);
$tab1 = new ConfigurationTab('test1', '/test1', 'TEST1');
$tab2 = new ConfigurationTab('test2', '/test2', 'TEST2');
$tab3 = new ConfigurationTab('test3', '/test3', 'TEST3');
Hook::registerObject(Hook\Configuration\ConfigurationTabBuilder::HOOK_NAMESPACE, 'test1', $tab1);
Hook::registerObject(Hook\Configuration\ConfigurationTabBuilder::HOOK_NAMESPACE, 'test2', $tab2);
Hook::registerObject(Hook\Configuration\ConfigurationTabBuilder::HOOK_NAMESPACE, 'test3', $tab3);
$builder->build();
$this->assertCount(5, $builder->getTabs());
}
/**
* @expectedException Icinga\Exception\ProgrammingError
* @expectedExceptionMessage tab not instance of ConfigTabInterface
*/
public function testTabCreation2()
{
$widget = new Tabs();
$builder = new Hook\Configuration\ConfigurationTabBuilder($widget);
$tab = new \stdClass();
Hook::registerObject(Hook\Configuration\ConfigurationTabBuilder::HOOK_NAMESPACE, 'misc', $tab);
$builder->build();
$this->assertCount(5, $builder->getTabs());
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace Tests\Icinga\Web\Hook\Configuration;
require_once '../../library/Icinga/Web/Hook/Configuration/ConfigurationTabInterface.php';
require_once '../../library/Icinga/Web/Hook/Configuration/ConfigurationTab.php';
require_once '../../library/Icinga/Exception/ProgrammingError.php';
use Icinga\Web\Hook\Configuration\ConfigurationTab;
class ConfigurationTabTest extends \PHPUnit_Framework_TestCase
{
public function testCreate1()
{
$tab = new ConfigurationTab(
'test1',
'/test/$555',
'TEST_TITLE'
);
$this->assertEquals('test1', $tab->getModuleName());
$testArray = array(
'title' => 'TEST_TITLE',
'url' => '/test/$555'
);
$this->assertEquals($testArray, $tab->getTab());
}
public function testCreate2()
{
$tab = new ConfigurationTab(
'test2',
'/test/$666'
);
$this->assertEquals('test2', $tab->getModuleName());
$testArray = array(
'title' => 'test2',
'url' => '/test/$666'
);
$this->assertEquals($testArray, $tab->getTab());
}
/**
* @expectedException Icinga\Exception\ProgrammingError
* @expectedExceptionMessage moduleName is missing
*/
public function testException1()
{
$tab = new ConfigurationTab();
$tab->getTab();
}
/**
* @expectedException Icinga\Exception\ProgrammingError
* @expectedExceptionMessage url is missing
*/
public function testException2()
{
$tab = new ConfigurationTab();
$tab->setModuleName('DING1');
$tab->getTab();
}
/**
* @expectedException Icinga\Exception\ProgrammingError
* @expectedExceptionMessage title is missing
*/
public function testException3()
{
$tab = new ConfigurationTab();
$tab->setModuleName('DING1');
$tab->setUrl('/ding/dong');
$tab->getTab();
}
}