diff --git a/src/CentreonLegacy/Core/Menu/Menu.php b/src/CentreonLegacy/Core/Menu/Menu.php new file mode 100644 index 0000000000000000000000000000000000000000..e79f03620a0721b2ffe4d753be4f9e349554c4c3 --- /dev/null +++ b/src/CentreonLegacy/Core/Menu/Menu.php @@ -0,0 +1,251 @@ +<?php +/** + * Copyright 2005-2018 Centreon + * Centreon is developped by : Julien Mathis and Romain Le Merlus under + * GPL Licence 2.0. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation ; either version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see <http://www.gnu.org/licenses>. + * + * Linking this program statically or dynamically with other modules is making a + * combined work based on this program. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this program give Centreon + * permission to link this program with independent modules to produce an executable, + * regardless of the license terms of these independent modules, and to copy and + * distribute the resulting executable under terms of Centreon choice, provided that + * Centreon also meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module which is not + * derived from this program. If you modify this program, you may extend this + * exception to your version of the program, but you are not obliged to do so. If you + * do not wish to do so, delete this exception statement from your version. + * + * For more information : contact@centreon.com + * + */ + +namespace CentreonLegacy\Core\Menu; + +class Menu +{ + /** + * @var CentreonDB The configuration database connection + */ + protected $db; + /** + * @var string The query filter for ACL + */ + protected $acl = null; + + /** + * Constructor + * + * @param CentreonDB $db The configuration database connection + * @param CentreonUser $user The current user + */ + public function __construct($db, $user = null) + { + $this->db = $db; + if (!is_null($user) && !$user->is_admin) { + $this->acl = ' AND topology_page IN (' . $user->access->getTopologyString() . ')'; + } + } + + /** + * Get the level one and level two parents for a page id + * + * For 20101 : + * array( + * "levelTwo" => 201, + * "levelOne" => 2 + * ) + * + * For 201 : + * array( + * "levelTwo" => 201, + * "levelOne" => 2 + * ) + * + * For 2 : + * array( + * "levelTwo" => null, + * "levelOne" => 2 + * ) + * + * @param int $pageId The page id to find parents + * @return array The parents + */ + public function getParentsId($pageId) + { + $firstParent = $this->getParentId($pageId); + if (is_null($firstParent)) { + return array( + 'levelOne' => $pageId, + 'levelTwo' => null + ); + } + $secondParent = $this->getParentId($firstParent); + if (is_null($secondParent)) { + return array( + 'levelOne' => $firstParent, + 'levelTwo' => $pageId + ); + } + return array( + 'levelOne' => $secondParent, + 'levelTwo' => $firstParent + ); + } + + /** + * Get the parent id for a page + * + * @param int $pageId The page id to find parent + * @return int The parent page id + */ + public function getParentId($pageId) + { + $query = 'SELECT topology_parent FROM topology WHERE topology_page = :page'; + $stmt = $this->db->prepare($query); + $stmt->bindParam(':page', $pageId, \PDO::PARAM_INT); + $stmt->execute(); + $row = $stmt->fetch(\PDO::FETCH_ASSOC); + $parent = null; + if ($row) { + $parent = $row['topology_parent']; + } + $stmt->closeCursor(); + return $parent; + } + + /** + * Get the level three menu + * + * Without groups + * + * array( + * array( + * "id" => "201", + * "label" => "My menu", + * "url" => "http://page" + * ) + * ) + * + * With groups + * + * array( + * array( + * "id" => "212", + * "label" => "", + * "children" => array( + * array( + * "id" => "201", + * "label" => "My menu", + * "url" => "http://page" + * ) + * ) + * ) + * ) + * + * @param int $parentId The parent id + * @return array The menu + */ + public function getMenuChildren($parentId = null) + { + /* Load groups */ + $groups = $this->getGroups($parentId); + + $query = 'SELECT topology_name, topology_page, topology_url, topology_group FROM topology + WHERE topology_show = "1" AND topology_page IS NOT NULL'; + if (is_null($parentId)) { + $query .= ' AND topology_parent IS NULL'; + } else { + $query .= ' AND topology_parent = :parent'; + } + + if (!is_null($this->acl)) { + $query .= $this->acl; + } + $query .= ' ORDER BY topology_group, topology_order'; + $stmt = $this->db->prepare($query); + if (!is_null($parentId)) { + $stmt->bindParam(':parent', $parentId, \PDO::PARAM_INT); + } + + $stmt->execute(); + + $menu = array(); + + while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + $item = array( + 'id' => $row['topology_page'], + 'label' => $row['topology_name'], + 'url' => $row['topology_url'] + ); + if (is_null($row['topology_group'])) { + $menu[] = $item; + } else { + /* Find the good group */ + $found = false; + for ($i = 0; $i < count($menu); $i++) { + if ($menu[$i]['id'] === $row['topology_group'] && isset($menu[$i]['children'])) { + $found = true; + $menu[$i]['children'][] = $item; + } + } + /* If not found add the group with the menu item */ + if (!$found) { + if (isset($groups[$row['topology_group']])) { + $menu[] = array( + 'id' => $row['topology_group'], + 'label' => $groups[$row['topology_group']], + 'children' => array($item) + ); + } else { + $menu[] = $item; + } + } + } + } + $stmt->closeCursor(); + return $menu; + } + + /** + * Get the list of groups + * + * @param int $parentId The parent id + * @return array The list of groups + */ + public function getGroups($parentId = null) + { + $query = 'SELECT topology_name, topology_group FROM topology + WHERE topology_show = "1" AND topology_page IS NULL AND topology_parent = :parent + ORDER BY topology_group, topology_order'; + $stmt = $this->db->prepare($query); + if (is_null($parentId)) { + $stmt->bindValue(':parent', null, \PDO::PARAM_NULL); + } else { + $stmt->bindParam(':parent', $parentId, \PDO::PARAM_INT); + } + + $stmt->execute(); + $groups = array(); + + while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + $groups[$row['topology_group']] = $row['topology_name']; + } + $stmt->closeCursor(); + + return $groups; + } +} diff --git a/tests/php/CentreonLegacy/Core/Menu/MenuTest.php b/tests/php/CentreonLegacy/Core/Menu/MenuTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5a2c88b5d46cd32c42ea29432b5d5da982c11237 --- /dev/null +++ b/tests/php/CentreonLegacy/Core/Menu/MenuTest.php @@ -0,0 +1,364 @@ +<?php +/** + * Copyright 2005-2018 Centreon + * Centreon is developped by : Julien Mathis and Romain Le Merlus under + * GPL Licence 2.0. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation ; either version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see <http://www.gnu.org/licenses>. + * + * Linking this program statically or dynamically with other modules is making a + * combined work based on this program. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this program give Centreon + * permission to link this program with independent modules to produce an executable, + * regardless of the license terms of these independent modules, and to copy and + * distribute the resulting executable under terms of Centreon choice, provided that + * Centreon also meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module which is not + * derived from this program. If you modify this program, you may extend this + * exception to your version of the program, but you are not obliged to do so. If you + * do not wish to do so, delete this exception statement from your version. + * + * For more information : contact@centreon.com + * + */ + +namespace CentreonLegacy\Core\Menu; + +use \Centreon\Test\Mock\CentreonDB; + +class MenuTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var CentreonDb The database mock + */ + private $db; + + public function setUp() + { + $this->db = new CentreonDB(); + } + + public function testGetParentIdHasParent() + { + /* Test has a parent id */ + $this->db->addResultSet( + 'SELECT topology_parent FROM topology WHERE topology_page = :page', + array( + array( + 'topology_parent' => 2 + ) + ), + array( + ':page' => 201 + ) + ); + $menu = new Menu($this->db); + $this->assertEquals($menu->getParentId(201), 2); + } + + public function testGetParentIdHasNotParent() + { + /* Test has a parent id */ + $this->db->addResultSet( + 'SELECT topology_parent FROM topology WHERE topology_page = :page', + array( + array( + 'topology_parent' => null + ) + ), + array( + ':page' => 201 + ) + ); + $menu = new Menu($this->db); + $this->assertNull($menu->getParentId(201)); + } + + public function testGetParentsIdLevelThree() + { + $this->db->addResultSet( + 'SELECT topology_parent FROM topology WHERE topology_page = :page', + array( + array( + 'topology_parent' => 201 + ) + ), + array( + ':page' => 20101 + ) + ); + $this->db->addResultSet( + 'SELECT topology_parent FROM topology WHERE topology_page = :page', + array( + array( + 'topology_parent' => 2 + ) + ), + array( + ':page' => 201 + ) + ); + $menu = new Menu($this->db); + $this->assertEquals( + $menu->getParentsId(20101), + array( + 'levelOne' => 2, + 'levelTwo' => 201 + ) + ); + } + + public function testGetParentsIdLevelTwo() + { + $this->db->addResultSet( + 'SELECT topology_parent FROM topology WHERE topology_page = :page', + array( + array( + 'topology_parent' => 2 + ) + ), + array( + ':page' => 201 + ) + ); + $this->db->addResultSet( + 'SELECT topology_parent FROM topology WHERE topology_page = :page', + array( + array( + 'topology_parent' => null + ) + ), + array( + ':page' => 2 + ) + ); + $menu = new Menu($this->db); + $this->assertEquals( + $menu->getParentsId(201), + array( + 'levelOne' => 2, + 'levelTwo' => 201 + ) + ); + } + + public function testGetParentsIdLevelOne() + { + $this->db->addResultSet( + 'SELECT topology_parent FROM topology WHERE topology_page = :page', + array( + array( + 'topology_parent' => null + ) + ), + array( + ':page' => 2 + ) + ); + $menu = new Menu($this->db); + $this->assertEquals( + $menu->getParentsId(2), + array( + 'levelOne' => 2, + 'levelTwo' => null + ) + ); + } + + public function testGetGroupsWithParentNull() + { + $this->db->addResultSet( + 'SELECT topology_name, topology_group FROM topology + WHERE topology_show = "1" AND topology_page IS NULL AND topology_parent = :parent + ORDER BY topology_group, topology_order', + array( + array( + 'topology_name' => 'By host', + 'topology_group' => 201 + ), + array( + 'topology_name' => 'By services', + 'topology_group' => 202 + ) + ), + array( + ':parent' => null + ) + ); + $menu = new Menu($this->db); + $this->assertEquals( + $menu->getGroups(), + array( + 201 => 'By host', + 202 => 'By services' + ) + ); + } + + public function testGetGroupsWithParentNotNull() + { + $this->db->addResultSet( + 'SELECT topology_name, topology_group FROM topology + WHERE topology_show = "1" AND topology_page IS NULL AND topology_parent = :parent + ORDER BY topology_group, topology_order', + array( + array( + 'topology_name' => 'By host', + 'topology_group' => 201 + ), + array( + 'topology_name' => 'By services', + 'topology_group' => 202 + ) + ), + array( + ':parent' => 2 + ) + ); + $menu = new Menu($this->db); + $this->assertEquals( + $menu->getGroups(2), + array( + 201 => 'By host', + 202 => 'By services' + ) + ); + } + + public function testGetMenuChildrenLevelOne() + { + $this->db->addResultSet( + 'SELECT topology_name, topology_group FROM topology + WHERE topology_show = "1" AND topology_page IS NULL AND topology_parent = :parent + ORDER BY topology_group, topology_order', + array(), + array( + ':parent' => null + ) + ); + $this->db->addResultSet( + 'SELECT topology_name, topology_page, topology_url, topology_group FROM topology + WHERE topology_show = "1" AND topology_page IS NOT NULL AND topology_parent IS NULL ORDER BY topology_group, topology_order', + array( + array( + 'topology_name' => 'Home', + 'topology_page' => 1, + 'topology_url' => 'main.php?p=1', + 'topology_group' => null + ), + array( + 'topology_name' => 'Monitoring', + 'topology_page' => 2, + 'topology_url' => 'main.php?p=2', + 'topology_group' => null + ) + ) + ); + $menu = new Menu($this->db); + $this->assertEquals( + $menu->getMenuChildren(), + array( + array( + 'id' => 1, + 'label' => 'Home', + 'url' => 'main.php?p=1' + ), + array( + 'id' => 2, + 'label' => 'Monitoring', + 'url' => 'main.php?p=2' + ) + ) + ); + } + + public function testGetMenuChildrenLevelThreeWithGroups() + { + $this->db->addResultSet( + 'SELECT topology_name, topology_group FROM topology + WHERE topology_show = "1" AND topology_page IS NULL AND topology_parent = :parent + ORDER BY topology_group, topology_order', + array( + array( + 'topology_name' => 'By host', + 'topology_group' => 201 + ), + array( + 'topology_name' => 'By services', + 'topology_group' => 202 + ) + ), + array( + ':parent' => 2 + ) + ); + $this->db->addResultSet( + 'SELECT topology_name, topology_page, topology_url, topology_group FROM topology + WHERE topology_show = "1" AND topology_page IS NOT NULL AND topology_parent = :parent ORDER BY topology_group, topology_order', + array( + array( + 'topology_name' => 'Status', + 'topology_page' => 20101, + 'topology_url' => 'main.php?p=20101', + 'topology_group' => 201 + ), + array( + 'topology_name' => 'Status by group', + 'topology_page' => 20102, + 'topology_url' => 'main.php?p=20102', + 'topology_group' => 201 + ), + array( + 'topology_name' => 'Status', + 'topology_page' => 20201, + 'topology_url' => 'main.php?p=20201', + 'topology_group' => 202 + ) + ) + ); + $menu = new Menu($this->db); + $this->assertEquals( + $menu->getMenuChildren(2), + array( + array( + 'id' => 201, + 'label' => 'By host', + 'children' => array( + array( + 'id' => 20101, + 'label' => 'Status', + 'url' => 'main.php?p=20101' + ), + array( + 'id' => 20102, + 'label' => 'Status by group', + 'url' => 'main.php?p=20102' + ) + ) + ), + array( + 'id' => 202, + 'label' => 'By services', + 'children' => array( + array( + 'id' => 20201, + 'label' => 'Status', + 'url' => 'main.php?p=20201' + ) + ) + ) + ) + ); + } +} diff --git a/www/api/class/centreon_menu.class.php b/www/api/class/centreon_menu.class.php new file mode 100644 index 0000000000000000000000000000000000000000..ffeca16ecae1fbd7143637d9b6da28c5acdfbcea --- /dev/null +++ b/www/api/class/centreon_menu.class.php @@ -0,0 +1,132 @@ +<?php +/** + * Copyright 2005-2018 Centreon + * Centreon is developped by : Julien Mathis and Romain Le Merlus under + * GPL Licence 2.0. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation ; either version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see <http://www.gnu.org/licenses>. + * + * Linking this program statically or dynamically with other modules is making a + * combined work based on this program. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this program give Centreon + * permission to link this program with independent modules to produce an executable, + * regardless of the license terms of these independent modules, and to copy and + * distribute the resulting executable under terms of Centreon choice, provided that + * Centreon also meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module which is not + * derived from this program. If you modify this program, you may extend this + * exception to your version of the program, but you are not obliged to do so. If you + * do not wish to do so, delete this exception statement from your version. + * + * For more information : contact@centreon.com + * + */ + +use CentreonLegacy\Core\Menu\Menu; + +require_once dirname(__FILE__) . "/webService.class.php"; + +class CentreonMenu extends CentreonWebService +{ + /** + * Get the init menu on loading page + * + * Argument: + * page -> int - The current page + * + * Method: GET + */ + public function getInitMenu() + { + if (!isset($_SESSION['centreon'])) { + throw new \RestUnauthorizedException('Session does not exists.'); + } + + if (!isset($this->arguments['page']) || !is_numeric($this->arguments['page'])) { + throw new \RestBadRequestException('Missing type argument or bad type page.'); + } + $page = $this->arguments['page']; + + $menu = new Menu($this->pearDB, $_SESSION['centreon']->user); + + $parents = $menu->getParentsId($page); + + /* Build the base menu tree on getting the menu level one */ + $menuTree = $menu->getMenuChildren(); + for ($i = 0; $i < count($menuTree); $i++) { + /* Default additional values */ + $menuTree[$i]['children'] = array(); + $menuTree[$i]['active'] = false; + if ($menuTree[$i]['id'] === $parents['levelOne']) { + $menuTree[$i]['active'] = true; + /* Get level two menu if page has level 2 */ + if (!is_null($parents['levelTwo'])) { + $menuTree[$i]['children'] = $menu->getMenuChildren($parents['levelOne']); + for ($j = 0; $j < count($menuTree[$i]['children']); $j++) { + /* Default additional values */ + $menuTree[$i]['children'][$j]['active'] = false; + $menuTree[$i]['children'][$j]['children'] = array(); + if ($menuTree[$i]['children'][$j]['id'] === $parents['levelTwo']) { + $menuTree[$i]['children'][$j]['active'] = true; + $menuTree[$i]['children'][$j]['children'] = $menu->getMenuChildren($parents['levelTwo']); + /* Search the current activated */ + for ($k = 0; $k < count($menuTree[$i]['children'][$j]['children']); $k++) { + $active = false; + /* Test if a group */ + if (is_array($menuTree[$i]['children'][$j]['children'][$k]['children'])) { + for ($l = 0; + $l < count($menuTree[$i]['children'][$j]['children'][$k]['children']); + $l++) { + if ($menuTree[$i]['children'][$j]['children'][$k]['children'][$l]['id'] === $page) { + $menuTree[$i]['children'][$j]['children'][$k]['children'][$l]['active'] = true; + } else { + $menuTree[$i]['children'][$j]['children'][$k]['children'][$l]['active'] = false; + } + } + } else if ($menuTree[$i]['children'][$j]['children'][$k]['id'] === $page) { + $active = true; + } + $menuTree[$i]['children'][$j]['children'][$k]['active'] = $active; + } + } + } + } + } + } + return $menuTree; + } + + /** + * Get menu children + * + * Argument: + * parent -> int - The id of level parent + * + * Method: GET + */ + public function getMenuChildren() + { + if (!isset($_SESSION['centreon'])) { + throw new \RestUnauthorizedException('Session does not exists.'); + } + + if (!isset($this->arguments['parent']) || !is_numeric($this->arguments['parent'])) { + throw new \RestBadRequestException('Missing type argument or bad type parent.'); + } + + $menu = new Menu($this->pearDB, $_SESSION['centreon']->user); + + return $menu->getMenuChildren($this->arguments['parent']); + } +}