From 9b5f738f578137389fb3572d9654e2eb6a57af15 Mon Sep 17 00:00:00 2001 From: Thomas Steur Date: Wed, 24 Apr 2013 18:26:09 +0200 Subject: [PATCH] refs #3913 provide a simple API for dashboards --- plugins/Dashboard/API.php | 154 ++++++++++++++++++++++++++++++ plugins/Dashboard/Controller.php | 140 ++++++--------------------- plugins/Dashboard/Dashboard.php | 158 ++++++++++++++++++++++++++++--- 3 files changed, 325 insertions(+), 127 deletions(-) create mode 100644 plugins/Dashboard/API.php diff --git a/plugins/Dashboard/API.php b/plugins/Dashboard/API.php new file mode 100644 index 00000000000..dde28f6e690 --- /dev/null +++ b/plugins/Dashboard/API.php @@ -0,0 +1,154 @@ +Dashboard API: it gives information about dashboards. + * + * @package Piwik_API + */ +class Piwik_Dashboard_API +{ + /** + * @var Piwik_Dashboard_API + */ + static private $instance = null; + + private $dashboard = null; + + public function __construct() + { + $this->dashboard = new Piwik_Dashboard(); + } + + /** + * @return Piwik_Dashboard_API + */ + static public function getInstance() + { + if (null == self::$instance) { + self::$instance = new self; + } + + return self::$instance; + } + + /** + * Get each dashboard that belongs to a user including the containing widgets that are placed within each dashboard. + * If the user has not created any dashboard yet, the default dashboard will be returned. + * + * @return array[] + */ + public function getDashboards() + { + $dashboards = $this->getUserDashboards(); + + if (empty($dashboards)) { + $dashboards = array($this->getDefaultDashboard()); + } + + return $dashboards; + } + + /** + * Get the default dashboard. + * + * @return array[] + */ + public function getDefaultDashboard() + { + $defaultLayout = $this->dashboard->getDefaultLayout(); + $defaultLayout = $this->dashboard->decodeLayout($defaultLayout); + + $defaultDashboard = array('name' => Piwik_Translate('Dashboard_Dashboard'), 'layout' => $defaultLayout); + + $widgets = $this->getExistingWidgetsWithinDashboard($defaultDashboard); + + return $this->buildDashboard($defaultDashboard, $widgets); + } + + /** + * Get all dashboards which a user has created. + * + * @return array[] + */ + public function getUserDashboards() + { + $userLogin = Piwik::getCurrentUserLogin(); + $userDashboards = $this->dashboard->getAllDashboards($userLogin); + + $dashboards = array(); + + foreach ($userDashboards as $userDashboard) { + + if ($this->hasDashboardColumns($userDashboard)) { + $widgets = $this->getExistingWidgetsWithinDashboard($userDashboard); + $dashboards[] = $this->buildDashboard($userDashboard, $widgets); + } + + } + + return $dashboards; + } + + private function getExistingWidgetsWithinDashboard($dashboard) + { + $columns = $this->getColumnsFromDashboard($dashboard); + + $widgets = array(); + $columns = array_filter($columns); + + foreach ($columns as $column) { + foreach ($column as $widget) { + + if ($this->widgetIsNotHidden($widget) && $this->widgetExists($widget)) { + $module = $widget->parameters->module; + $action = $widget->parameters->action; + + $widgets[] = array('module' => $module, 'action' => $action); + } + } + } + + return $widgets; + } + + private function getColumnsFromDashboard($dashboard) + { + if (is_array($dashboard['layout'])) { + + return $dashboard['layout']; + } + + return $dashboard['layout']->columns; + } + + private function hasDashboardColumns($dashboard) + { + if (is_array($dashboard['layout'])) { + + return !empty($dashboard['layout']); + } + + return !empty($dashboard['layout']->columns); + } + + private function buildDashboard($dashboard, $widgets) + { + return array('name' => $dashboard['name'], 'widgets' => $widgets); + } + + private function widgetExists($widget) + { + if (empty($widget->parameters)) { + return false; + } + + $module = $widget->parameters->module; + $action = $widget->parameters->action; + + return Piwik_IsWidgetDefined($module, $action); + } + + private function widgetIsNotHidden($widget) + { + return empty($widget->isHidden); + } +} diff --git a/plugins/Dashboard/Controller.php b/plugins/Dashboard/Controller.php index be49ce1adef..0fdbba275fd 100644 --- a/plugins/Dashboard/Controller.php +++ b/plugins/Dashboard/Controller.php @@ -15,6 +15,18 @@ */ class Piwik_Dashboard_Controller extends Piwik_Controller { + /** + * @var Piwik_Dashboard + */ + private $dashboard; + + protected function init() + { + parent::init(); + + $this->dashboard = new Piwik_Dashboard(); + } + protected function _getDashboardView($template) { $view = Piwik_View::factory($template); @@ -43,7 +55,7 @@ public function index() if (!Piwik::isUserIsAnonymous()) { $login = Piwik::getCurrentUserLogin(); - $view->dashboards = Piwik_Dashboard::getAllDashboards($login); + $view->dashboards = $this->dashboard->getAllDashboards($login); } echo $view->render(); } @@ -73,7 +85,7 @@ public function getDashboardLayout() public function resetLayout() { $this->checkTokenInUrl(); - $layout = $this->getDefaultLayout(); + $layout = $this->dashboard->getDefaultLayout(); $idDashboard = Piwik_Common::getRequestVar('idDashboard', 1, 'int'); if (Piwik::isUserIsAnonymous()) { $session = new Piwik_Session_Namespace("Piwik_Dashboard"); @@ -114,29 +126,6 @@ protected function updateDashboardName($login, $idDashboard, $name) Piwik_Query($query, $paramsBind); } - /** - * Returns the layout in the DB for the given user, or false if the layout has not been set yet. - * Parameters must be checked BEFORE this function call - * - * @param string $login - * @param int $idDashboard - * - * @return bool - */ - protected function _getLayoutForUser($login, $idDashboard) - { - $paramsBind = array($login, $idDashboard); - $query = sprintf('SELECT layout FROM %s WHERE login = ? AND iddashboard = ?', - Piwik_Common::prefixTable('user_dashboard')); - $return = Piwik_FetchAll($query, $paramsBind); - - if (count($return) == 0) { - return false; - } - - return $return[0]['layout']; - } - /** * Removes the dashboard with the given id */ @@ -168,9 +157,9 @@ public function getAllDashboards() echo '[]'; return; } - $login = Piwik::getCurrentUserLogin(); - $dashboards = Piwik_Dashboard::getAllDashboards($login); + $login = Piwik::getCurrentUserLogin(); + $dashboards = $this->dashboard->getAllDashboards($login); Piwik_DataTable_Renderer_Json::sendHeaderJSON(); echo Piwik_Common::json_encode($dashboards); @@ -196,7 +185,7 @@ public function createNewDashboard() $layout = '{}'; if ($type == 'default') { - $layout = $this->getDefaultLayout(); + $layout = $this->dashboard->getDefaultLayout(); } $query = sprintf('INSERT INTO %s (login, iddashboard, name, layout) VALUES (?, ?, ?, ?)', @@ -232,7 +221,7 @@ public function copyDashboardToUser() $name = urldecode(Piwik_Common::getRequestVar('name', '', 'string')); $user = urldecode(Piwik_Common::getRequestVar('user', '', 'string')); $idDashboard = Piwik_Common::getRequestVar('dashboardId', 0, 'int'); - $layout = $this->_getLayoutForUser($login, $idDashboard); + $layout = $this->dashboard->getLayoutForUser($login, $idDashboard); if ($layout !== false) { $nextId = $this->getNextIdDashboard($user); @@ -297,105 +286,30 @@ public function saveLayoutAsDefault() protected function getLayout($idDashboard) { if (Piwik::isUserIsAnonymous()) { + $session = new Piwik_Session_Namespace("Piwik_Dashboard"); if (!isset($session->dashboardLayout)) { - return $this->getDefaultLayout(); + + return $this->dashboard->getDefaultLayout(); } + $layout = $session->dashboardLayout; + } else { - $layout = $this->_getLayoutForUser(Piwik::getCurrentUserLogin(), $idDashboard); + $layout = $this->dashboard->getLayoutForUser(Piwik::getCurrentUserLogin(), $idDashboard); } + if (!empty($layout)) { - $layout = $this->removeDisabledPluginFromLayout($layout); + $layout = $this->dashboard->removeDisabledPluginFromLayout($layout); } if (empty($layout)) { - $layout = $this->getDefaultLayout(); - } - return $layout; - } - - protected function removeDisabledPluginFromLayout($layout) - { - $layout = str_replace("\n", "", $layout); - // if the json decoding works (ie. new Json format) - // we will only return the widgets that are from enabled plugins - $layoutObject = Piwik_Common::json_decode($layout, $assoc = false); - - if (is_array($layoutObject)) { - $layoutObject = (object)array( - 'config' => array('layout' => '33-33-33'), - 'columns' => $layoutObject - ); - } - - if (empty($layoutObject) || empty($layoutObject->columns)) { - $layoutObject = (object)array( - 'config' => array('layout' => '33-33-33'), - 'columns' => array() - ); + $layout = $this->dashboard->getDefaultLayout(); } - foreach ($layoutObject->columns as &$row) { - if (!is_array($row)) { - $row = array(); - continue; - } - - foreach ($row as $widgetId => $widget) { - if (isset($widget->parameters->module)) { - $controllerName = $widget->parameters->module; - $controllerAction = $widget->parameters->action; - if (!Piwik_IsWidgetDefined($controllerName, $controllerAction)) { - unset($row[$widgetId]); - } - } else { - unset($row[$widgetId]); - } - } - } - $layout = Piwik_Common::json_encode($layoutObject); return $layout; } - protected function getDefaultLayout() - { - $defaultLayout = $this->_getLayoutForUser('', 1); - - if (empty($defaultLayout)) { - $topWidget = ''; - if (Piwik::isUserIsSuperUser()) { - $topWidget = '{"uniqueId":"widgetCoreHomegetDonateForm",' - . '"parameters":{"module":"CoreHome","action":"getDonateForm"}},'; - } else { - $topWidget = '{"uniqueId":"widgetCoreHomegetPromoVideo",' - . '"parameters":{"module":"CoreHome","action":"getPromoVideo"}},'; - } - - $defaultLayout = '[ - [ - {"uniqueId":"widgetVisitsSummarygetEvolutionGraphcolumnsArray","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":"nb_visits"}}, - {"uniqueId":"widgetLivewidget","parameters":{"module":"Live","action":"widget"}}, - {"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDuration","parameters":{"module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}} - ], - [ - ' . $topWidget . ' - {"uniqueId":"widgetReferersgetKeywords","parameters":{"module":"Referers","action":"getKeywords"}}, - {"uniqueId":"widgetReferersgetWebsites","parameters":{"module":"Referers","action":"getWebsites"}} - ], - [ - {"uniqueId":"widgetUserCountryMapvisitorMap","parameters":{"module":"UserCountryMap","action":"visitorMap"}}, - {"uniqueId":"widgetUserSettingsgetBrowser","parameters":{"module":"UserSettings","action":"getBrowser"}}, - {"uniqueId":"widgetReferersgetSearchEngines","parameters":{"module":"Referers","action":"getSearchEngines"}}, - {"uniqueId":"widgetVisitTimegetVisitInformationPerServerTime","parameters":{"module":"VisitTime","action":"getVisitInformationPerServerTime"}}, - {"uniqueId":"widgetExampleRssWidgetrssPiwik","parameters":{"module":"ExampleRssWidget","action":"rssPiwik"}} - ] - ]'; - } - $defaultLayout = $this->removeDisabledPluginFromLayout($defaultLayout); - return $defaultLayout; - } - /** * Returns all available column layouts for the dashboard * diff --git a/plugins/Dashboard/Dashboard.php b/plugins/Dashboard/Dashboard.php index 50a71bf28c5..f3db9fba6b4 100644 --- a/plugins/Dashboard/Dashboard.php +++ b/plugins/Dashboard/Dashboard.php @@ -35,34 +35,165 @@ public function getListHooksRegistered() ); } - public static function getAllDashboards($login) + /** + * Returns the layout in the DB for the given user, or false if the layout has not been set yet. + * Parameters must be checked BEFORE this function call + * + * @param string $login + * @param int $idDashboard + * + * @return bool|string + */ + public function getLayoutForUser($login, $idDashboard) + { + $paramsBind = array($login, $idDashboard); + $query = sprintf('SELECT layout FROM %s WHERE login = ? AND iddashboard = ?', + Piwik_Common::prefixTable('user_dashboard')); + $return = Piwik_FetchAll($query, $paramsBind); + + if (count($return) == 0) { + return false; + } + + return $return[0]['layout']; + } + + public function getDefaultLayout() + { + $defaultLayout = $this->getLayoutForUser('', 1); + + if (empty($defaultLayout)) { + if (Piwik::isUserIsSuperUser()) { + $topWidget = '{"uniqueId":"widgetCoreHomegetDonateForm",' + . '"parameters":{"module":"CoreHome","action":"getDonateForm"}},'; + } else { + $topWidget = '{"uniqueId":"widgetCoreHomegetPromoVideo",' + . '"parameters":{"module":"CoreHome","action":"getPromoVideo"}},'; + } + + $defaultLayout = '[ + [ + {"uniqueId":"widgetVisitsSummarygetEvolutionGraphcolumnsArray","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":"nb_visits"}}, + {"uniqueId":"widgetLivewidget","parameters":{"module":"Live","action":"widget"}}, + {"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDuration","parameters":{"module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}} + ], + [ + ' . $topWidget . ' + {"uniqueId":"widgetReferersgetKeywords","parameters":{"module":"Referers","action":"getKeywords"}}, + {"uniqueId":"widgetReferersgetWebsites","parameters":{"module":"Referers","action":"getWebsites"}} + ], + [ + {"uniqueId":"widgetUserCountryMapvisitorMap","parameters":{"module":"UserCountryMap","action":"visitorMap"}}, + {"uniqueId":"widgetUserSettingsgetBrowser","parameters":{"module":"UserSettings","action":"getBrowser"}}, + {"uniqueId":"widgetReferersgetSearchEngines","parameters":{"module":"Referers","action":"getSearchEngines"}}, + {"uniqueId":"widgetVisitTimegetVisitInformationPerServerTime","parameters":{"module":"VisitTime","action":"getVisitInformationPerServerTime"}}, + {"uniqueId":"widgetExampleRssWidgetrssPiwik","parameters":{"module":"ExampleRssWidget","action":"rssPiwik"}} + ] + ]'; + } + + $defaultLayout = $this->removeDisabledPluginFromLayout($defaultLayout); + + return $defaultLayout; + } + + public function getAllDashboards($login) { - $dashboards = Piwik_FetchAll('SELECT iddashboard, name - FROM ' . Piwik_Common::prefixTable('user_dashboard') . + $dashboards = Piwik_FetchAll('SELECT iddashboard, name, layout + FROM ' . Piwik_Common::prefixTable('user_dashboard') . ' WHERE login = ? ORDER BY iddashboard', array($login)); - $pos = 0; + $nameless = 1; foreach ($dashboards AS &$dashboard) { + if (empty($dashboard['name'])) { $dashboard['name'] = Piwik_Translate('Dashboard_DashboardOf', $login); if ($nameless > 1) { $dashboard['name'] .= " ($nameless)"; } - if (empty($dashboard['layout'])) { - $layout = '[]'; - } else { - $layout = html_entity_decode($dashboard['layout']); - $layout = str_replace("\\\"", "\"", $layout); - } - $dashboard['layout'] = Piwik_Common::json_decode($layout); + $nameless++; } + $dashboard['name'] = Piwik_Common::unsanitizeInputValue($dashboard['name']); - $pos++; + + $layout = '[]'; + if (!empty($dashboard['layout'])) { + $layout = $dashboard['layout']; + } + + $dashboard['layout'] = $this->decodeLayout($layout); } + return $dashboards; } + private function isAlreadyDecodedLayout($layout) + { + return !is_string($layout); + } + + public function removeDisabledPluginFromLayout($layout) + { + $layoutObject = $this->decodeLayout($layout); + + // if the json decoding works (ie. new Json format) + // we will only return the widgets that are from enabled plugins + + if (is_array($layoutObject)) { + $layoutObject = (object)array( + 'config' => array('layout' => '33-33-33'), + 'columns' => $layoutObject + ); + } + + if (empty($layoutObject) || empty($layoutObject->columns)) { + $layoutObject = (object)array( + 'config' => array('layout' => '33-33-33'), + 'columns' => array() + ); + } + + foreach ($layoutObject->columns as &$row) { + if (!is_array($row)) { + $row = array(); + continue; + } + + foreach ($row as $widgetId => $widget) { + if (isset($widget->parameters->module)) { + $controllerName = $widget->parameters->module; + $controllerAction = $widget->parameters->action; + if (!Piwik_IsWidgetDefined($controllerName, $controllerAction)) { + unset($row[$widgetId]); + } + } else { + unset($row[$widgetId]); + } + } + } + $layout = $this->encodeLayout($layoutObject); + return $layout; + } + + public function decodeLayout($layout) + { + if ($this->isAlreadyDecodedLayout($layout)) { + return $layout; + } + + $layout = html_entity_decode($layout); + $layout = str_replace("\\\"", "\"", $layout); + $layout = str_replace("\n", "", $layout); + + return Piwik_Common::json_decode($layout, $assoc = false); + } + + public function encodeLayout($layout) + { + return Piwik_Common::json_encode($layout); + } + public function addMenus() { Piwik_AddMenu('Dashboard_Dashboard', '', array('module' => 'Dashboard', 'action' => 'embeddedIndex', 'idDashboard' => 1), true, 5); @@ -70,7 +201,7 @@ public function addMenus() if (!Piwik::isUserIsAnonymous()) { $login = Piwik::getCurrentUserLogin(); - $dashboards = self::getAllDashboards($login); + $dashboards = $this->getAllDashboards($login); if (count($dashboards) > 1) { $pos = 0; foreach ($dashboards AS $dashboard) { @@ -155,5 +286,4 @@ public function uninstall() { Piwik_DropTables(Piwik_Common::prefixTable('user_dashboard')); } - }