diff --git a/core/API/Proxy.php b/core/API/Proxy.php index bceac4556b7f5262adda56923b502276b061594a..f843bdb5fc42e5072a0f6f32f01fddb2f826ab0b 100644 --- a/core/API/Proxy.php +++ b/core/API/Proxy.php @@ -28,7 +28,7 @@ use ReflectionMethod; * * @package Piwik * @subpackage Piwik_API - * @method \Piwik\API\Proxy getInstance() + * @static \Piwik\API\Proxy getInstance() */ class Proxy extends Singleton { @@ -265,6 +265,19 @@ class Proxy extends Singleton return str_replace(array('\\Piwik\\Plugins\\', '\\API'), '', $className); } + public function isExistingApiAction($pluginName, $apiAction) + { + $namespacedApiClassName = "\\Piwik\\Plugins\\$pluginName\\API"; + $api = $namespacedApiClassName::getInstance(); + + return method_exists($api, $apiAction); + } + + public function buildApiActionName($pluginName, $apiAction) + { + return sprintf("%s.%s", $pluginName, $apiAction); + } + /** * Sets whether to hide '@ignore'd functions from method metadata or not. * diff --git a/core/API/Request.php b/core/API/Request.php index 93673bc1b1976b9c97ee516ff087fd3c86130fa0..219bcb2c2d42afcba07de86ed241bef790a20f3f 100644 --- a/core/API/Request.php +++ b/core/API/Request.php @@ -263,6 +263,21 @@ class Request return $GET; } + /** + * Returns URL for this report w/o any filter parameters. + * + * @param string $module + * @param string $action + * @param array $queryParams + * + * @return string + */ + public static function getBaseReportUrl($module, $action, $queryParams = array()) + { + $params = array_merge($queryParams, array('module' => $module, 'action' => $action)); + return Request::getCurrentUrlWithoutGenericFilters($params); + } + /** * Returns the current URL without generic filter query parameters. * diff --git a/core/Common.php b/core/Common.php index 8b5409469c8975719221283a69a3663763567bc8..2d7a95e0b6f04ad4a8b551cc4bb672d1a8316170 100644 --- a/core/Common.php +++ b/core/Common.php @@ -597,6 +597,19 @@ class Common return json_decode($json, $assoc); } + /** + * Returns the list of parent classes for the given class. + * + * @param string $klass A class name. + * @return string[] The list of parent classes in order from highest ancestor to the descended class. + */ + public static function getClassLineage($klass) + { + $klasses = array_merge(array($klass), array_values(class_parents($klass, $autoload = false))); + + return array_reverse($klasses); + } + /* * DataFiles */ diff --git a/core/FrontController.php b/core/FrontController.php index 0c43174fd78051c693e675dadb1469ff46876b63..f00e8772e9ea8648f97ff2e18afaf9ed5b3d208a 100644 --- a/core/FrontController.php +++ b/core/FrontController.php @@ -26,7 +26,7 @@ use Piwik\Session; * * @package Piwik * @subpackage FrontController - * @method \Piwik\FrontController getInstance() + * @static \Piwik\FrontController getInstance() */ class FrontController extends Singleton { diff --git a/core/Plugin/API.php b/core/Plugin/API.php index e10baf788878da70ea8ac5972543d98501006ad9..bb7e67cd7ec68bc549cb01c814f92c24a0f41c1f 100644 --- a/core/Plugin/API.php +++ b/core/Plugin/API.php @@ -15,4 +15,5 @@ use Piwik\Singleton; abstract class API extends Singleton { + } diff --git a/core/Plugin/Controller.php b/core/Plugin/Controller.php index f16d4c694b0bbe26e77f461d9df7e3c7569b304f..b1be2080b1e954d187b945f68c0c3bba82a90cc1 100644 --- a/core/Plugin/Controller.php +++ b/core/Plugin/Controller.php @@ -32,7 +32,7 @@ use Piwik\SettingsPiwik; use Piwik\Site; use Piwik\Url; use Piwik\View; -use Piwik\ViewDataTable; +use Piwik\ViewDataTable as ViewDataTableBuilder; /** * Parent class of all plugins Controllers (located in /plugins/PluginName/Controller.php @@ -179,9 +179,9 @@ abstract class Controller */ protected function getLastUnitGraph($currentModuleName, $currentControllerAction, $apiMethod) { - $view = ViewDataTable::factory( + $view = ViewDataTableBuilder::factory( 'graphEvolution', $apiMethod, $currentModuleName . '.' . $currentControllerAction, $forceDefault = true); - $view->show_goals = false; + $view->config->show_goals = false; return $view; } @@ -222,13 +222,16 @@ abstract class Controller // initialize the graph and load the data $view = $this->getLastUnitGraph($currentModuleName, $currentControllerAction, $apiMethod); - $view->columns_to_display = $columnsToDisplay; - $view->visualization_properties->selectable_columns = - array_merge($view->visualization_properties->selectable_columns ? : array(), $selectableColumns); - $view->translations += $translations; + $view->config->columns_to_display = $columnsToDisplay; + + if (property_exists($view->config, 'selectable_columns')) { + $view->config->selectable_columns = array_merge($view->config->selectable_columns ? : array(), $selectableColumns); + } + + $view->config->translations += $translations; if ($reportDocumentation) { - $view->documentation = $reportDocumentation; + $view->config->documentation = $reportDocumentation; } return $view; diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index b0e5e9153aea7b5a7ec28d436a3e80d9a377f43d..1b536f8d8cc8d26181054ba599f522983671fda4 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -25,7 +25,7 @@ require_once PIWIK_INCLUDE_PATH . '/core/EventDispatcher.php'; /** * Plugin manager * - * @method \Piwik\Plugin\Manager getInstance() + * @static \Piwik\Plugin\Manager getInstance() * @package Piwik * @subpackage Manager */ diff --git a/core/Plugin/ViewDataTable.php b/core/Plugin/ViewDataTable.php new file mode 100644 index 0000000000000000000000000000000000000000..933e4cdbe85c07ea2c96d35f1411ca6643829ee9 --- /dev/null +++ b/core/Plugin/ViewDataTable.php @@ -0,0 +1,481 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik + * @package Piwik + */ +namespace Piwik\Plugin; + +use Piwik\API\Request; +use Piwik\Common; +use Piwik\DataTable; +use Piwik\Date; +use Piwik\Log; +use Piwik\MetricsFormatter; +use Piwik\Period; +use Piwik\Period\Range; +use Piwik\Piwik; +use Piwik\Plugins\PrivacyManager\PrivacyManager; +use Piwik\Site; +use Piwik\View; +use Piwik\View\ViewInterface; +use Piwik\ViewDataTable\Config as VizConfig; +use Piwik\ViewDataTable\Request as ViewDataTableRequest; +use Piwik\ViewDataTable\RequestConfig as VizRequest; + +/** + * This class is used to load (from the API) and customize the output of a given DataTable. + * The main() method will create an object implementing ViewInterface + * You can customize the dataTable using the disable* methods. + * + * You can also customize the dataTable rendering using row metadata: + * - 'html_label_prefix': If this metadata is present on a row, it's contents will be prepended + * the label in the HTML output. + * - 'html_label_suffix': If this metadata is present on a row, it's contents will be appended + * after the label in the HTML output. + * + * Example: + * In the Controller of the plugin VisitorInterest + * <pre> + * function getNumberOfVisitsPerVisitDuration( $fetch = false) + * { + * $view = ViewDataTable::factory( 'cloud' ); + * $view->init( $this->pluginName, __FUNCTION__, 'VisitorInterest.getNumberOfVisitsPerVisitDuration' ); + * $view->setColumnsToDisplay( array('label','nb_visits') ); + * $view->disableSort(); + * $view->disableExcludeLowPopulation(); + * $view->disableOffsetInformation(); + * + * return $this->renderView($view, $fetch); + * } + * </pre> + * + * @see factory() for all the available output (cloud tags, html table, pie chart, vertical bar chart) + * @package Piwik + * @subpackage ViewDataTable + * + * @api + */ +abstract class ViewDataTable implements ViewInterface +{ + const ID = ''; + const CONFIGURE_FOOTER_ICONS_EVENT = 'Visualization.configureFooterIcons'; + + /** + * DataTable loaded from the API for this ViewDataTable. + * + * @var DataTable + */ + protected $dataTable = null; + + /** + * @var \Piwik\ViewDataTable\Config + */ + public $config; + + /** + * @var \Piwik\ViewDataTable\RequestConfig + */ + public $requestConfig; + + /** + * @var ViewDataTableRequest + */ + protected $request; + + /** + * Default constructor. + */ + public function __construct($controllerAction, $apiMethodToRequestDataTable) + { + list($controllerName, $controllerAction) = explode('.', $controllerAction); + + $this->requestConfig = static::getDefaultRequestConfig(); + $this->config = static::getDefaultConfig(); + $this->config->subtable_controller_action = $controllerAction; + $this->config->setController($controllerName, $controllerAction); + + $this->request = new ViewDataTableRequest($this->requestConfig); + + $this->requestConfig->idSubtable = Common::getRequestVar('idSubtable', false, 'int'); + $this->config->self_url = Request::getBaseReportUrl($controllerName, $controllerAction); + + $this->requestConfig->apiMethodToRequestDataTable = $apiMethodToRequestDataTable; + + /** + * This event is triggered to gather the report display properties for each available report. If you define + * your own report, you want to subscribe to this event to define how your report shall be displayed in the + * Piwik UI. + * + * public function configureViewDataTable(ViewDataTable $view) + * { + * switch ($view->requestConfig->apiMethodToRequestDataTable) { + * case 'VisitTime.getVisitInformationPerServerTime': + * $view->config->enable_sort = true; + * $view->requestConfig->filter_limit = 10; + * break; + * } + * } + */ + Piwik::postEvent('ViewDataTable.configure', array($this)); + + $this->config->show_footer_icons = (false == $this->requestConfig->idSubtable); + + // the exclude low population threshold value is sometimes obtained by requesting data. + // to avoid issuing unecessary requests when display properties are determined by metadata, + // we allow it to be a closure. + if (isset($this->requestConfig->filter_excludelowpop_value) + && $this->requestConfig->filter_excludelowpop_value instanceof \Closure + ) { + $function = $this->requestConfig->filter_excludelowpop_value; + $this->requestConfig->filter_excludelowpop_value = $function(); + } + + $this->overrideViewPropertiesWithQueryParams(); + } + + public static function getDefaultConfig() + { + return new VizConfig(); + } + + public static function getDefaultRequestConfig() + { + return new VizRequest(); + } + + protected function loadDataTableFromAPI() + { + if (!is_null($this->dataTable)) { + // data table is already there + // this happens when setDataTable has been used + return $this->dataTable; + } + + $this->dataTable = $this->request->loadDataTableFromAPI(); + + return $this->dataTable; + } + + /** + * Returns the viewDataTable ID for this DataTable visualization. Derived classes + * should declare a const ID field with the viewDataTable ID. + * + * @throws \Exception + * @return string + */ + public static function getViewDataTableId() + { + $id = static::ID; + + if (empty($id)) { + $message = sprintf('ViewDataTable %s does not define an ID. Set the ID constant to fix this issue', get_called_class()); + throw new \Exception($message); + } + + return $id; + } + + public function isViewDataTableId($viewDataTableId) + { + $myIds = static::getIdsWithInheritance(get_called_class()); + + return in_array($viewDataTableId, $myIds); + } + + /** + * Returns the DataTable loaded from the API + * + * @return DataTable + * @throws \Exception if not yet defined + */ + public function getDataTable() + { + if (is_null($this->dataTable)) { + throw new \Exception("The DataTable object has not yet been created"); + } + + return $this->dataTable; + } + + /** + * To prevent calling an API multiple times, the DataTable can be set directly. + * It won't be loaded again from the API in this case + * + * @param $dataTable + * @return void $dataTable DataTable + */ + public function setDataTable($dataTable) + { + $this->dataTable = $dataTable; + } + + /** + * Returns the viewDataTable IDs of a visualization's class lineage. + * + * @see self::getVisualizationClassLineage + * + * @param string $klass The visualization class. + * + * @return array + */ + public static function getIdsWithInheritance($klass) + { + $klasses = Common::getClassLineage($klass); + + $result = array(); + foreach ($klasses as $klass) { + if ('Piwik\\Plugin\\ViewDataTable' != $klass + && 'Piwik\\Plugin\\Visualization' != $klass) { + $result[] = $klass::getViewDataTableId(); + } + } + + return $result; + } + + /** + * Checks that the API returned a normal DataTable (as opposed to DataTable\Map) + * @throws \Exception + * @return void + */ + protected function checkStandardDataTable() + { + Piwik::checkObjectTypeIs($this->dataTable, array('\Piwik\DataTable')); + } + + /** + * Convenience function. Calls main() & renders the view that gets built. + * + * @return string The result of rendering. + */ + public function render() + { + $view = $this->buildView(); + return $view->render(); + } + + abstract protected function buildView(); + + protected function getDefaultFooterIconsToShow() + { + $result = array(); + + // add normal view icons (eg, normal table, all columns, goals) + $normalViewIcons = array( + 'class' => 'tableAllColumnsSwitch', + 'buttons' => array(), + ); + + if ($this->config->show_table) { + $normalViewIcons['buttons'][] = array( + 'id' => 'table', + 'title' => Piwik::translate('General_DisplaySimpleTable'), + 'icon' => 'plugins/Zeitgeist/images/table.png', + ); + } + + if ($this->config->show_table_all_columns) { + $normalViewIcons['buttons'][] = array( + 'id' => 'tableAllColumns', + 'title' => Piwik::translate('General_DisplayTableWithMoreMetrics'), + 'icon' => 'plugins/Zeitgeist/images/table_more.png' + ); + } + + if ($this->config->show_goals) { + if (Common::getRequestVar('idGoal', false) == 'ecommerceOrder') { + $icon = 'plugins/Zeitgeist/images/ecommerceOrder.gif'; + } else { + $icon = 'plugins/Zeitgeist/images/goal.png'; + } + + $normalViewIcons['buttons'][] = array( + 'id' => 'tableGoals', + 'title' => Piwik::translate('General_DisplayTableWithGoalMetrics'), + 'icon' => $icon + ); + } + + if ($this->config->show_ecommerce) { + $normalViewIcons['buttons'][] = array( + 'id' => 'ecommerceOrder', + 'title' => Piwik::translate('General_EcommerceOrders'), + 'icon' => 'plugins/Zeitgeist/images/ecommerceOrder.gif', + 'text' => Piwik::translate('General_EcommerceOrders') + ); + + $normalViewIcons['buttons'][] = array( + 'id' => 'ecommerceAbandonedCart', + 'title' => Piwik::translate('General_AbandonedCarts'), + 'icon' => 'plugins/Zeitgeist/images/ecommerceAbandonedCart.gif', + 'text' => Piwik::translate('General_AbandonedCarts') + ); + } + + if (!empty($normalViewIcons['buttons'])) { + $result[] = $normalViewIcons; + } + + // add graph views + $graphViewIcons = array( + 'class' => 'tableGraphViews tableGraphCollapsed', + 'buttons' => array(), + ); + + if ($this->config->show_all_views_icons) { + if ($this->config->show_bar_chart) { + $graphViewIcons['buttons'][] = array( + 'id' => 'graphVerticalBar', + 'title' => Piwik::translate('General_VBarGraph'), + 'icon' => 'plugins/Zeitgeist/images/chart_bar.png' + ); + } + + if ($this->config->show_pie_chart) { + $graphViewIcons['buttons'][] = array( + 'id' => 'graphPie', + 'title' => Piwik::translate('General_Piechart'), + 'icon' => 'plugins/Zeitgeist/images/chart_pie.png' + ); + } + + if ($this->config->show_tag_cloud) { + $graphViewIcons['buttons'][] = array( + 'id' => 'cloud', + 'title' => Piwik::translate('General_TagCloud'), + 'icon' => 'plugins/Zeitgeist/images/tagcloud.png' + ); + } + + if ($this->config->show_non_core_visualizations) { + $nonCoreVisualizations = \Piwik\ViewDataTable::getNonCoreVisualizations(); + $nonCoreVisualizationInfo = static::getVisualizationInfoFor($nonCoreVisualizations); + + foreach ($nonCoreVisualizationInfo as $format => $info) { + $graphViewIcons['buttons'][] = array( + 'id' => $format, + 'title' => Piwik::translate($info['title']), + 'icon' => $info['table_icon'] + ); + } + } + } + + if (!empty($graphViewIcons['buttons'])) { + $result[] = $graphViewIcons; + } + + /** + * This event is called when determining the default set of footer icons to display + * below a report. + * + * Plugins can use this event to modify the default set of footer icons. You can + * add new icons or remove existing ones. + * + * $result must have the following format: + * + * ``` + * array( + * array( // footer icon group 1 + * 'class' => 'footerIconGroup1CssClass', + * 'buttons' => array( + * 'id' => 'myid', + * 'title' => 'My Tooltip', + * 'icon' => 'path/to/my/icon.png' + * ) + * ), + * array( // footer icon group 2 + * 'class' => 'footerIconGroup2CssClass', + * 'buttons' => array(...) + * ), + * ... + * ) + * ``` + */ + Piwik::postEvent(self::CONFIGURE_FOOTER_ICONS_EVENT, array(&$result, $viewDataTable = $this)); + + return $result; + } + + public function getDefaultDataTableCssClass() + { + return 'dataTableViz' . Piwik::getUnnamespacedClassName(get_class($this)); + } + + /** + * Returns an array mapping visualization IDs with information necessary for adding the + * visualizations to the footer of DataTable views. + * + * @param array $visualizations An array mapping visualization IDs w/ their associated classes. + * @return array + */ + public static function getVisualizationInfoFor($visualizations) + { + $result = array(); + + foreach ($visualizations as $vizId => $vizClass) { + $result[$vizId] = array('table_icon' => $vizClass::FOOTER_ICON, 'title' => $vizClass::FOOTER_ICON_TITLE); + } + + return $result; + } + + /** + * Returns the list of view properties that can be overriden by query parameters. + * + * @return array + */ + public function getOverridableProperties() + { + return array_merge($this->config->overridableProperties, $this->requestConfig->overridableProperties); + } + + private function overrideViewPropertiesWithQueryParams() + { + $properties = $this->getOverridableProperties(); + + foreach ($properties as $name) { + if (property_exists($this->requestConfig, $name)) { + $this->requestConfig->name = $this->getPropertyFromQueryParam($name, $this->requestConfig->$name); + } elseif (property_exists($this->config, $name)) { + $this->config->name = $this->getPropertyFromQueryParam($name, $this->config->$name); + } + } + + // handle special 'columns' query parameter + $columns = Common::getRequestVar('columns', false); + + if (false !== $columns) { + $this->config->columns_to_display = Piwik::getArrayFromApiParameter($columns); + array_unshift($this->config->columns_to_display, 'label'); + } + } + + protected function getPropertyFromQueryParam($name, $defaultValue) + { + $type = is_numeric($defaultValue) ? 'int' : null; + return Common::getRequestVar($name, $defaultValue, $type); + } + + public function isRequestingSingleDataTable() + { + $requestArray = $this->request->getRequestArray() + $_GET + $_POST; + $date = Common::getRequestVar('date', null, 'string', $requestArray); + $period = Common::getRequestVar('period', null, 'string', $requestArray); + $idSite = Common::getRequestVar('idSite', null, 'string', $requestArray); + + if (Period::isMultiplePeriod($date, $period) + || strpos($idSite, ',') !== false + || $idSite == 'all' + ) { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/core/Plugin/Visualization.php b/core/Plugin/Visualization.php new file mode 100644 index 0000000000000000000000000000000000000000..d57125b009159f5ddc22830b1f67b087aa4a37f4 --- /dev/null +++ b/core/Plugin/Visualization.php @@ -0,0 +1,463 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik + * @package Piwik + */ + +namespace Piwik\Plugin; + +use Piwik\Common; +use Piwik\DataTable; +use Piwik\Date; +use Piwik\Log; +use Piwik\Metrics; +use Piwik\MetricsFormatter; +use Piwik\NoAccessException; +use Piwik\Option; +use Piwik\Period; +use Piwik\Period\Range; +use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; +use Piwik\Plugins\PrivacyManager\PrivacyManager; +use Piwik\Site; +use Piwik\View; + +/** + * Base class for all DataTable visualizations. Different visualizations are used to + * handle different values of the viewDataTable query parameter. Each one will display + * DataTable data in a different way. + * + * TODO: must be more in depth + */ +class Visualization extends ViewDataTable +{ + const TEMPLATE_FILE = ''; + + private $templateVars = array(); + + final public function __construct($controllerAction, $apiMethodToRequestDataTable) + { + $templateFile = static::TEMPLATE_FILE; + + if (empty($templateFile)) { + throw new \Exception('You have not defined a constant named TEMPLATE_FILE in your visualization class.'); + } + + parent::__construct($controllerAction, $apiMethodToRequestDataTable); + } + + protected function init() + { + // do your init stuff here, do not overwrite constructor + } + + protected function buildView() + { + $this->overrideSomeConfigPropertiesIfNeeded(); + + try { + + $this->beforeLoadDataTable(); + + $this->loadDataTableFromAPI(); + $this->postDataTableLoadedFromAPI(); + + $requestPropertiesAfterLoadDataTable = $this->requestConfig->getProperties(); + + $this->applyFilters(); + $this->afterAllFilteresAreApplied(); + $this->beforeRender(); + + $this->logMessageIfRequestPropertiesHaveChanged($requestPropertiesAfterLoadDataTable); + + } catch (NoAccessException $e) { + throw $e; + } catch (\Exception $e) { + Log::warning("Failed to get data from API: " . $e->getMessage()); + + $loadingError = array('message' => $e->getMessage()); + } + + $view = new View("@CoreHome/_dataTable"); + + if (!empty($loadingError)) { + $view->error = $loadingError; + } + + $view->assign($this->templateVars); + $view->visualization = $this; + $view->visualizationTemplate = static::TEMPLATE_FILE; + $view->visualizationCssClass = $this->getDefaultDataTableCssClass(); + + if (null === $this->dataTable) { + $view->dataTable = null; + } else { + $view->dataTableHasNoData = !$this->isThereDataToDisplay(); + $view->dataTable = $this->dataTable; + + // if it's likely that the report data for this data table has been purged, + // set whether we should display a message to that effect. + $view->showReportDataWasPurgedMessage = $this->hasReportBeenPurged(); + $view->deleteReportsOlderThan = Option::get('delete_reports_older_than'); + } + + $view->idSubtable = $this->requestConfig->idSubtable; + $view->clientSideParameters = $this->getClientSideParametersToSet(); + $view->clientSideProperties = $this->getClientSidePropertiesToSet(); + $view->properties = array_merge($this->requestConfig->getProperties(), $this->config->getProperties()); + $view->footerIcons = $this->config->footer_icons; + $view->isWidget = Common::getRequestVar('widget', 0, 'int'); + + return $view; + } + + private function overrideSomeConfigPropertiesIfNeeded() + { + if (empty($this->config->footer_icons)) { + $this->config->footer_icons = $this->getDefaultFooterIconsToShow(); + } + + if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated('Goals')) { + $this->config->show_goals = false; + } + } + + public function assignTemplateVar($vars, $value = null) + { + if (is_string($vars)) { + $this->templateVars[$vars] = $value; + } elseif (is_array($vars)) { + foreach ($vars as $key => $value) { + $this->templateVars[$key] = $value; + } + } + } + + protected function isThereDataToDisplay() + { + return true; + } + + /** + * Hook called after the dataTable has been loaded from the API + * Can be used to add, delete or modify the data freshly loaded + * + * @return bool + */ + private function postDataTableLoadedFromAPI() + { + $columns = $this->dataTable->getColumns(); + $hasNbVisits = in_array('nb_visits', $columns); + $hasNbUniqVisitors = in_array('nb_uniq_visitors', $columns); + + // default columns_to_display to label, nb_uniq_visitors/nb_visits if those columns exist in the + // dataset. otherwise, default to all columns in dataset. + if (empty($this->config->columns_to_display)) { + $this->config->setDefaultColumnsToDisplay($columns, $hasNbVisits, $hasNbUniqVisitors); + } + + if (!empty($this->dataTable)) { + $this->removeEmptyColumnsFromDisplay(); + } + + if (empty($this->requestConfig->filter_sort_column)) { + $this->requestConfig->setDefaultSort($this->config->columns_to_display, $hasNbUniqVisitors); + } + + // deal w/ table metadata + if ($this->dataTable instanceof DataTable) { + $this->config->metadata = $this->dataTable->getAllTableMetadata(); + + if (isset($this->config->metadata[DataTable::ARCHIVED_DATE_METADATA_NAME])) { + $this->config->report_last_updated_message = $this->makePrettyArchivedOnText(); + } + } + } + + private function applyFilters() + { + list($priorityFilters, $otherFilters) = $this->config->getFiltersToRun(); + + // First, filters that delete rows + foreach ($priorityFilters as $filter) { + $this->dataTable->filter($filter[0], $filter[1]); + } + + $this->beforeGenericFiltersAreAppliedToLoadedDataTable(); + + if (!$this->config->areGenericFiltersDisabled()) { + $this->applyGenericFilters(); + } + + $this->afterGenericFiltersAreAppliedToLoadedDataTable(); + + // queue other filters so they can be applied later if queued filters are disabled + foreach ($otherFilters as $filter) { + $this->dataTable->queueFilter($filter[0], $filter[1]); + } + + // Finally, apply datatable filters that were queued (should be 'presentation' filters that + // do not affect the number of rows) + if (!$this->config->areQueuedFiltersDisabled()) { + $this->dataTable->applyQueuedFilters(); + } + } + + private function removeEmptyColumnsFromDisplay() + { + if ($this->dataTable instanceof DataTable\Map) { + $emptyColumns = $this->dataTable->getMetadataIntersectArray(DataTable::EMPTY_COLUMNS_METADATA_NAME); + } else { + $emptyColumns = $this->dataTable->getMetadata(DataTable::EMPTY_COLUMNS_METADATA_NAME); + } + + if (is_array($emptyColumns)) { + foreach ($emptyColumns as $emptyColumn) { + $key = array_search($emptyColumn, $this->config->columns_to_display); + if ($key !== false) { + unset($this->config->columns_to_display[$key]); + } + } + + $this->config->columns_to_display = array_values($this->config->columns_to_display); + } + } + + /** + * Returns prettified and translated text that describes when a report was last updated. + * + * @return string + */ + private function makePrettyArchivedOnText() + { + $dateText = $this->config->metadata[DataTable::ARCHIVED_DATE_METADATA_NAME]; + $date = Date::factory($dateText); + $today = mktime(0, 0, 0); + + if ($date->getTimestamp() > $today) { + + $elapsedSeconds = time() - $date->getTimestamp(); + $timeAgo = MetricsFormatter::getPrettyTimeFromSeconds($elapsedSeconds); + + return Piwik::translate('CoreHome_ReportGeneratedXAgo', $timeAgo); + } + + $prettyDate = $date->getLocalized("%longYear%, %longMonth% %day%") . $date->toString('S'); + + return Piwik::translate('CoreHome_ReportGeneratedOn', $prettyDate); + } + + /** + * Returns true if it is likely that the data for this report has been purged and if the + * user should be told about that. + * + * In order for this function to return true, the following must also be true: + * - The data table for this report must either be empty or not have been fetched. + * - The period of this report is not a multiple period. + * - The date of this report must be older than the delete_reports_older_than config option. + * @return bool + */ + private function hasReportBeenPurged() + { + if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated('PrivacyManager')) { + return false; + } + + return PrivacyManager::hasReportBeenPurged($this->dataTable); + } + + /** + * Returns array of properties that should be visible to client side JavaScript. The data + * will be available in the data-props HTML attribute of the .dataTable div. + * + * @return array Maps property names w/ property values. + */ + private function getClientSidePropertiesToSet() + { + $result = array(); + + foreach ($this->config->clientSideProperties as $name) { + if (property_exists($this->requestConfig, $name)) { + $result[$name] = $this->getIntIfValueIsBool($this->requestConfig->$name); + } else if (property_exists($this->config, $name)) { + $result[$name] = $this->getIntIfValueIsBool($this->config->$name); + } + } + + return $result; + } + + private function getIntIfValueIsBool($value) + { + return is_bool($value) ? (int)$value : $value; + } + + /** + * This functions reads the customization values for the DataTable and returns an array (name,value) to be printed in Javascript. + * This array defines things such as: + * - name of the module & action to call to request data for this table + * - optional filters information, eg. filter_limit and filter_offset + * - etc. + * + * The values are loaded: + * - from the generic filters that are applied by default @see Piwik_API_DataTableGenericFilter.php::getGenericFiltersInformation() + * - from the values already available in the GET array + * - from the values set using methods from this class (eg. setSearchPattern(), setLimit(), etc.) + * + * @return array eg. array('show_offset_information' => 0, 'show_... + */ + protected function getClientSideParametersToSet() + { + // build javascript variables to set + $javascriptVariablesToSet = array(); + + foreach ($this->config->custom_parameters as $name => $value) { + $javascriptVariablesToSet[$name] = $value; + } + + foreach ($_GET as $name => $value) { + try { + $requestValue = Common::getRequestVar($name); + } catch (\Exception $e) { + $requestValue = ''; + } + $javascriptVariablesToSet[$name] = $requestValue; + } + + foreach ($this->requestConfig->clientSideParameters as $name) { + if (isset($javascriptVariablesToSet[$name])) { + continue; + } + + $valueToConvert = false; + + if (property_exists($this->requestConfig, $name)) { + $valueToConvert = $this->requestConfig->$name; + } else if (property_exists($this->config, $name)) { + $valueToConvert = $this->config->$name; + } + + if (false !== $valueToConvert) { + $javascriptVariablesToSet[$name] = $this->getIntIfValueIsBool($valueToConvert); + } + } + + if ($this->dataTable instanceof DataTable) { + // we override the filter_sort_column with the column used for sorting, + // which can be different from the one specified (eg. if the column doesn't exist) + $javascriptVariablesToSet['filter_sort_column'] = $this->dataTable->getSortedByColumnName(); + // datatable can return "2" but we want to write "nb_visits" in the js + if (isset(Metrics::$mappingFromIdToName[$javascriptVariablesToSet['filter_sort_column']])) { + $javascriptVariablesToSet['filter_sort_column'] = Metrics::$mappingFromIdToName[$javascriptVariablesToSet['filter_sort_column']]; + } + } + + $javascriptVariablesToSet['module'] = $this->config->controllerName; + $javascriptVariablesToSet['action'] = $this->config->controllerAction; + if (!isset($javascriptVariablesToSet['viewDataTable'])) { + $javascriptVariablesToSet['viewDataTable'] = static::getViewDataTableId(); + } + + if ($this->dataTable && + // Set doesn't have the method + !($this->dataTable instanceof DataTable\Map) + && empty($javascriptVariablesToSet['totalRows']) + ) { + $javascriptVariablesToSet['totalRows'] = $this->dataTable->getRowsCountBeforeLimitFilter(); + } + + $deleteFromJavascriptVariables = array( + 'filter_excludelowpop', + 'filter_excludelowpop_value', + ); + foreach ($deleteFromJavascriptVariables as $name) { + if (isset($javascriptVariablesToSet[$name])) { + unset($javascriptVariablesToSet[$name]); + } + } + + $rawSegment = \Piwik\API\Request::getRawSegmentFromRequest(); + if (!empty($rawSegment)) { + $javascriptVariablesToSet['segment'] = $rawSegment; + } + + return $javascriptVariablesToSet; + } + + public function beforeRender() + { + // make sure config properties have a specific value because it can be changed by a report or by request params + // like $this->config->showFooterColumns = true; + } + + public function beforeLoadDataTable() + { + // change request + // like defining $this->requestConfig->filter_column + } + + public function beforeGenericFiltersAreAppliedToLoadedDataTable() + { + + } + + public function afterGenericFiltersAreAppliedToLoadedDataTable() + { + + } + + public function afterAllFilteresAreApplied() + { + // filter and format requested data here + // $dataTable ... + + // $this->generator = new GeneratorFoo($dataTable); + } + + /** + * Second, generic filters (Sort, Limit, Replace Column Names, etc.) + */ + private function applyGenericFilters() + { + $requestArray = $this->request->getRequestArray(); + $request = \Piwik\API\Request::getRequestArrayFromString($requestArray); + + if (false === $this->config->enable_sort) { + $request['filter_sort_column'] = ''; + $request['filter_sort_order'] = ''; + } + + $genericFilter = new \Piwik\API\DataTableGenericFilter($request); + $genericFilter->filter($this->dataTable); + } + + private function logMessageIfRequestPropertiesHaveChanged(array $requestPropertiesBefore) + { + $requestProperties = $this->requestConfig->getProperties(); + + $diff = array_diff_assoc($requestProperties, $requestPropertiesBefore); + + if (empty($diff)) { + return; + } + + $details = array( + 'changedProperties' => $diff, + 'apiMethod' => $this->requestConfig->apiMethodToRequestDataTable, + 'controller' => $this->config->controllerName . '.' . $this->config->controllerAction, + 'viewDataTable' => static::getViewDataTableId() + ); + + $message = 'Some ViewDataTable::requestConfig properties have changed after requesting the data table. ' + . 'That means the changed values had probably no effect. For instance in beforeRender() hook. ' + . 'Probably a bug? Details:' + . print_r($details, 1); + + Log::warning($message); + } +} \ No newline at end of file diff --git a/core/ViewDataTable.php b/core/ViewDataTable.php index 9ca220201c0fcf72f93003cf487e7c45a465f187..473be55c92657999f1411c7166e74eda115612e2 100644 --- a/core/ViewDataTable.php +++ b/core/ViewDataTable.php @@ -10,15 +10,10 @@ */ namespace Piwik; +use Piwik\API\Proxy; use Piwik\API\Request; -use Piwik\DataTable; -use Piwik\Period; -use Piwik\Period\Range; use Piwik\Plugins\API\API; -use Piwik\ViewDataTable\Visualization; -use Piwik\ViewDataTable\VisualizationPropertiesProxy; -use Piwik\Visualization\Config as VizConfig; -use Piwik\Visualization\Request as VizRequest; +use Piwik\Plugin\Visualization; /** * This class is used to load (from the API) and customize the output of a given DataTable. @@ -55,185 +50,13 @@ use Piwik\Visualization\Request as VizRequest; */ class ViewDataTable { - const CONFIGURE_VIEW_EVENT = 'Visualization.initView'; - const CONFIGURE_FOOTER_ICONS_EVENT = 'Visualization.configureFooterIcons'; /** - * The class name of the visualization to use. - * - * @var string|null - */ - private $visualizationClass; - - /** - * Cache for getAllReportDisplayProperties result. + * Cache for getDefaultViewTypeForReports result. * * @var array */ - public static $reportPropertiesCache = null; - - /** - * If the current dataTable refers to a subDataTable (eg. keywordsBySearchEngineId for id=X) this variable is set to the Id - * - * @var bool|int - */ - protected $idSubtable = false; - - /** - * DataTable loaded from the API for this ViewDataTable. - * - * @var DataTable - */ - protected $dataTable = null; - - /** - * @see init() - * @var string - */ - protected $currentControllerAction; - - /** - * @see init() - * @var string - */ - protected $currentControllerName; - - /** - * @var null|\Piwik\Visualization\Config - */ - protected $vizConfig; - - /** - * @var null|\Piwik\Visualization\Request - */ - protected $vizRequest; - - /** - * Default constructor. - */ - public function __construct($currentControllerAction, - $apiMethodToRequestDataTable, - $viewProperties = array(), - $visualizationId = null) - { - if (class_exists($visualizationId) - && is_subclass_of($visualizationId, "Piwik\\ViewDataTable\\Visualization") - ) { - $visualizationClass = $visualizationId; - } else { - $visualizationClass = $visualizationId ? Visualization::getClassFromId($visualizationId) : null; - } - - $this->visualizationClass = $visualizationClass; - - list($currentControllerName, $currentControllerAction) = explode('.', $currentControllerAction); - $this->currentControllerName = $currentControllerName; - $this->currentControllerAction = $currentControllerAction; - - $this->vizRequest = new VizRequest(); - $this->vizConfig = new VizConfig(); - $this->vizConfig->visualization_properties = new VisualizationPropertiesProxy($visualizationClass); - $this->vizConfig->subtable_controller_action = $currentControllerAction; - - $this->setDefaultProperties(); - $this->setViewProperties($viewProperties); - - $this->idSubtable = Common::getRequestVar('idSubtable', false, 'int'); - - $this->vizConfig->show_footer_icons = ($this->idSubtable == false); - $this->vizRequest->apiMethodToRequestDataTable = $apiMethodToRequestDataTable; - - $this->vizConfig->report_id = $currentControllerName . '.' . $currentControllerAction; - $this->vizConfig->self_url = $this->getBaseReportUrl($currentControllerName, $currentControllerAction); - - // the exclude low population threshold value is sometimes obtained by requesting data. - // to avoid issuing unecessary requests when display properties are determined by metadata, - // we allow it to be a closure. - if (isset($this->vizRequest->filter_excludelowpop_value) - && $this->vizRequest->filter_excludelowpop_value instanceof \Closure - ) { - $function = $this->vizRequest->filter_excludelowpop_value; - $this->vizRequest->filter_excludelowpop_value = $function(); - } - - $this->overrideViewPropertiesWithQueryParams(); - - $this->loadDocumentation(); - } - - /** - * Returns the API method that will be called to obatin the report data. - * - * @return string e.g. 'Actions.getPageUrls' - */ - public function getReportApiMethod() - { - return $this->vizRequest->apiMethodToRequestDataTable; - } - - /** - * Returns the view's associated visualization class name. - * - * @return string - */ - public function getVisualizationClass() - { - return $this->visualizationClass; - } - - /** - * Gets a view property by reference. - * - * @param string $name A valid view property name. @see Properties for all - * valid view properties. - * @return mixed - * @throws \Exception if the property name is invalid. - */ - public function &__get($name) - { - if (property_exists($this->vizRequest, $name)) { - return $this->vizRequest->$name; - } elseif (property_exists($this->vizConfig, $name)) { - return $this->vizConfig->$name; - } - } - - /** - * Sets a view property. - * - * @param string $name A valid view property name. @see Properties for all - * valid view properties. - * @param mixed $value - * @return mixed Returns $value. - * @throws \Exception if the property name is invalid. - */ - public function __set($name, $value) - { - if (property_exists($this->vizRequest, $name)) { - return $this->vizRequest->$name = $value; - } elseif (property_exists($this->vizConfig, $name)) { - return $this->vizConfig->$name = $value; - } - } - - /** - * Hack to allow property access in Twig (w/ property name checking). - */ - public function __call($name, $arguments) - { - return $this->$name; - } - - /** - * Unique string ID that defines the format of the dataTable, eg. "pieChart", "table", etc. - * - * @return string - */ - public function getViewDataTableId() - { - $klass = $this->visualizationClass; - return $klass::getViewDataTableId($this); - } + private static $defaultViewTypes = null; /** * Returns a Piwik_ViewDataTable_* object. @@ -247,762 +70,96 @@ class ViewDataTable * @param string|bool $controllerAction * @param bool $forceDefault * - * @return ViewDataTable - */ - static public function factory($defaultType = null, $apiAction = false, $controllerAction = false, $forceDefault = false) - { - if ($controllerAction === false) { - $controllerAction = $apiAction; - } - - $defaultProperties = self::getDefaultPropertiesForReport($apiAction); - if (!empty($defaultProperties['default_view_type']) - && !$forceDefault - ) { - $defaultType = $defaultProperties['default_view_type']; - } - - $type = Common::getRequestVar('viewDataTable', $defaultType ? : 'table', 'string'); - - if ($type == 'sparkline') { - $result = new ViewDataTable\Sparkline($controllerAction, $apiAction, $defaultProperties); - } else { - $result = new ViewDataTable($controllerAction, $apiAction, $defaultProperties, $type); - } - - return $result; - } - - /** - * Returns the list of view properties that should be sent with the HTML response - * as JSON. These properties are visible to the UI JavaScript, but are not passed - * with every request. - * - * @return array - */ - public function getClientSideConfigProperties() - { - return $this->getPropertyNameListWithMetaProperty(VizConfig::$clientSideProperties, __FUNCTION__); - } - - /** - * Returns the list of view properties that should be sent with the HTML response - * and resent by the UI JavaScript in every subsequent AJAX request. - * - * @return array - */ - public function getClientSideRequestParameters() - { - return $this->getPropertyNameListWithMetaProperty(VizRequest::$clientSideParameters, __FUNCTION__); - } - - /** - * Returns the list of view properties that can be overriden by query parameters. - * - * @return array - */ - public function getOverridableProperties() - { - $params = array_merge(VizConfig::$overridableProperties, VizRequest::$overridableProperties); - - return $this->getPropertyNameListWithMetaProperty($params, __FUNCTION__); - } - - public function getCurrentControllerAction() - { - return $this->currentControllerAction; - } - - public function getCurrentControllerName() - { - return $this->currentControllerName; - } - - /** - * Returns the DataTable loaded from the API - * - * @return DataTable - * @throws \Exception if not yet defined - */ - public function getDataTable() - { - if (is_null($this->dataTable)) { - throw new \Exception("The DataTable object has not yet been created"); - } - return $this->dataTable; - } - - /** - * To prevent calling an API multiple times, the DataTable can be set directly. - * It won't be loaded again from the API in this case - * - * @param $dataTable - * @return void $dataTable DataTable - */ - public function setDataTable($dataTable) - { - $this->dataTable = $dataTable; - } - - /** - * Returns the defaut view properties for a report, if any. - * - * Plugins can associate callbacks with the Visualization.getReportDisplayProperties - * event to set the default properties of reports. - * - * @param string $apiAction - * @return array - */ - private static function getDefaultPropertiesForReport($apiAction) - { - $reportDisplayProperties = self::getAllReportDisplayProperties(); - return isset($reportDisplayProperties[$apiAction]) ? $reportDisplayProperties[$apiAction] : array(); - } - - /** - * Returns the list of display properties for all available reports. - * - * @return array - */ - private static function getAllReportDisplayProperties() - { - if (self::$reportPropertiesCache === null) { - self::$reportPropertiesCache = array(); - /** - * This event is triggered to gather the report display properties for each available report. If you define - * your own report, you want to subscribe to this event to define how your report shall be displayed in the - * Piwik UI. - * - * Example: - * ``` - * public function getReportDisplayProperties(&$properties) - * { - * $properties['Provider.getProvider'] = array( - * 'translations' => array('label' => Piwik::translate('Provider_ColumnProvider')), - * 'filter_limit' => 5 - * ) - * } - * ``` - */ - Piwik::postEvent('Visualization.getReportDisplayProperties', array(&self::$reportPropertiesCache)); - } - - return self::$reportPropertiesCache; - } - - /** - * Sets a view property by name. This function handles special view properties - * like 'translations' & 'related_reports' that store arrays. - * - * @param string $name - * @param mixed $value For array properties, $value can be a comma separated string. - * @throws \Exception - */ - private function setViewProperty($name, $value) - { - if (isset($this->vizRequest->$name) - && is_array($this->vizRequest->$name) - && is_string($value) - ) { - $value = Piwik::getArrayFromApiParameter($value); - } - - if (isset($this->vizConfig->$name) - && is_array($this->vizConfig->$name) - && is_string($value) - ) { - $value = Piwik::getArrayFromApiParameter($value); - } - - if ($name == 'translations' - || $name == 'filters' - ) { - $this->vizConfig->$name = array_merge($this->vizConfig->$name, $value); - } else if ($name == 'related_reports') { // TODO: should process after (in overrideViewProperties) - $this->addRelatedReports($value); - } else if ($name == 'visualization_properties') { - $this->setVisualizationPropertiesFromMetadata($value); - } elseif (property_exists($this->vizRequest, $name)) { - $this->vizRequest->$name = $value; - } else if (property_exists($this->vizConfig, $name)) { - $this->vizConfig->$name = $value; - } else { - $report = $this->currentControllerName . '.' . $this->currentControllerAction; - throw new \Exception("Invalid view property '$name' specified in view property metadata for '$report'."); - } - } - - /** - * Sets visualization properties using data in a visualization's default property values - * array. - */ - private function setVisualizationPropertiesFromMetadata($properties) - { - if ($this->visualizationClass === null) { - return null; - } - - if (!is_array($properties)) { - return null; - } - - $visualizationIds = Visualization::getVisualizationIdsWithInheritance($this->visualizationClass); - foreach ($visualizationIds as $visualizationId) { - if (empty($properties[$visualizationId])) { - continue; - } - - foreach ($properties[$visualizationId] as $key => $value) { - if (property_exists($this->vizRequest, $key)) { - $this->vizRequest->$key = $value; - } elseif (property_exists($this->vizConfig, $key)) { - $this->vizConfig->$key = $value; - } else { - $this->vizConfig->visualization_properties->$key = $value; - } - } - } - } - - /** - * Function called by the ViewDataTable objects in order to fetch data from the API. - * The function init() must have been called before, so that the object knows which API module and action to call. - * It builds the API request string and uses Request to call the API. - * The requested DataTable object is stored in $this->dataTable. - */ - protected function loadDataTableFromAPI() - { - if (!is_null($this->dataTable)) { - // data table is already there - // this happens when setDataTable has been used - return; - } - - // we build the request (URL) to call the API - $requestArray = $this->getRequestArray(); - - // we make the request to the API - $request = new Request($requestArray); - - // and get the DataTable structure - $dataTable = $request->process(); - - $this->dataTable = $dataTable; - } - - /** - * Checks that the API returned a normal DataTable (as opposed to DataTable\Map) * @throws \Exception - * @return void - */ - protected function checkStandardDataTable() - { - Piwik::checkObjectTypeIs($this->dataTable, array('\Piwik\DataTable')); - } - - private function getFiltersToRun() - { - $priorityFilters = array(); - $presentationFilters = array(); - - foreach ($this->vizConfig->filters as $filterInfo) { - if ($filterInfo instanceof \Closure) { - $nameOrClosure = $filterInfo; - $parameters = array(); - $priority = false; - } else { - @list($nameOrClosure, $parameters, $priority) = $filterInfo; - } - - if ($nameOrClosure instanceof \Closure) { - $parameters[] = $this; - } - - if ($priority) { - $priorityFilters[] = array($nameOrClosure, $parameters); - } else { - $presentationFilters[] = array($nameOrClosure, $parameters); - } - } - - return array($priorityFilters, $presentationFilters); - } - - /** - * Hook called after the dataTable has been loaded from the API - * Can be used to add, delete or modify the data freshly loaded - * - * @return bool - */ - protected function postDataTableLoadedFromAPI(Visualization $visualization) - { - $columns = $this->dataTable->getColumns(); - $haveNbVisits = in_array('nb_visits', $columns); - $haveNbUniqVisitors = in_array('nb_uniq_visitors', $columns); - - // default columns_to_display to label, nb_uniq_visitors/nb_visits if those columns exist in the - // dataset. otherwise, default to all columns in dataset. - if (empty($this->vizConfig->columns_to_display)) { - if ($haveNbVisits - || $haveNbUniqVisitors - ) { - $columnsToDisplay = array('label'); - - // if unique visitors data is available, show it, otherwise just visits - if ($haveNbUniqVisitors) { - $columnsToDisplay[] = 'nb_uniq_visitors'; - } else { - $columnsToDisplay[] = 'nb_visits'; - } - } else { - $columnsToDisplay = $columns; - } - - $this->vizConfig->columns_to_display = array_filter($columnsToDisplay); - } - - $this->removeEmptyColumnsFromDisplay(); - - // default sort order to visits/visitors data - if (empty($this->vizRequest->filter_sort_column)) { - if ($haveNbUniqVisitors - && in_array('nb_uniq_visitors', $this->vizConfig->columns_to_display) - ) { - $this->vizRequest->filter_sort_column = 'nb_uniq_visitors'; - } else { - $this->vizRequest->filter_sort_column = 'nb_visits'; - } - $this->vizRequest->filter_sort_order = 'desc'; - } - - // deal w/ table metadata - if ($this->dataTable instanceof DataTable) { - $this->vizConfig->metadata = $this->dataTable->getAllTableMetadata(); - - if (isset($this->vizConfig->metadata[DataTable::ARCHIVED_DATE_METADATA_NAME])) { - $this->vizConfig->metadata[DataTable::ARCHIVED_DATE_METADATA_NAME] = - $this->makePrettyArchivedOnText(); - } - } - - list($priorityFilters, $otherFilters) = $this->getFiltersToRun(); - - // First, filters that delete rows - foreach ($priorityFilters as $filter) { - $this->dataTable->filter($filter[0], $filter[1]); - } - - $visualization->beforeGenericFiltersAreAppliedToLoadedDataTable($this->dataTable, $this->vizConfig, $this->vizRequest); - - if (!$this->areGenericFiltersDisabled()) { - // Second, generic filters (Sort, Limit, Replace Column Names, etc.) - $requestArray = $this->getRequestArray(); - $request = Request::getRequestArrayFromString($requestArray); - - if ($this->vizConfig->enable_sort === false) { - $request['filter_sort_column'] = $request['filter_sort_order'] = ''; - } - - $genericFilter = new \Piwik\API\DataTableGenericFilter($request); - $genericFilter->filter($this->dataTable); - } - - // queue other filters so they can be applied later if queued filters are disabled - foreach ($otherFilters as $filter) { - $this->dataTable->queueFilter($filter[0], $filter[1]); - } - - // Finally, apply datatable filters that were queued (should be 'presentation' filters that - // do not affect the number of rows) - if (!$this->areQueuedFiltersDisabled()) { - - $this->dataTable->applyQueuedFilters(); - } - - $visualization->afterGenericFiltersAreAppliedToLoadedDataTable($this->dataTable, $this->vizConfig, $this->vizRequest); - - return true; - } - - /** - * Returns true if generic filters have been disabled, false if otherwise. - * - * @return bool + * @return \Piwik\Plugin\ViewDataTable|\Piwik\Plugin\Visualization|\Piwik\Plugins\CoreVisualizations\Visualizations\Sparkline; */ - private function areGenericFiltersDisabled() + public static function factory($defaultType = null, $apiAction = false, $controllerAction = false, $forceDefault = false) { - // if disable_generic_filters query param is set to '1', generic filters are disabled - if (Common::getRequestVar('disable_generic_filters', '0', 'string') == 1) { - return true; - } - - // if $this->disableGenericFilters() was called, generic filters are disabled - if (isset($this->vizConfig->disable_generic_filters) - && $this->vizConfig->disable_generic_filters === true - ) { - return true; + if (false === $controllerAction) { + $controllerAction = $apiAction; } - return false; - } - - /** - * Returns true if queued filters have been disabled, false if otherwise. - * - * @return bool - */ - private function areQueuedFiltersDisabled() - { - return isset($this->vizConfig->disable_queued_filters) && $this->vizConfig->disable_queued_filters; - } - - /** - * Returns prettified and translated text that describes when a report was last updated. - * - * @return string - */ - private function makePrettyArchivedOnText() - { - $dateText = $this->vizConfig->metadata[DataTable::ARCHIVED_DATE_METADATA_NAME]; - $date = Date::factory($dateText); - $today = mktime(0, 0, 0); - if ($date->getTimestamp() > $today) { - $elapsedSeconds = time() - $date->getTimestamp(); - $timeAgo = MetricsFormatter::getPrettyTimeFromSeconds($elapsedSeconds); + $defaultViewType = self::getDefaultViewTypeForReport($apiAction); - return Piwik::translate('CoreHome_ReportGeneratedXAgo', $timeAgo); + if (!$forceDefault && !empty($defaultViewType)) { + $defaultType = $defaultViewType; } - $prettyDate = $date->getLocalized("%longYear%, %longMonth% %day%") . $date->toString('S'); - return Piwik::translate('CoreHome_ReportGeneratedOn', $prettyDate); - } - - /** - * @return string URL to call the API, eg. "method=Referrers.getKeywords&period=day&date=yesterday"... - */ - public function getRequestArray() - { - // we prepare the array to give to the API Request - // we setup the method and format variable - // - we request the method to call to get this specific DataTable - // - the format = original specifies that we want to get the original DataTable structure itself, not rendered - $requestArray = array( - 'method' => $this->vizRequest->apiMethodToRequestDataTable, - 'format' => 'original', - 'disable_generic_filters' => Common::getRequestVar('disable_generic_filters', 1, 'int'), - ); + $type = Common::getRequestVar('viewDataTable', $defaultType ? : 'table', 'string'); - $toSetEventually = array( - 'filter_limit', - 'keep_summary_row', - 'filter_sort_column', - 'filter_sort_order', - 'filter_excludelowpop', - 'filter_excludelowpop_value', - 'filter_column', - 'filter_pattern', - ); + $visualizations = static::getAvailableVisualizations(); - foreach ($toSetEventually as $varToSet) { - $value = $this->getDefaultOrCurrent($varToSet); - if (false !== $value) { - $requestArray[$varToSet] = $value; - } + if (array_key_exists($type, $visualizations)) { + return new $visualizations[$type]($controllerAction, $apiAction); } - $segment = Request::getRawSegmentFromRequest(); - if (!empty($segment)) { - $requestArray['segment'] = $segment; + if (class_exists($type)) { + return new $type($controllerAction, $apiAction); } - if (self::shouldLoadExpanded()) { - $requestArray['expanded'] = 1; - } - - $requestArray = array_merge($requestArray, $this->vizRequest->request_parameters_to_modify); - - if (!empty($requestArray['filter_limit']) - && $requestArray['filter_limit'] === 0 - ) { - unset($requestArray['filter_limit']); - } - - return $requestArray; + throw new \Exception(sprintf('Visuzalization type %s not found', $type)); } /** - * This functions reads the customization values for the DataTable and returns an array (name,value) to be printed in Javascript. - * This array defines things such as: - * - name of the module & action to call to request data for this table - * - optional filters information, eg. filter_limit and filter_offset - * - etc. - * - * The values are loaded: - * - from the generic filters that are applied by default @see Piwik_API_DataTableGenericFilter.php::getGenericFiltersInformation() - * - from the values already available in the GET array - * - from the values set using methods from this class (eg. setSearchPattern(), setLimit(), etc.) + * Returns all registered visualization classes. Uses the 'Visualization.getAvailable' + * event to retrieve visualizations. * - * @return array eg. array('show_offset_information' => 0, 'show_... + * @return array Array mapping visualization IDs with their associated visualization classes. + * @throws \Exception If a visualization class does not exist or if a duplicate visualization ID + * is found. + * @return array */ - protected function getClientSideParametersToSet() + public static function getAvailableVisualizations() { - // build javascript variables to set - $javascriptVariablesToSet = array(); - - foreach ($this->vizConfig->custom_parameters as $name => $value) { - $javascriptVariablesToSet[$name] = $value; - } - - foreach ($_GET as $name => $value) { - try { - $requestValue = Common::getRequestVar($name); - } catch (\Exception $e) { - $requestValue = ''; - } - $javascriptVariablesToSet[$name] = $requestValue; - } + /** @var string[] $visualizations */ + $visualizations = array(); - foreach ($this->getClientSideRequestParameters() as $name) { - if (isset($javascriptVariablesToSet[$name])) { - continue; - } + /** + * This event is used to gather all available DataTable visualizations. Callbacks should add visualization + * class names to the incoming array. + */ + Piwik::postEvent('Visualization.addVisualizations', array(&$visualizations)); - $valueToConvert = false; - if (property_exists($this->vizRequest, $name)) { - $valueToConvert = $this->vizRequest->$name; - } else if (property_exists($this->vizConfig, $name)) { - $valueToConvert = $this->vizConfig->$name; - } else if (VisualizationPropertiesProxy::isValidVisualizationProperty($this->visualizationClass, $name)) { - $valueToConvert = $this->vizConfig->visualization_properties->$name; - } + $result = array(); - if (false !== $valueToConvert) { - $javascriptVariablesToSet[$name] = $this->convertForJson($valueToConvert); + foreach ($visualizations as $viz) { + if (!class_exists($viz)) { + throw new \Exception("Invalid visualization class '$viz' found in Visualization.getAvailableVisualizations."); } - } - if ($this->dataTable instanceof DataTable) { - // we override the filter_sort_column with the column used for sorting, - // which can be different from the one specified (eg. if the column doesn't exist) - $javascriptVariablesToSet['filter_sort_column'] = $this->dataTable->getSortedByColumnName(); - // datatable can return "2" but we want to write "nb_visits" in the js - if (isset(Metrics::$mappingFromIdToName[$javascriptVariablesToSet['filter_sort_column']])) { - $javascriptVariablesToSet['filter_sort_column'] = Metrics::$mappingFromIdToName[$javascriptVariablesToSet['filter_sort_column']]; + if (!is_subclass_of($viz, '\\Piwik\\Plugin\\ViewDataTable')) { + throw new \Exception("Visualization class '$viz' does not extend Plugin/ViewDataTable"); } - } - - $javascriptVariablesToSet['module'] = $this->currentControllerName; - $javascriptVariablesToSet['action'] = $this->currentControllerAction; - if (!isset($javascriptVariablesToSet['viewDataTable'])) { - $javascriptVariablesToSet['viewDataTable'] = $this->getViewDataTableId(); - } - if ($this->dataTable && - // Set doesn't have the method - !($this->dataTable instanceof DataTable\Map) - && empty($javascriptVariablesToSet['totalRows']) - ) { - $javascriptVariablesToSet['totalRows'] = $this->dataTable->getRowsCountBeforeLimitFilter(); - } + $vizId = $viz::getViewDataTableId(); - $deleteFromJavascriptVariables = array( - 'filter_excludelowpop', - 'filter_excludelowpop_value', - ); - foreach ($deleteFromJavascriptVariables as $name) { - if (isset($javascriptVariablesToSet[$name])) { - unset($javascriptVariablesToSet[$name]); + if (isset($result[$vizId])) { + throw new \Exception("Visualization ID '$vizId' is already in use!"); } - } - - $rawSegment = Request::getRawSegmentFromRequest(); - if (!empty($rawSegment)) { - $javascriptVariablesToSet['segment'] = $rawSegment; - } - return $javascriptVariablesToSet; - } - - /** - * Returns array of properties that should be visible to client side JavaScript. The data - * will be available in the data-props HTML attribute of the .dataTable div. - * - * @return array Maps property names w/ property values. - */ - private function getClientSidePropertiesToSet() - { - $result = array(); - - foreach ($this->getClientSideConfigProperties() as $name) { - if (property_exists($this->vizRequest, $name)) { - $result[$name] = $this->convertForJson($this->vizRequest->$name); - } else if (property_exists($this->vizConfig, $name)) { - $result[$name] = $this->convertForJson($this->vizConfig->$name); - } else if (VisualizationPropertiesProxy::isValidVisualizationProperty($this->visualizationClass, $name)) { - $result[$name] = $this->convertForJson($this->vizConfig->visualization_properties->$name); - } + $result[$vizId] = $viz; } return $result; } /** - * Returns, for a given parameter, the value of this parameter in the REQUEST array. - * If not set, returns the default value for this parameter @see getDefault() - * - * @param string $nameVar - * @return string|mixed Value of this parameter - */ - protected function getDefaultOrCurrent($nameVar) - { - if (isset($_GET[$nameVar])) { - return Common::sanitizeInputValue($_GET[$nameVar]); - } - $default = $this->getDefault($nameVar); - return $default; - } - - /** - * Returns the default value for a given parameter. - * For example, these default values can be set using the disable* methods. - * - * @param string $nameVar - * @return mixed - */ - protected function getDefault($nameVar) - { - if (isset($this->vizRequest->$nameVar)) { - return $this->vizRequest->$nameVar; - } - if (isset($this->vizConfig->$nameVar)) { - return $this->vizConfig->$nameVar; - } - - return false; - } - - /** Load documentation from the API */ - private function loadDocumentation() - { - $this->vizConfig->metrics_documentation = array(); - - $report = API::getInstance()->getMetadata(0, $this->currentControllerName, $this->currentControllerAction); - $report = $report[0]; - - if (isset($report['metricsDocumentation'])) { - $this->vizConfig->metrics_documentation = $report['metricsDocumentation']; - } - - if (isset($report['documentation'])) { - $this->vizConfig->documentation = $report['documentation']; - } - } - - private function removeEmptyColumnsFromDisplay() - { - if (empty($this->dataTable)) { - return; - } - if ($this->dataTable instanceof DataTable\Map) { - $emptyColumns = $this->dataTable->getMetadataIntersectArray(DataTable::EMPTY_COLUMNS_METADATA_NAME); - } else { - $emptyColumns = $this->dataTable->getMetadata(DataTable::EMPTY_COLUMNS_METADATA_NAME); - } - if (is_array($emptyColumns)) { - foreach ($emptyColumns as $emptyColumn) { - $key = array_search($emptyColumn, $this->vizConfig->columns_to_display); - if ($key !== false) { - unset($this->vizConfig->columns_to_display[$key]); - } - } - $this->vizConfig->columns_to_display = array_values($this->vizConfig->columns_to_display); - } - } - - private function addRelatedReport($module, $action, $title, $queryParams = array()) - { - // don't add the related report if it references this report - if ($this->currentControllerName == $module && $this->currentControllerAction == $action) { - return; - } - - $url = $this->getBaseReportUrl($module, $action, $queryParams); - $this->vizConfig->related_reports[$url] = $title; - } - - private function addRelatedReports($relatedReports) - { - foreach ($relatedReports as $report => $title) { - list($module, $action) = explode('.', $report); - $this->addRelatedReport($module, $action, $title); - } - } - - /** - * Returns true if it is likely that the data for this report has been purged and if the - * user should be told about that. + * Returns all available visualizations that are not part of the CoreVisualizations plugin. * - * In order for this function to return true, the following must also be true: - * - The data table for this report must either be empty or not have been fetched. - * - The period of this report is not a multiple period. - * - The date of this report must be older than the delete_reports_older_than config option. - * @return bool + * @return array Array mapping visualization IDs with their associated visualization classes. */ - public function hasReportBeenPurged() + public static function getNonCoreVisualizations() { - $strPeriod = Common::getRequestVar('period', false); - $strDate = Common::getRequestVar('date', false); - - if ($strPeriod !== false - && $strDate !== false - && (is_null($this->dataTable) - || (!empty($this->dataTable) && $this->dataTable->getRowsCount() == 0)) - ) { - // if range, only look at the first date - if ($strPeriod == 'range') { - $idSite = Common::getRequestVar('idSite', ''); - if (intval($idSite) != 0) { - $site = new Site($idSite); - $timezone = $site->getTimezone(); - } else { - $timezone = 'UTC'; - } - - $period = new Range('range', $strDate, $timezone); - $reportDate = $period->getDateStart(); - } // if a multiple period, this function is irrelevant - else if (Period::isMultiplePeriod($strDate, $strPeriod)) { - return false; - } // otherwise, use the date as given - else { - $reportDate = Date::factory($strDate); - } - - $reportYear = $reportDate->toString('Y'); - $reportMonth = $reportDate->toString('m'); + $result = array(); - if (\Piwik\Plugin\Manager::getInstance()->isPluginActivated('PrivacyManager') - && Plugins\PrivacyManager\PrivacyManager::shouldReportBePurged($reportYear, $reportMonth) - ) { - return true; + foreach (static::getAvailableVisualizations() as $vizId => $vizClass) { + if (false === strpos($vizClass, 'Piwik\\Plugins\\CoreVisualizations') + && false === strpos($vizClass, 'Piwik\\Plugins\\Goals\\Visualizations\\Goals')) { + $result[$vizId] = $vizClass; } } - return false; - } - - /** - * Returns URL for this report w/o any filter parameters. - * - * @param string $module - * @param string $action - * @param array $queryParams - * @return string - */ - private function getBaseReportUrl($module, $action, $queryParams = array()) - { - $params = array_merge($queryParams, array('module' => $module, 'action' => $action)); - return Request::getCurrentUrlWithoutGenericFilters($params); + return $result; } /** @@ -1014,15 +171,19 @@ class ViewDataTable * @throws \Exception * @return string|null See $fetch. */ - static public function renderReport($pluginName, $apiAction, $fetch = true) + public static function renderReport($pluginName, $apiAction, $fetch = true) { - $namespacedApiClassName = "\\Piwik\\Plugins\\$pluginName\\API"; - if (!method_exists($namespacedApiClassName::getInstance(), $apiAction)) { - throw new \Exception("$namespacedApiClassName Invalid action name '$apiAction' for '$pluginName' plugin."); + /** @var Proxy $apiProxy */ + $apiProxy = Proxy::getInstance(); + + if (!$apiProxy->isExistingApiAction($pluginName, $apiAction)) { + throw new \Exception("Invalid action name '$apiAction' for '$pluginName' plugin."); } - $view = self::factory(null, $pluginName . '.' . $apiAction); - $rendered = $view->render(); + $apiAction = $apiProxy->buildApiActionName($pluginName, $apiAction); + + $view = static::factory(null, $apiAction); + $rendered = $view->render(); if ($fetch) { return $rendered; @@ -1032,323 +193,41 @@ class ViewDataTable } /** - * Convenience function. Calls main() & renders the view that gets built. - * - * @return string The result of rendering. + * Returns the default viewDataTable ID to use when determining which visualization to use. */ - public function render() + private static function getDefaultViewTypeForReport($apiAction) { - $view = $this->buildView(); - return $view->render(); + $defaultViewTypes = self::getDefaultViewTypeForReports(); + return isset($defaultViewTypes[$apiAction]) ? $defaultViewTypes[$apiAction] : false; } /** - * Returns whether the DataTable result will have to be expanded for the - * current request before rendering. - * - * @return bool + * Returns a list of default viewDataTables ID to use when determining which visualization to use for multiple + * reports. */ - public static function shouldLoadExpanded() + private static function getDefaultViewTypeForReports() { - // if filter_column_recursive & filter_pattern_recursive are supplied, and flat isn't supplied - // we have to load all the child subtables. - return Common::getRequestVar('filter_column_recursive', false) !== false - && Common::getRequestVar('filter_pattern_recursive', false) !== false - && Common::getRequestVar('flat', false) === false; - } - - protected function overrideViewProperties() - { - if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated('Goals')) { - $this->vizConfig->show_goals = false; - } - - if (empty($this->vizConfig->footer_icons)) { - $this->vizConfig->footer_icons = $this->getDefaultFooterIconsToShow(); - } - } - - protected function buildView() - { - /** @var Visualization $visualization */ - $visualization = new $this->visualizationClass($this); - - try { - - $visualization->configureVisualization($this->vizConfig); - + if (null === self::$defaultViewTypes) { + self::$defaultViewTypes = array(); /** - * This event is called after a visualization has been configured. Plugins can use this event to - * override view properties for individual reports or visualizations. + * This event is triggered to gather the default view types for each available report. By default a table + * is used. If you define your own report, you may want to subscribe to this event to define another + * Visualization that should be used by default to display your report. For instance a Pie, a Bar or a + * Cloud. * - * Themes can use this event to make sure reports look nice with their themes. Plugins - * that provide new visualizations can use this event to make sure certain reports - * are configured differently when viewed with the new visualization. + * Example: + * ``` + * public function getDefaultViewTypeForReports(&$defaultViewTypes) + * { + * $defaultViewTypes['Referrers.getSocials'] = HtmlTable::ID; + * $defaultViewTypes['Referrers.getUrlsForSocial'] = Pie::ID; + * ) + * } + * ``` */ - Piwik::postEvent(self::CONFIGURE_VIEW_EVENT, array($viewDataTable = $this)); - - $this->overrideViewProperties(); - $visualization->beforeLoadDataTable($this->vizRequest, $this->vizConfig); - - $this->loadDataTableFromAPI(); - $this->postDataTableLoadedFromAPI($visualization); - - $visualization->afterAllFilteresAreApplied($this->dataTable, $this->vizConfig, $this->vizRequest); - - } catch (NoAccessException $e) { - throw $e; - } catch (\Exception $e) { - Log::warning("Failed to get data from API: " . $e->getMessage()); - - $loadingError = array('message' => $e->getMessage()); - } - - $view = new View("@CoreHome/_dataTable"); - - if (!empty($loadingError)) { - $view->error = $loadingError; - } - - $view->visualization = $visualization; - $view->visualizationCssClass = $this->getDefaultDataTableCssClass(); - - if (null === $this->dataTable) { - $view->dataTable = null; - } else { - // TODO: this hook seems inappropriate. should be able to find data that is requested for (by site/date) and check if that - // has data. - if (method_exists($visualization, 'isThereDataToDisplay')) { - $view->dataTableHasNoData = !$visualization->isThereDataToDisplay($this->dataTable, $this); - } - - $view->dataTable = $this->dataTable; - - // if it's likely that the report data for this data table has been purged, - // set whether we should display a message to that effect. - $view->showReportDataWasPurgedMessage = $this->hasReportBeenPurged(); - $view->deleteReportsOlderThan = Option::get('delete_reports_older_than'); - } - $view->idSubtable = $this->idSubtable; - $view->clientSideParameters = $this->getClientSideParametersToSet(); - $view->clientSideProperties = $this->getClientSidePropertiesToSet(); - $view->properties = array_merge($this->vizRequest->getProperties(), $this->vizConfig->getProperties()); - $view->footerIcons = $this->vizConfig->footer_icons; - $view->isWidget = Common::getRequestVar('widget', 0, 'int'); - - return $view; - } - - private function getDefaultFooterIconsToShow() - { - $result = array(); - - // add normal view icons (eg, normal table, all columns, goals) - $normalViewIcons = array( - 'class' => 'tableAllColumnsSwitch', - 'buttons' => array(), - ); - - if ($this->show_table) { - $normalViewIcons['buttons'][] = array( - 'id' => 'table', - 'title' => Piwik::translate('General_DisplaySimpleTable'), - 'icon' => 'plugins/Zeitgeist/images/table.png', - ); - } - - if ($this->show_table_all_columns) { - $normalViewIcons['buttons'][] = array( - 'id' => 'tableAllColumns', - 'title' => Piwik::translate('General_DisplayTableWithMoreMetrics'), - 'icon' => 'plugins/Zeitgeist/images/table_more.png' - ); - } - - if ($this->show_goals) { - if (Common::getRequestVar('idGoal', false) == 'ecommerceOrder') { - $icon = 'plugins/Zeitgeist/images/ecommerceOrder.gif'; - } else { - $icon = 'plugins/Zeitgeist/images/goal.png'; - } - - $normalViewIcons['buttons'][] = array( - 'id' => 'tableGoals', - 'title' => Piwik::translate('General_DisplayTableWithGoalMetrics'), - 'icon' => $icon - ); - } - - if ($this->show_ecommerce) { - $normalViewIcons['buttons'][] = array( - 'id' => 'ecommerceOrder', - 'title' => Piwik::translate('General_EcommerceOrders'), - 'icon' => 'plugins/Zeitgeist/images/ecommerceOrder.gif', - 'text' => Piwik::translate('General_EcommerceOrders') - ); - - $normalViewIcons['buttons'][] = array( - 'id' => 'ecommerceAbandonedCart', - 'title' => Piwik::translate('General_AbandonedCarts'), - 'icon' => 'plugins/Zeitgeist/images/ecommerceAbandonedCart.gif', - 'text' => Piwik::translate('General_AbandonedCarts') - ); - } - - if (!empty($normalViewIcons['buttons'])) { - $result[] = $normalViewIcons; - } - - // add graph views - $graphViewIcons = array( - 'class' => 'tableGraphViews tableGraphCollapsed', - 'buttons' => array(), - ); - - if ($this->show_all_views_icons) { - if ($this->show_bar_chart) { - $graphViewIcons['buttons'][] = array( - 'id' => 'graphVerticalBar', - 'title' => Piwik::translate('General_VBarGraph'), - 'icon' => 'plugins/Zeitgeist/images/chart_bar.png' - ); - } - - if ($this->show_pie_chart) { - $graphViewIcons['buttons'][] = array( - 'id' => 'graphPie', - 'title' => Piwik::translate('General_Piechart'), - 'icon' => 'plugins/Zeitgeist/images/chart_pie.png' - ); - } - - if ($this->show_tag_cloud) { - $graphViewIcons['buttons'][] = array( - 'id' => 'cloud', - 'title' => Piwik::translate('General_TagCloud'), - 'icon' => 'plugins/Zeitgeist/images/tagcloud.png' - ); - } - - if ($this->show_non_core_visualizations) { - $nonCoreVisualizations = Visualization::getNonCoreVisualizations(); - $nonCoreVisualizationInfo = Visualization::getVisualizationInfoFor($nonCoreVisualizations); - - foreach ($nonCoreVisualizationInfo as $format => $info) { - $graphViewIcons['buttons'][] = array( - 'id' => $format, - 'title' => Piwik::translate($info['title']), - 'icon' => $info['table_icon'] - ); - } - } - } - - if (!empty($graphViewIcons['buttons'])) { - $result[] = $graphViewIcons; - } - - /** - * This event is called when determining the default set of footer icons to display - * below a report. - * - * Plugins can use this event to modify the default set of footer icons. You can - * add new icons or remove existing ones. - * - * $result must have the following format: - * - * ``` - * array( - * array( // footer icon group 1 - * 'class' => 'footerIconGroup1CssClass', - * 'buttons' => array( - * 'id' => 'myid', - * 'title' => 'My Tooltip', - * 'icon' => 'path/to/my/icon.png' - * ) - * ), - * array( // footer icon group 2 - * 'class' => 'footerIconGroup2CssClass', - * 'buttons' => array(...) - * ), - * ... - * ) - * ``` - */ - Piwik::postEvent(self::CONFIGURE_FOOTER_ICONS_EVENT, array(&$result, $viewDataTable = $this)); - - return $result; - } - - public function getDefaultDataTableCssClass() - { - return 'dataTableViz' . Piwik::getUnnamespacedClassName($this->visualizationClass); - } - - private function setViewProperties($values) - { - foreach ($values as $name => $value) { - $this->setViewProperty($name, $value); + Piwik::postEvent('Visualization.getDefaultViewTypeForReports', array(&self::$defaultViewTypes)); } - } - - private function setDefaultProperties() - { - // set core default properties - $this->setViewProperties($this->vizRequest->getProperties()); - $this->setViewProperties($this->vizConfig->getProperties()); - // set visualization default properties - if ($this->visualizationClass === null) { - return; - } - - $visualizationClass = $this->visualizationClass; - $this->setViewProperties($visualizationClass::getDefaultPropertyValues()); - } - - private function convertForJson($value) - { - return is_bool($value) ? (int)$value : $value; - } - - private function overrideViewPropertiesWithQueryParams() - { - $properties = $this->getOverridableProperties(); - foreach ($properties as $name) { - if (property_exists($this->vizRequest, $name)) { - $this->vizRequest->name = $this->getPropertyFromQueryParam($name, $this->vizRequest->$name); - } elseif (property_exists($this->vizConfig, $name)) { - $this->vizConfig->name = $this->getPropertyFromQueryParam($name, $this->vizConfig->$name); - } else if (VisualizationPropertiesProxy::isValidVisualizationProperty($this->visualizationClass, $name)) { - $default = $this->vizConfig->visualization_properties->$name; - - $this->vizConfig->visualization_properties->$name = $this->getPropertyFromQueryParam($name, $default); - } - } - - // handle special 'columns' query parameter - $columns = Common::getRequestVar('columns', false); - if ($columns !== false) { - $this->columns_to_display = Piwik::getArrayFromApiParameter($columns); - array_unshift($this->columns_to_display, 'label'); - } - } - - private function getPropertyFromQueryParam($name, $defaultValue) - { - $type = is_numeric($defaultValue) ? 'int' : null; - return Common::getRequestVar($name, $defaultValue, $type); - } - - /** - * Helper function for getCliendSiteProperties/getClientSideParameters/etc. - */ - private function getPropertyNameListWithMetaProperty($propertyNames, $getPropertiesFunctionName) - { - if ($this->visualizationClass) { - $klass = $this->visualizationClass; - $propertyNames = array_merge($propertyNames, $klass::$getPropertiesFunctionName()); - } - return $propertyNames; + return self::$defaultViewTypes; } -} +} \ No newline at end of file diff --git a/core/Visualization/Config.php b/core/ViewDataTable/Config.php similarity index 73% rename from core/Visualization/Config.php rename to core/ViewDataTable/Config.php index 6e6499144292aa59007dc88db8dadfbed65e9bf7..fdf467a39b1c6894bbe0be6a70a4e0816ca6b888 100644 --- a/core/Visualization/Config.php +++ b/core/ViewDataTable/Config.php @@ -9,8 +9,12 @@ * @package Piwik */ -namespace Piwik\Visualization; +namespace Piwik\ViewDataTable; +use Piwik\API\Request as ApiRequest; +use Piwik\Common; use Piwik\Metrics; +use Piwik\Piwik; +use Piwik\Plugins\API\API; /** * Renders a sparkline image given a PHP data array. @@ -24,19 +28,15 @@ class Config /** * The list of ViewDataTable properties that are 'Client Side Properties'. - * - * @see Piwik\ViewDataTable\Visualization::getClientSideProperties */ - public static $clientSideProperties = array( + public $clientSideProperties = array( 'show_limit_control' ); /** * The list of ViewDataTable properties that can be overriden by query parameters. - * - * @see Piwik\ViewDataTable\Visualization::getOverridableProperties */ - public static $overridableProperties = array( + public $overridableProperties = array( 'show_goals', 'disable_generic_filters', 'disable_queued_filters', @@ -66,16 +66,6 @@ class Config 'show_non_core_visualizations' ); - /** - * The default viewDataTable ID to use when determining which visualization to use. - * This property is only valid for reports whose properties are determined by the - * Visualization.getReportDisplayProperties event. When manually creating ViewDataTables, - * setting this property will have no effect. - * - * Default value: 'table' - */ - public $default_view_type = 'table'; - /** * Controls what footer icons are displayed on the bottom left of the DataTable view. * The value of this property must be an array of footer icon groups. Footer icon groups @@ -209,8 +199,6 @@ class Config * change to the clicked report and the list will change so the original report can be * navigated back to. * - * @see also self::TITLE. Both must be set if associating related reports. - * * Default value: array() */ public $related_reports = array(); @@ -219,7 +207,7 @@ class Config * The report title. Used with related reports so report headings can be changed when switching * reports. * - * @see also self::RELATED_REPORTS. This must be set if related reports are added. + * This must be set if related reports are added. * * Default value: '' */ @@ -354,19 +342,10 @@ class Config * from a Related Report will go to a different URL. Can be used to load an entire page instead * of a single report when going back to the original report. * - * @see also self::RELATED_REPORTS - * * Default value: The URL used to request the report without generic filters. */ public $self_url = ''; - /** - * Special property that holds the properties for DataTable Visualizations. - * - * @var \Piwik\ViewDataTable\VisualizationPropertiesProxy - */ - public $visualization_properties = array(); - /** * CSS class to use in the output HTML div. This is added in addition to the visualization CSS * class. @@ -386,8 +365,6 @@ class Config /** * If true, searching through the DataTable will search through all subtables. * - * @see also self::FILTER_PATTERN - * * Default value: false */ public $search_recursive = false; @@ -435,8 +412,6 @@ class Config * * TODO: pagination/offset is only valid for HtmlTables... should only display for those visualizations. * - * @see self::SHOW_OFFSET_INFORMATION - * * Default value: true */ public $show_pagination_control = true; @@ -444,8 +419,6 @@ class Config /** * Controls whether offset information (ie, '5-10 of 20') is shown under the datatable. * - * @see self::SHOW_PAGINATION_CONTROL - * * Default value: true */ public $show_offset_information = true; @@ -471,9 +444,13 @@ class Config */ public $show_non_core_visualizations = true; + public $report_last_updated_message = false; public $metadata = array(); public $report_id = ''; + public $controllerName; + public $controllerAction; + public function __construct() { $this->export_limit = \Piwik\Config::getInstance()->General['API_datatable_default_limit']; @@ -483,57 +460,153 @@ class Config ); } + public function setController($controllerName, $controllerAction) + { + $this->controllerName = $controllerName; + $this->controllerAction = $controllerAction; + $this->report_id = $controllerName . '.' . $controllerAction; + + $this->loadDocumentation(); + } + + /** Load documentation from the API */ + private function loadDocumentation() + { + $this->metrics_documentation = array(); + + $report = API::getInstance()->getMetadata(0, $this->controllerName, $this->controllerAction); + $report = $report[0]; + + if (isset($report['metricsDocumentation'])) { + $this->metrics_documentation = $report['metricsDocumentation']; + } + + if (isset($report['documentation'])) { + $this->documentation = $report['documentation']; + } + } + + public function addPropertiesThatShouldBeAvailableClientSide(array $propertyNames) + { + foreach ($propertyNames as $propertyName) { + $this->clientSideProperties[] = $propertyName; + } + } + + public function addPropertiesThatCanBeOverwrittenByQueryParams(array $propertyNames) + { + foreach ($propertyNames as $propertyName) { + $this->overridableProperties[] = $propertyName; + } + } + public function getProperties() { - return array( - 'show_non_core_visualizations' => $this->show_non_core_visualizations, - 'export_limit' => $this->export_limit, - 'hide_annotations_view' => $this->hide_annotations_view, - 'show_offset_information' => $this->show_offset_information, - 'show_pagination_control' => $this->show_pagination_control, - 'subtable_controller_action' => $this->subtable_controller_action, - 'filters' => $this->filters, - 'show_export_as_image_icon' => $this->show_export_as_image_icon, - 'y_axis_unit' => $this->y_axis_unit, - 'search_recursive' => $this->search_recursive, - 'datatable_js_type' => $this->datatable_js_type, - 'datatable_css_class' => $this->datatable_css_class, - 'visualization_properties' => $this->visualization_properties, - 'self_url' => $this->self_url, - 'tooltip_metadata_name' => $this->tooltip_metadata_name, - 'metrics_documentation' => $this->metrics_documentation, - 'show_footer_message' => $this->show_footer_message, - 'show_ecommerce' => $this->show_ecommerce, - 'show_export_as_rss_feed' => $this->show_export_as_rss_feed, - 'show_tag_cloud' => $this->show_tag_cloud, - 'show_pie_chart' => $this->show_pie_chart, - 'show_bar_chart' => $this->show_bar_chart, - 'enable_sort' => $this->enable_sort, - 'show_search' => $this->show_search, - 'show_limit_control' => $this->show_limit_control, - 'disable_queued_filters' => $this->disable_queued_filters, - 'disable_generic_filters' => $this->disable_generic_filters, - 'custom_parameters' => $this->custom_parameters, - 'documentation' => $this->documentation, - 'show_related_reports' => $this->show_related_reports, - 'title' => $this->title, - 'related_reports' => $this->related_reports, - 'show_active_view_icon' => $this->show_active_view_icon, - 'show_all_views_icons' => $this->show_all_views_icons, - 'columns_to_display' => $this->columns_to_display, - 'show_footer_icons' => $this->show_footer_icons, - 'show_footer' => $this->show_footer, - 'show_table_all_columns' => $this->show_table_all_columns, - 'show_table' => $this->show_table, - 'show_flatten_table' => $this->show_flatten_table, - 'show_exclude_low_population' => $this->show_exclude_low_population, - 'translations' => $this->translations, - 'show_goals' => $this->show_goals, - 'show_visualization_only' => $this->show_visualization_only, - 'footer_icons' => $this->footer_icons, - 'default_view_type' => $this->default_view_type, - 'metadata' => $this->metadata, - 'report_id' => $this->report_id - ); + return get_object_vars($this); } + + /** + * Returns true if queued filters have been disabled, false if otherwise. + * + * @return bool + */ + public function areQueuedFiltersDisabled() + { + return isset($this->disable_queued_filters) && $this->disable_queued_filters; + } + + /** + * Returns true if generic filters have been disabled, false if otherwise. + * + * @return bool + */ + public function areGenericFiltersDisabled() + { + // if disable_generic_filters query param is set to '1', generic filters are disabled + if (Common::getRequestVar('disable_generic_filters', '0', 'string') == 1) { + return true; + } + + if (isset($this->disable_generic_filters) && true === $this->disable_generic_filters) { + return true; + } + + return false; + } + + public function setDefaultColumnsToDisplay($columns, $hasNbVisits, $hasNbUniqVisitors) + { + if ($hasNbVisits || $hasNbUniqVisitors) { + $columnsToDisplay = array('label'); + + // if unique visitors data is available, show it, otherwise just visits + if ($hasNbUniqVisitors) { + $columnsToDisplay[] = 'nb_uniq_visitors'; + } else { + $columnsToDisplay[] = 'nb_visits'; + } + } else { + $columnsToDisplay = $columns; + } + + $this->columns_to_display = array_filter($columnsToDisplay); + } + + public function getFiltersToRun() + { + $priorityFilters = array(); + $presentationFilters = array(); + + foreach ($this->filters as $filterInfo) { + if ($filterInfo instanceof \Closure) { + $nameOrClosure = $filterInfo; + $parameters = array(); + $priority = false; + } else { + @list($nameOrClosure, $parameters, $priority) = $filterInfo; + } + + if ($priority) { + $priorityFilters[] = array($nameOrClosure, $parameters); + } else { + $presentationFilters[] = array($nameOrClosure, $parameters); + } + } + + return array($priorityFilters, $presentationFilters); + } + + public function addRelatedReport($relatedReport, $title, $queryParams = array()) + { + list($module, $action) = explode('.', $relatedReport); + + // don't add the related report if it references this report + if ($this->controllerName == $module && $this->controllerAction == $action) { + return; + } + + $url = ApiRequest::getBaseReportUrl($module, $action, $queryParams); + + $this->related_reports[$url] = $title; + } + + public function addRelatedReports($relatedReports) + { + foreach ($relatedReports as $report => $title) { + $this->addRelatedReport($report, $title); + } + } + + public function addTranslation($key, $translation) + { + $this->translations[$key] = $translation; + } + + public function addTranslations($translations) + { + foreach ($translations as $key => $translation) { + $this->addTranslation($key, $translation); + } + } + } diff --git a/core/ViewDataTable/Graph.php b/core/ViewDataTable/Graph.php deleted file mode 100644 index 00404f5c055830540856d0012010805ddfb8243b..0000000000000000000000000000000000000000 --- a/core/ViewDataTable/Graph.php +++ /dev/null @@ -1,243 +0,0 @@ -<?php -/** - * Piwik - Open source web analytics - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - * @category Piwik - * @package Piwik - */ -namespace Piwik\ViewDataTable; - -use Piwik\DataTable\Row; -use Piwik\DataTable; -use Piwik\DataTable\DataTableInterface; -use Piwik\Piwik; -use Piwik\Visualization\Config; -use Piwik\Visualization\Request; - -/** - * This is an abstract visualization that should be the base of any 'graph' visualization. - * This class defines certain visualization properties that are specific to all graph types. - * Derived visualizations can decide for themselves whether they should support individual - * properties. - */ -abstract class Graph extends Visualization -{ - const ID = 'graph'; - - /** - * Whether the series picker should allow picking more than one series or not. - * - * Default value: true - */ - const ALLOW_MULTI_SELECT_SERIES_PICKER = 'allow_multi_select_series_picker'; - - /** - * The maximum number of rows to render. All other rows will be aggregated in an 'Others' row. - * - * Default value: false (no limit) - */ - const MAX_GRAPH_ELEMENTS = 'max_graph_elements'; - - /** - * Array property that contains the names of columns that can be selected in the Series Picker. - * - * Default value: false - */ - const SELECTABLE_COLUMNS = 'selectable_columns'; - - /** - * Contains the column (if any) of the values used in the Row Picker. - * - * @see self::ROWS_TO_DISPLAY - * - * Default value: false - */ - const ROW_PICKER_VALUE_COLUMN = 'row_picker_match_rows_by'; - - /** - * Contains the list of values identifying rows that should be displayed as separate series. - * The values are of a specific column determined by the row_picker_match_rows_by column. - * - * @see self::ROW_PICKER_VALUE_COLUMN - * - * Default value: false - */ - const ROWS_TO_DISPLAY = 'rows_to_display'; - - /** - * Contains the list of values available for the Row Picker. Currently set to be all visible - * rows, if the row_picker_match_rows_by property is set. - * - * @see self::ROW_PICKER_VALUE_COLUMN - */ - const SELECTABLE_ROWS = 'selectable_rows'; - - /** - * Controls whether all ticks & labels are shown on a graph's x-axis or just some. - * - * Default value: false - */ - const SHOW_ALL_TICKS = 'show_all_ticks'; - - /** - * If true, a row with totals of each DataTable column is added. - * - * Default value: false - */ - const ADD_TOTAL_ROW = 'add_total_row'; - - /** - * Controls whether the Series Picker is shown or not. The Series Picker allows users to - * choose between displaying data of different columns. - * - * Default value: true - */ - const SHOW_SERIES_PICKER = 'show_series_picker'; - - /** - * Controls whether the percentage of the total is displayed as a tooltip when hovering over - * data points. - * - * NOTE: Sometimes this percentage is meaningless (when the total of the column values is - * not the total number of elements in the set). In this case the tooltip should not be - * displayed. - * - * Default value: true - */ - const DISPLAY_PERCENTAGE_IN_TOOLTIP = 'display_percentage_in_tooltip'; - - public static $clientSideConfigProperties = array( - 'show_series_picker', - 'allow_multi_select_series_picker', - 'selectable_columns', - 'selectable_rows', - 'display_percentage_in_tooltip' - ); - - public static $clientSideRequestParameters = array( - 'columns' - ); - - public static $overridableProperties = array( - 'show_all_ticks', - 'show_series_picker' - ); - - public $selectableRows = array(); - - public function configureVisualization(Config $properties) - { - if ($properties->show_goals) { - $properties->translations['nb_conversions'] = Piwik::translate('Goals_ColumnConversions'); - $properties->translations['revenue'] = Piwik::translate('General_TotalRevenue'); - } - } - - public static function getDefaultPropertyValues() - { - return array( - 'show_limit_control' => false, - 'visualization_properties' => array( - 'graph' => array( - 'add_total_row' => false, - 'show_all_ticks' => false, - 'allow_multi_select_series_picker' => true, - 'max_graph_elements' => false, - 'selectable_columns' => false, - 'show_series_picker' => true, - 'display_percentage_in_tooltip' => true, - 'row_picker_match_rows_by' => false, - 'rows_to_display' => false, - 'selectable_rows' => false - ) - ) - ); - } - - /** - * Defaults the selectable_columns property if it has not been set and then transforms - * it into something the SeriesPicker JavaScript class can use. - */ - public function afterAllFilteresAreApplied(DataTableInterface $dataTable, Config $properties, Request $request) - { - $properties->visualization_properties->selectable_rows = array_values($this->selectableRows); - - $selectableColumns = $properties->visualization_properties->selectable_columns; - - // set default selectable columns, if none specified - if ($selectableColumns === false) { - $selectableColumns = array('nb_visits', 'nb_actions'); - - if (in_array('nb_uniq_visitors', $dataTable->getColumns())) { - $selectableColumns[] = 'nb_uniq_visitors'; - } - } - - if ($properties->show_goals) { - $goalMetrics = array('nb_conversions', 'revenue'); - $selectableColumns = array_merge($selectableColumns, $goalMetrics); - } - - $transformed = array(); - foreach ($selectableColumns as $column) { - $transformed[] = array( - 'column' => $column, - 'translation' => @$properties->translations[$column], - 'displayed' => in_array($column, $properties->columns_to_display) - ); - } - $properties->visualization_properties->selectable_columns = $transformed; - } - - /** - * Determines what rows are selectable and stores them in the selectable_rows property in - * a format the SeriesPicker JavaScript class can use. - */ - public function beforeLoadDataTable(Request $request, Config $properties) - { - // TODO: this should not be required here. filter_limit should not be a view property, instead HtmlTable should use 'limit' or something, - // and manually set request_parameters_to_modify['filter_limit'] based on that. (same for filter_offset). - $request->request_parameters_to_modify['filter_limit'] = false; - - if ($properties->visualization_properties->max_graph_elements) { - $request->request_parameters_to_modify['filter_truncate'] = $properties->visualization_properties->max_graph_elements - 1; - } - - if ($properties->visualization_properties->row_picker_match_rows_by === false) { - return; - } - } - - public function beforeGenericFiltersAreAppliedToLoadedDataTable(DataTableInterface $dataTable, Config $properties, Request $request) - { - // collect all selectable rows - $self = $this; - - $dataTable->filter(function ($dataTable) use ($self, $properties) { - foreach ($dataTable->getRows() as $row) { - $rowLabel = $row->getColumn('label'); - if ($rowLabel === false) { - continue; - } - - // determine whether row is visible - $isVisible = true; - if ($properties->visualization_properties->row_picker_match_rows_by == 'label') { - $isVisible = in_array($rowLabel, $properties->visualization_properties->rows_to_display); - } - - // build config - if (!isset($self->selectableRows[$rowLabel])) { - $self->selectableRows[$rowLabel] = array( - 'label' => $rowLabel, - 'matcher' => $rowLabel, - 'displayed' => $isVisible - ); - } - } - }); - } -} \ No newline at end of file diff --git a/core/ViewDataTable/Request.php b/core/ViewDataTable/Request.php new file mode 100644 index 0000000000000000000000000000000000000000..9cd5d933d4560a3c4ade8c002fb0eb3136ad6023 --- /dev/null +++ b/core/ViewDataTable/Request.php @@ -0,0 +1,157 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik + * @package Piwik + */ + +namespace Piwik\ViewDataTable; + +use Piwik\API\Request as ApiRequest; +use Piwik\Common; +use Piwik\DataTable; +use Piwik\Date; +use Piwik\Metrics; +use Piwik\MetricsFormatter; +use Piwik\Period; +use Piwik\Piwik; + +class Request +{ + /** + * @var null|\Piwik\ViewDataTable\RequestConfig + */ + public $requestConfig; + + public function __construct($requestConfig) + { + $this->requestConfig = $requestConfig; + } + + /** + * Function called by the ViewDataTable objects in order to fetch data from the API. + * The function init() must have been called before, so that the object knows which API module and action to call. + * It builds the API request string and uses Request to call the API. + * The requested DataTable object is stored in $this->dataTable. + */ + public function loadDataTableFromAPI() + { + // we build the request (URL) to call the API + $requestArray = $this->getRequestArray(); + + // we make the request to the API + $request = new ApiRequest($requestArray); + + // and get the DataTable structure + $dataTable = $request->process(); + + return $dataTable; + } + + /** + * @return array URL to call the API, eg. "method=Referrers.getKeywords&period=day&date=yesterday"... + */ + public function getRequestArray() + { + // we prepare the array to give to the API Request + // we setup the method and format variable + // - we request the method to call to get this specific DataTable + // - the format = original specifies that we want to get the original DataTable structure itself, not rendered + $requestArray = array( + 'method' => $this->requestConfig->apiMethodToRequestDataTable, + 'format' => 'original', + 'disable_generic_filters' => Common::getRequestVar('disable_generic_filters', 1, 'int') + ); + + $toSetEventually = array( + 'filter_limit', + 'keep_summary_row', + 'filter_sort_column', + 'filter_sort_order', + 'filter_excludelowpop', + 'filter_excludelowpop_value', + 'filter_column', + 'filter_pattern', + ); + + foreach ($toSetEventually as $varToSet) { + $value = $this->getDefaultOrCurrent($varToSet); + if (false !== $value) { + $requestArray[$varToSet] = $value; + } + } + + $segment = ApiRequest::getRawSegmentFromRequest(); + if (!empty($segment)) { + $requestArray['segment'] = $segment; + } + + if (self::shouldLoadExpanded()) { + $requestArray['expanded'] = 1; + } + + $requestArray = array_merge($requestArray, $this->requestConfig->request_parameters_to_modify); + + if (!empty($requestArray['filter_limit']) + && $requestArray['filter_limit'] === 0 + ) { + unset($requestArray['filter_limit']); + } + + return $requestArray; + } + + /** + * Returns, for a given parameter, the value of this parameter in the REQUEST array. + * If not set, returns the default value for this parameter @see getDefault() + * + * @param string $nameVar + * @return string|mixed Value of this parameter + */ + protected function getDefaultOrCurrent($nameVar) + { + if (isset($_GET[$nameVar])) { + return Common::sanitizeInputValue($_GET[$nameVar]); + } + $default = $this->getDefault($nameVar); + return $default; + } + + /** + * Returns the default value for a given parameter. + * For example, these default values can be set using the disable* methods. + * + * @param string $nameVar + * @return mixed + */ + protected function getDefault($nameVar) + { + if (isset($this->requestConfig->$nameVar)) { + return $this->requestConfig->$nameVar; + } + + return false; + } + + /** + * Returns whether the DataTable result will have to be expanded for the + * current request before rendering. + * + * @return bool + */ + public static function shouldLoadExpanded() + { + // TODO this is not the right class for this + + // if filter_column_recursive & filter_pattern_recursive are supplied, and flat isn't supplied + // we have to load all the child subtables. + return Common::getRequestVar('filter_column_recursive', false) !== false + && Common::getRequestVar('filter_pattern_recursive', false) !== false + && Common::getRequestVar('flat', false) === false; + } + +} \ No newline at end of file diff --git a/core/Visualization/Request.php b/core/ViewDataTable/RequestConfig.php similarity index 64% rename from core/Visualization/Request.php rename to core/ViewDataTable/RequestConfig.php index 959658e619646a3a3a2f0056696e07af929305e5..c92b0a3ef70aaca3b139214eb0f0a48bdf3cb562 100644 --- a/core/Visualization/Request.php +++ b/core/ViewDataTable/RequestConfig.php @@ -9,7 +9,7 @@ * @package Piwik */ -namespace Piwik\Visualization; +namespace Piwik\ViewDataTable; /** * Renders a sparkline image given a PHP data array. @@ -18,15 +18,13 @@ namespace Piwik\Visualization; * @package Piwik * @subpackage Piwik_Visualization */ -class Request +class RequestConfig { /** * The list of ViewDataTable properties that are 'Client Side Parameters'. - * - * @see Piwik\ViewDataTable\Visualization::getClientSideParameters */ - public static $clientSideParameters = array( + public $clientSideParameters = array( 'filter_excludelowpop', 'filter_excludelowpop_value', 'filter_pattern', @@ -36,10 +34,8 @@ class Request /** * The list of ViewDataTable properties that can be overriden by query parameters. - * - * @see Piwik\ViewDataTable\Visualization::getOverridableProperties */ - public static $overridableProperties = array( + public $overridableProperties = array( 'filter_sort_column', 'filter_sort_order', 'filter_limit', @@ -47,7 +43,7 @@ class Request 'filter_pattern', 'filter_column', 'filter_excludelowpop', - 'filter_excludelowpop_value', + 'filter_excludelowpop_value' ); /** @@ -63,8 +59,6 @@ class Request * Controls the sort order. Either 'asc' or 'desc'. * * Default value: 'desc' - * - * @see self::SORTED_COLUMN */ public $filter_sort_order = 'desc'; @@ -72,8 +66,6 @@ class Request * The number of items to truncate the data set to before rendering the DataTable view. * * Default value: false - * - * @see self::OFFSET */ public $filter_limit = false; @@ -81,8 +73,6 @@ class Request * The number of items from the start of the data set that should be ignored. * * Default value: 0 - * - * @see self::LIMIT */ public $filter_offset = 0; @@ -107,8 +97,6 @@ class Request /** * Stores the column name to filter when filtering out rows with low values. * - * @see also self::EXCLUDE_LOW_POPULATION_VALUE - * * Default value: false */ public $filter_excludelowpop = false; @@ -116,8 +104,6 @@ class Request /** * Stores the value considered 'low' when filtering out rows w/ low values. * - * @see also self::EXCLUDE_LOW_POPULATION_COLUMN - * * Default value: false * @var \Closure|string */ @@ -135,19 +121,56 @@ class Request public $apiMethodToRequestDataTable = ''; + /** + * If the current dataTable refers to a subDataTable (eg. keywordsBySearchEngineId for id=X) this variable is set to the Id + * + * @var bool|int + */ + public $idSubtable = false; + public function getProperties() { - return array( - 'filter_excludelowpop_value' => $this->filter_excludelowpop_value, - 'filter_excludelowpop' => $this->filter_excludelowpop, - 'filter_column' => $this->filter_column, - 'filter_pattern' => $this->filter_pattern, - 'filter_offset' => $this->filter_offset, - 'filter_limit' => $this->filter_limit, - 'filter_sort_order' => $this->filter_sort_order, - 'filter_sort_column' => $this->filter_sort_column, - 'request_parameters_to_modify' => $this->request_parameters_to_modify, - 'apiMethodToRequestDataTable' => $this->apiMethodToRequestDataTable - ); + return get_object_vars($this); } + + public function addPropertiesThatShouldBeAvailableClientSide(array $propertyNames) + { + foreach ($propertyNames as $propertyName) { + $this->clientSideParameters[] = $propertyName; + } + } + + public function addPropertiesThatCanBeOverwrittenByQueryParams(array $propertyNames) + { + foreach ($propertyNames as $propertyName) { + $this->overridableProperties[] = $propertyName; + } + } + + public function setDefaultSort($columnsToDisplay, $hasNbUniqVisitors) + { + // default sort order to visits/visitors data + if ($hasNbUniqVisitors && in_array('nb_uniq_visitors', $columnsToDisplay)) { + $this->filter_sort_column = 'nb_uniq_visitors'; + } else { + $this->filter_sort_column = 'nb_visits'; + } + + $this->filter_sort_order = 'desc'; + } + + public function getApiModuleToRequest() + { + list($module, $method) = explode('.', $this->apiMethodToRequestDataTable); + + return $module; + } + + public function getApiMethodToRequest() + { + list($module, $method) = explode('.', $this->apiMethodToRequestDataTable); + + return $method; + } + } diff --git a/core/ViewDataTable/Visualization.php b/core/ViewDataTable/Visualization.php deleted file mode 100644 index 3af056bd0d58af6205468cd4ad32b4c0d9e9fe9e..0000000000000000000000000000000000000000 --- a/core/ViewDataTable/Visualization.php +++ /dev/null @@ -1,310 +0,0 @@ -<?php -/** - * Piwik - Open source web analytics - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - * @category Piwik - * @package Piwik - */ - -namespace Piwik\ViewDataTable; - -use Piwik\DataTable; -use Piwik\DataTable\DataTableInterface; -use Piwik\Piwik; -use Piwik\View; -use Piwik\ViewDataTable; -use Piwik\Visualization\Config; -use Piwik\Visualization\Request; - -/** - * Base class for all DataTable visualizations. Different visualizations are used to - * handle different values of the viewDataTable query parameter. Each one will display - * DataTable data in a different way. - * - * TODO: must be more in depth - */ -abstract class Visualization extends View -{ - const GET_AVAILABLE_EVENT = 'Visualization.addVisualizations'; - const TEMPLATE_FILE = ''; - - /** - * The view data table - * @var ViewDataTable - */ - protected $viewDataTable; - - final public function __construct($view) - { - $templateFile = static::TEMPLATE_FILE; - - if (empty($templateFile)) { - throw new \Exception('You have not defined a constant named TEMPLATE_FILE in your visualization class.'); - } - - parent::__construct($templateFile); - - $this->viewDataTable = $view; - $this->init(); - } - - protected function init() - { - // do your init stuff here, do not overwrite constructor - // maybe setting my view properties $this->vizTitle - } - - public function configureVisualization(Config $properties) - { - // our stuff goes in here - // like $properties->showFooterColumns = true; - } - - public function beforeLoadDataTable(Request $request, Config $properties) - { - // change request --> $requestProperties... - // like defining filter_column - // $requestProperties->filterColumn = 54; - // $requestProperties->setFilterColumn(); - } - - public function beforeGenericFiltersAreAppliedToLoadedDataTable(DataTableInterface $dataTable, Config $properties, Request $request) - { - - } - - public function afterGenericFiltersAreAppliedToLoadedDataTable(DataTableInterface $dataTable, Config $properties, Request $request) - { - - } - - public function afterAllFilteresAreApplied(DataTableInterface $dataTable, Config $properties, Request $request) - { - // filter and format requested data here - // $dataTable ... - - // $this->generator = new GeneratorFoo($dataTable); - } - - /** - * Default implementation of getDefaultPropertyValues static function. - * - * @return array - */ - public static function getDefaultPropertyValues() - { - return array(); - } - - /** - * Returns the array of view properties that a DataTable visualization will require - * to be both visible to client side JavaScript, and passed along as query parameters - * in every AJAX request. - * - * Derived Visualizations can specify client side parameters by declaring - * a static $clientSideParameters field that contains a list of view property - * names. - * - * @return array - */ - public static function getClientSideRequestParameters() - { - return self::getPropertyNameListWithMetaProperty('clientSideRequestParameters'); - } - - /** - * Returns an array of view property names that a DataTable visualization will - * require to be visible to client side JavaScript. Unlike 'client side parameters', - * these will not be passed with AJAX requests as query parameters. - * - * Derived Visualizations can specify client side properties by declaring - * a static $clientSideProperties field that contains a list of view property - * names. - * - * @return array - */ - public static function getClientSideConfigProperties() - { - return self::getPropertyNameListWithMetaProperty('clientSideConfigProperties'); - } - - /** - * Returns an array of view property names that can be overriden by query parameters. - * If a query parameter is sent with the same name as a view property, the view - * property will be set to the value of the query parameter. - * - * Derived Visualizations can specify overridable properties by declaring - * a static $overridableProperties field that contains a list of view property - * names. - */ - public static function getOverridableProperties() - { - return self::getPropertyNameListWithMetaProperty('overridableProperties'); - } - - /** - * Returns the viewDataTable ID for this DataTable visualization. Derived classes - * should declare a const ID field with the viewDataTable ID. - * - * @return string - */ - public static function getViewDataTableId() - { - if (defined('static::ID')) { - return static::ID; - } else { - return get_called_class(); - } - } - - /** - * Returns the list of parents for a Visualization class excluding the - * Visualization class and above. - * - * @param string $klass The class name of the Visualization. - * @return Visualization[] The list of parent classes in order from highest - * ancestor to the descended class. - */ - public static function getVisualizationClassLineage($klass) - { - $klasses = array_merge(array($klass), array_values(class_parents($klass, $autoload = false))); - - $idx = array_search('Piwik\\ViewDataTable\\Visualization', $klasses); - if ($idx !== false) { - $klasses = array_slice($klasses, 0, $idx); - } - - return array_reverse($klasses); - } - - /** - * Returns the viewDataTable IDs of a visualization's class lineage. - * - * @see self::getVisualizationClassLineage - * - * @param string $klass The visualization class. - * - * @return array - */ - public static function getVisualizationIdsWithInheritance($klass) - { - $klasses = self::getVisualizationClassLineage($klass); - - $result = array(); - foreach ($klasses as $klass) { - $result[] = $klass::getViewDataTableId(); - } - return $result; - } - - /** - * Returns all registered visualization classes. Uses the 'Visualization.getAvailable' - * event to retrieve visualizations. - * - * @return array Array mapping visualization IDs with their associated visualization classes. - * @throws \Exception If a visualization class does not exist or if a duplicate visualization ID - * is found. - */ - public static function getAvailableVisualizations() - { - /** @var self[] $visualizations */ - $visualizations = array(); - - /** - * This event is used to gather all available DataTable visualizations. Callbacks should add visualization - * class names to the incoming array. - */ - Piwik::postEvent(self::GET_AVAILABLE_EVENT, array(&$visualizations)); - - $result = array(); - foreach ($visualizations as $viz) { - if (!class_exists($viz)) { - throw new \Exception( - "Invalid visualization class '$viz' found in Visualization.getAvailableVisualizations."); - } - - if (is_subclass_of($viz, __CLASS__)) { - $vizId = $viz::getViewDataTableId(); - if (isset($result[$vizId])) { - throw new \Exception("Visualization ID '$vizId' is already in use!"); - } - - $result[$vizId] = $viz; - } - } - return $result; - } - - /** - * Returns all available visualizations that are not part of the CoreVisualizations plugin. - * - * @return array Array mapping visualization IDs with their associated visualization classes. - */ - public static function getNonCoreVisualizations() - { - $result = array(); - foreach (self::getAvailableVisualizations() as $vizId => $vizClass) { - if (strpos($vizClass, 'Piwik\\Plugins\\CoreVisualizations') === false) { - $result[$vizId] = $vizClass; - } - } - return $result; - } - - /** - * Returns an array mapping visualization IDs with information necessary for adding the - * visualizations to the footer of DataTable views. - * - * @param array $visualizations An array mapping visualization IDs w/ their associated classes. - * @return array - */ - public static function getVisualizationInfoFor($visualizations) - { - $result = array(); - foreach ($visualizations as $vizId => $vizClass) { - $result[$vizId] = array('table_icon' => $vizClass::FOOTER_ICON, 'title' => $vizClass::FOOTER_ICON_TITLE); - } - return $result; - } - - /** - * Returns the visualization class by it's viewDataTable ID. - * - * @param string $id The visualization ID. - * @return string The visualization class name. If $id is not a valid ID, the HtmlTable visualization - * is returned. - */ - public static function getClassFromId($id) - { - $visualizationClasses = self::getAvailableVisualizations(); - if (!isset($visualizationClasses[$id])) { - return $visualizationClasses['table']; - } - return $visualizationClasses[$id]; - } - - /** - * Helper function that merges the static field values of every class in this - * classes inheritance hierarchy. Uses late-static binding. - */ - private static function getPropertyNameListWithMetaProperty($staticFieldName) - { - if (isset(static::$$staticFieldName)) { - $result = array(); - - $lineage = static::getVisualizationClassLineage(get_called_class()); - foreach ($lineage as $klass) { - if (isset($klass::$$staticFieldName)) { - $result = array_merge($result, $klass::$$staticFieldName); - } - } - - return array_unique($result); - } else { - return array(); - } - } -} \ No newline at end of file diff --git a/core/ViewDataTable/VisualizationPropertiesProxy.php b/core/ViewDataTable/VisualizationPropertiesProxy.php deleted file mode 100644 index b100cd5c9298f592c95d99e083e6d9e46372e33f..0000000000000000000000000000000000000000 --- a/core/ViewDataTable/VisualizationPropertiesProxy.php +++ /dev/null @@ -1,175 +0,0 @@ -<?php -/** - * Piwik - Open source web analytics - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - * @category Piwik - * @package Piwik - */ - -namespace Piwik\ViewDataTable; - - -/** - * Proxy object used to get/set visualization properties. Used to check that property - * names are valid. - */ -class VisualizationPropertiesProxy -{ - /** - * The visualization class name. - * - * @var string - */ - private $visualizationClass; - - /** - * Stores visualization properties. - * - * @var array - */ - private $visualizationProperties = array(); - - /** - * Constructor. - * - * @param string $visualizationClass The visualization class to get/set properties of. - */ - public function __construct($visualizationClass) - { - $this->visualizationClass = $visualizationClass; - } - - /** - * Hack to allow property access in Twig (w/ property name checking). - */ - public function __call($name, $arguments) - { - return $this->$name; - } - - /** - * Gets a reference to a visualization property. - * - * @param string $name A valid property name for the current visualization. - * @return mixed - * @throws \Exception if the property name is invalid. - */ - public function &__get($name) - { - if ($this->visualizationClass !== null) { - static::checkValidVisualizationProperty($this->visualizationClass, $name); - } - - return $this->visualizationProperties[$name]; - } - - /** - * Sets a visualization property. - * - * @param string $name A valid property name for the current visualization. - * @param mixed $value - * @return mixed Returns $value. - * @throws \Exception if the property name is invalid. - */ - public function __set($name, $value) - { - if ($this->visualizationClass !== null) { - static::checkValidVisualizationProperty($this->visualizationClass, $name); - } - - return $this->visualizationProperties[$name] = $value; - } - - /** - * Checks if a property is a valid visualization property for the given visualization class, - * and if not, throws an exception. - * - * @param string $visualizationClass - * @param string $name The property name. - * @throws \Exception - */ - public static function checkValidVisualizationProperty($visualizationClass, $name) - { - if (!self::isValidVisualizationProperty($visualizationClass, $name)) { - throw new \Exception("Invalid Visualization display property '$name' for '$visualizationClass'."); - } - } - /** - * Returns true if $name is a valid visualization property for the given visualization class. - */ - public static function isValidVisualizationProperty($visualizationClass, $name) - { - $properties = self::getVisualizationProperties($visualizationClass); - return isset($properties[$name]); - } - - /** - * Returns the set of all valid properties for the given visualization class. The result is an - * array with property names as keys. Values of the array are undefined. - * - * @param string $visualizationClass - * - * @return array - */ - public static function getVisualizationProperties($visualizationClass) - { - static $propertiesCache = array(); - - if ($visualizationClass === null) { - return array(); - } - - if (!isset($propertiesCache[$visualizationClass])) { - $properties = self::getFlippedClassConstantMap($visualizationClass); - - $parentClass = get_parent_class($visualizationClass); - if ($parentClass != 'Piwik\\ViewDataTable\\Visualization') { - $properties += self::getVisualizationProperties($parentClass); - } - - $propertiesCache[$visualizationClass] = $properties; - } - - return $propertiesCache[$visualizationClass]; - } - - private static function getFlippedClassConstantMap($klass) - { - $klass = new \ReflectionClass($klass); - $constants = $klass->getConstants(); - - unset($constants['ID']); - unset($constants['FOOTER_ICON']); - unset($constants['FOOTER_ICON_TITLE']); - - foreach ($constants as $name => $value) { - if (!is_string($value)) { - unset($constants[$name]); - } - } - - return array_flip($constants); - } - - /** - * Sets a visualization property, but only if the visualization is an instance of a - * certain class. - * - * @param string $forClass The visualization class to check for. - * @param string $name A valid property name for the current visualization. - * @param mixed $value - * @return mixed Returns $value. - * @throws \Exception if the property name is invalid. - */ - public function setForVisualization($forClass, $name, $value) - { - if ($forClass == $this->visualizationClass - || is_subclass_of($this->visualizationClass, $forClass) - ) { - return $this->__set($name, $value); - } - } -} \ No newline at end of file diff --git a/plugins/Actions/Actions.php b/plugins/Actions/Actions.php index b2fb9e9583b6883cae7ec602c665f234b67a0aca..84bae607b7d54a41378424459a360518878576ff 100644 --- a/plugins/Actions/Actions.php +++ b/plugins/Actions/Actions.php @@ -17,11 +17,13 @@ use Piwik\Db; use Piwik\Menu\MenuMain; use Piwik\MetricsFormatter; use Piwik\Piwik; +use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; use Piwik\SegmentExpression; use Piwik\Site; use Piwik\Tracker\Action; -use Piwik\ViewDataTable; +use Piwik\ViewDataTable\Request as ViewDataTableRequest; use Piwik\WidgetsList; +use \Piwik\Plugin\ViewDataTable; /** * Actions plugin @@ -56,15 +58,15 @@ class Actions extends \Piwik\Plugin public function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'WidgetsList.addWidgets' => 'addWidgets', - 'Menu.Reporting.addItems' => 'addMenus', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', - 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', - 'AssetManager.getJavaScriptFiles' => 'getJsFiles' + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'WidgetsList.addWidgets' => 'addWidgets', + 'Menu.Reporting.addItems' => 'addMenus', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.configure' => 'configureViewDataTable', + 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', + 'AssetManager.getJavaScriptFiles' => 'getJsFiles' ); return $hooks; } @@ -643,51 +645,93 @@ class Actions extends \Piwik\Plugin } } - public function getReportDisplayProperties(&$properties) + public function configureViewDataTable(ViewDataTable $view) { - $properties['Actions.getPageUrls'] = $this->getDisplayPropertiesForPageUrls(); - $properties['Actions.getEntryPageUrls'] = $this->getDisplayPropertiesForEntryPageUrls(); - $properties['Actions.getExitPageUrls'] = $this->getDisplayPropertiesForExitPageUrls(); - $properties['Actions.getSiteSearchKeywords'] = $this->getDisplayPropertiesForSiteSearchKeywords(); - $properties['Actions.getSiteSearchNoResultKeywords'] = $this->getDisplayPropertiesForSiteSearchNoResultKeywords(); - $properties['Actions.getSiteSearchCategories'] = $this->getDisplayPropertiesForSiteSearchCategories(); - $properties['Actions.getPageUrlsFollowingSiteSearch'] = $this->getDisplayPropertiesForGetPageUrlsOrTitlesFollowingSiteSearch(false); - $properties['Actions.getPageTitlesFollowingSiteSearch'] = $this->getDisplayPropertiesForGetPageUrlsOrTitlesFollowingSiteSearch(true); - $properties['Actions.getPageTitles'] = $this->getDisplayPropertiesForGetPageTitles(); - $properties['Actions.getEntryPageTitles'] = $this->getDisplayPropertiesForGetEntryPageTitles(); - $properties['Actions.getExitPageTitles'] = $this->getDisplayPropertiesForGetExitPageTitles(); - $properties['Actions.getDownloads'] = $this->getDisplayPropertiesForGetDownloads(); - $properties['Actions.getOutlinks'] = $this->getDisplayPropertiesForGetOutlinks(); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'Actions.getPageUrls': + $this->configureViewForPageUrls($view); + break; + case 'Actions.getEntryPageUrls': + $this->configureViewForEntryPageUrls($view); + break; + case 'Actions.getExitPageUrls': + $this->configureViewForExitPageUrls($view); + break; + case 'Actions.getSiteSearchKeywords': + $this->configureViewForSiteSearchKeywords($view); + break; + case 'Actions.getSiteSearchNoResultKeywords': + $this->configureViewForSiteSearchNoResultKeywords($view); + break; + case 'Actions.getSiteSearchCategories': + $this->configureViewForSiteSearchCategories($view); + break; + case 'Actions.getPageUrlsFollowingSiteSearch': + $this->configureViewForGetPageUrlsOrTitlesFollowingSiteSearch($view, false); + break; + case 'Actions.getPageTitlesFollowingSiteSearch': + $this->configureViewForGetPageUrlsOrTitlesFollowingSiteSearch($view, true); + break; + case 'Actions.getPageTitles': + $this->configureViewForGetPageTitles($view); + break; + case 'Actions.getEntryPageTitles': + $this->configureViewForGetEntryPageTitles($view); + break; + case 'Actions.getExitPageTitles': + $this->configureViewForGetExitPageTitles($view); + break; + case 'Actions.getDownloads': + $this->configureViewForGetDownloads($view); + break; + case 'Actions.getOutlinks': + $this->configureViewForGetOutlinks($view); + break; + } + + if ($this->pluginName == $view->requestConfig->getApiModuleToRequest()) { + if ($view->isRequestingSingleDataTable()) { + // make sure custom visualizations are shown on actions reports + $view->config->show_all_views_icons = true; + $view->config->show_bar_chart = false; + $view->config->show_pie_chart = false; + $view->config->show_tag_cloud = false; + } + } } - private function addBaseDisplayProperties(&$result) + private function addBaseDisplayProperties(ViewDataTable $view) { - $result['datatable_js_type'] = 'ActionsDataTable'; - $result['visualization_properties']['table']['show_embedded_subtable'] = true; - $result['search_recursive'] = true; - $result['show_all_views_icons'] = false; - $result['show_table_all_columns'] = false; - $result['filter_limit'] = self::ACTIONS_REPORT_ROWS_DISPLAY; + $view->config->datatable_js_type = 'ActionsDataTable'; + $view->config->search_recursive = true; + $view->config->show_table_all_columns = false; + $view->requestConfig->filter_limit = self::ACTIONS_REPORT_ROWS_DISPLAY; + $view->config->show_all_views_icons = false; + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->show_embedded_subtable = true; + } // if the flat parameter is not provided, make sure it is set to 0 in the URL, // so users can see that they can set it to 1 (see #3365) - $result['custom_parameters'] = array('flat' => 0); + $view->config->custom_parameters = array('flat' => 0); - if (ViewDataTable::shouldLoadExpanded()) { - $result['visualization_properties']['table']['show_expanded'] = true; + if (ViewDataTableRequest::shouldLoadExpanded()) { - $result['filters'][] = function ($dataTable) { + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->show_expanded = true; + } + + $view->config->filters[] = function ($dataTable) { Actions::setDataTableRowLevels($dataTable); }; } - $result['filters'][] = function ($dataTable, $view) { - if ($view->getViewDataTableId() == 'table') { - $view->datatable_css_class = 'dataTableActions'; + $view->config->filters[] = function ($dataTable) use ($view) { + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->datatable_css_class = 'dataTableActions'; } }; - - return $result; } /** @@ -706,11 +750,11 @@ class Actions extends \Piwik\Plugin } } - private function addExcludeLowPopDisplayProperties(&$result) + private function addExcludeLowPopDisplayProperties(ViewDataTable $view) { if (Common::getRequestVar('enable_filter_excludelowpop', '0', 'string') != '0') { - $result['filter_excludelowpop'] = 'nb_hits'; - $result['filter_excludelowpop_value'] = function () { + $view->requestConfig->filter_excludelowpop = 'nb_hits'; + $view->requestConfig->filter_excludelowpop_value = function () { // computing minimum value to exclude (2 percent of the total number of actions) $visitsInfo = \Piwik\Plugins\VisitsSummary\Controller::getVisitsSummary()->getFirstRow(); $nbActions = $visitsInfo->getColumn('nb_actions'); @@ -723,27 +767,26 @@ class Actions extends \Piwik\Plugin } } - private function addPageDisplayProperties(&$result) + private function addPageDisplayProperties(ViewDataTable $view) { - // add common translations - $result['translations'] += array( + $view->config->addTranslations(array( 'nb_hits' => Piwik::translate('General_ColumnPageviews'), 'nb_visits' => Piwik::translate('General_ColumnUniquePageviews'), 'avg_time_on_page' => Piwik::translate('General_ColumnAverageTimeOnPage'), 'bounce_rate' => Piwik::translate('General_ColumnBounceRate'), 'exit_rate' => Piwik::translate('General_ColumnExitRate'), 'avg_time_generation' => Piwik::translate('General_ColumnAverageGenerationTime'), - ); + )); // prettify avg_time_on_page column $getPrettyTimeFromSeconds = '\Piwik\MetricsFormatter::getPrettyTimeFromSeconds'; - $result['filters'][] = array('ColumnCallbackReplace', array('avg_time_on_page', $getPrettyTimeFromSeconds)); + $view->config->filters[] = array('ColumnCallbackReplace', array('avg_time_on_page', $getPrettyTimeFromSeconds)); // prettify avg_time_generation column $avgTimeCallback = function ($time) { return $time ? MetricsFormatter::getPrettyTimeFromSeconds($time, true, true, false) : "-"; }; - $result['filters'][] = array('ColumnCallbackReplace', array('avg_time_generation', $avgTimeCallback)); + $view->config->filters[] = array('ColumnCallbackReplace', array('avg_time_generation', $avgTimeCallback)); // add avg_generation_time tooltip $tooltipCallback = function ($hits, $min, $max) { @@ -758,7 +801,7 @@ class Actions extends \Piwik\Plugin MetricsFormatter::getPrettyTimeFromSeconds($max) )); }; - $result['filters'][] = array('ColumnCallbackAddMetadata', + $view->config->filters[] = array('ColumnCallbackAddMetadata', array( array('nb_hits_with_time_generation', 'min_time_generation', 'max_time_generation'), 'avg_time_generation_tooltip', @@ -766,135 +809,117 @@ class Actions extends \Piwik\Plugin ) ); - $this->addExcludeLowPopDisplayProperties($result); + $this->addExcludeLowPopDisplayProperties($view); } - public function getDisplayPropertiesForPageUrls() + public function configureViewForPageUrls(ViewDataTable $view) { - $result = array( - 'translations' => array('label' => Piwik::translate('Actions_ColumnPageURL')), - 'columns_to_display' => array('label', 'nb_hits', 'nb_visits', 'bounce_rate', - 'avg_time_on_page', 'exit_rate', 'avg_time_generation'), - ); + $view->config->addTranslation('label', Piwik::translate('Actions_ColumnPageURL')); + $view->config->columns_to_display = array('label', 'nb_hits', 'nb_visits', 'bounce_rate', + 'avg_time_on_page', 'exit_rate', 'avg_time_generation'); - $this->addPageDisplayProperties($result); - $this->addBaseDisplayProperties($result); - - return $result; + $this->addPageDisplayProperties($view); + $this->addBaseDisplayProperties($view); } - public function getDisplayPropertiesForEntryPageUrls() + public function configureViewForEntryPageUrls(ViewDataTable $view) { // link to the page, not just the report, but only if not a widget - $widget = Common::getRequestVar('widget', false); - $reportUrl = Request::getCurrentUrlWithoutGenericFilters(array( - 'module' => 'Actions', - 'action' => $widget === false ? 'indexEntryPageUrls' : 'getEntryPageUrls' - )); - - $result = array( - 'translations' => array('label' => Piwik::translate('Actions_ColumnEntryPageURL'), - 'entry_bounce_count' => Piwik::translate('General_ColumnBounces'), - 'entry_nb_visits' => Piwik::translate('General_ColumnEntrances')), - 'columns_to_display' => array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate'), - 'filter_sort_column' => 'entry_nb_visits', - 'filter_sort_order' => 'desc', - 'title' => Piwik::translate('Actions_SubmenuPagesEntry'), - 'related_reports' => array( - 'Actions.getEntryPageTitles' => Piwik::translate('Actions_EntryPageTitles') - ), - 'self_url' => $reportUrl + $widget = Common::getRequestVar('widget', false); + + $view->config->self_url = Request::getCurrentUrlWithoutGenericFilters(array( + 'module' => 'Actions', + 'action' => $widget === false ? 'indexEntryPageUrls' : 'getEntryPageUrls' + )); + + $view->config->addTranslations(array( + 'label' => Piwik::translate('Actions_ColumnEntryPageURL'), + 'entry_bounce_count' => Piwik::translate('General_ColumnBounces'), + 'entry_nb_visits' => Piwik::translate('General_ColumnEntrances')) ); - $this->addPageDisplayProperties($result); - $this->addBaseDisplayProperties($result); + $view->config->title = Piwik::translate('Actions_SubmenuPagesEntry'); + $view->config->addRelatedReport('Actions.getEntryPageTitles', Piwik::translate('Actions_EntryPageTitles')); + $view->config->columns_to_display = array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate'); + $view->requestConfig->filter_sort_column = 'entry_nb_visits'; + $view->requestConfig->filter_sort_order = 'desc'; - return $result; + $this->addPageDisplayProperties($view); + $this->addBaseDisplayProperties($view); } - public function getDisplayPropertiesForExitPageUrls() + public function configureViewForExitPageUrls(ViewDataTable $view) { // link to the page, not just the report, but only if not a widget - $widget = Common::getRequestVar('widget', false); - $reportUrl = Request::getCurrentUrlWithoutGenericFilters(array( - 'module' => 'Actions', - 'action' => $widget === false ? 'indexExitPageUrls' : 'getExitPageUrls' - )); - - $result = array( - 'translations' => array('label' => Piwik::translate('Actions_ColumnExitPageURL'), - 'exit_nb_visits' => Piwik::translate('General_ColumnExits')), - 'columns_to_display' => array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate'), - 'filter_sort_column' => 'exit_nb_visits', - 'filter_sort_order' => 'desc', - 'title' => Piwik::translate('Actions_SubmenuPagesExit'), - 'related_reports' => array( - 'Actions.getExitPageTitles' => Piwik::translate('Actions_ExitPageTitles') - ), - 'self_url' => $reportUrl, + $widget = Common::getRequestVar('widget', false); + + $view->config->self_url = Request::getCurrentUrlWithoutGenericFilters(array( + 'module' => 'Actions', + 'action' => $widget === false ? 'indexExitPageUrls' : 'getExitPageUrls' + )); + + $view->config->addTranslations(array( + 'label' => Piwik::translate('Actions_ColumnExitPageURL'), + 'exit_nb_visits' => Piwik::translate('General_ColumnExits')) ); - $this->addPageDisplayProperties($result); - $this->addBaseDisplayProperties($result); + $view->config->title = Piwik::translate('Actions_SubmenuPagesExit'); + $view->config->addRelatedReport('Actions.getExitPageTitles', Piwik::translate('Actions_ExitPageTitles')); - return $result; + $view->config->columns_to_display = array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate'); + $view->requestConfig->filter_sort_column = 'exit_nb_visits'; + $view->requestConfig->filter_sort_order = 'desc'; + + $this->addPageDisplayProperties($view); + $this->addBaseDisplayProperties($view); } - private function addSiteSearchDisplayProperties(&$result) + private function addSiteSearchDisplayProperties(ViewDataTable $view) { - $result['translations'] += array( + $view->config->addTranslations(array( 'nb_visits' => Piwik::translate('Actions_ColumnSearches'), 'exit_rate' => str_replace("% ", "% ", Piwik::translate('Actions_ColumnSearchExits')), 'nb_pages_per_search' => Piwik::translate('Actions_ColumnPagesPerSearch') - ); - $result['show_bar_chart'] = false; - $result['show_table_all_columns'] = false; + )); + + $view->config->show_bar_chart = false; + $view->config->show_table_all_columns = false; } - public function getDisplayPropertiesForSiteSearchKeywords() + public function configureViewForSiteSearchKeywords(ViewDataTable $view) { - $result = array( - 'translations' => array('label' => Piwik::translate('General_ColumnKeyword')), - 'columns_to_display' => array('label', 'nb_visits', 'nb_pages_per_search', 'exit_rate'), - ); + $view->config->addTranslation('label', Piwik::translate('General_ColumnKeyword')); + $view->config->columns_to_display = array('label', 'nb_visits', 'nb_pages_per_search', 'exit_rate'); - $this->addSiteSearchDisplayProperties($result); - - return $result; + $this->addSiteSearchDisplayProperties($view); } - public function getDisplayPropertiesForSiteSearchNoResultKeywords() + public function configureViewForSiteSearchNoResultKeywords(ViewDataTable $view) { - $result = array( - 'translations' => array('label', Piwik::translate('Actions_ColumnNoResultKeyword')), - 'columns_to_display' => array('label', 'nb_visits', 'exit_rate') - ); - - $this->addSiteSearchDisplayProperties($result); + $view->config->addTranslation('label', Piwik::translate('Actions_ColumnNoResultKeyword')); + $view->config->columns_to_display = array('label', 'nb_visits', 'exit_rate'); - return $result; + $this->addSiteSearchDisplayProperties($view); } - public function getDisplayPropertiesForSiteSearchCategories() + public function configureViewForSiteSearchCategories(ViewDataTable $view) { - return array( - 'translations' => array( - 'label' => Piwik::translate('Actions_ColumnSearchCategory'), - 'nb_visits' => Piwik::translate('Actions_ColumnSearches'), - 'nb_pages_per_search' => Piwik::translate('Actions_ColumnPagesPerSearch') - ), - 'columns_to_display' => array('label', 'nb_visits', 'nb_pages_per_search'), - 'show_table_all_columns' => false, - 'show_bar_chart' => false, - 'visualization_properties' => array( - 'table' => array( - 'disable_row_evolution' => false, - ) - ) - ); + $view->config->addTranslations(array( + 'label' => Piwik::translate('Actions_ColumnSearchCategory'), + 'nb_visits' => Piwik::translate('Actions_ColumnSearches'), + 'nb_pages_per_search' => Piwik::translate('Actions_ColumnPagesPerSearch') + )); + + $view->config->columns_to_display = array('label', 'nb_visits', 'nb_pages_per_search'); + $view->config->show_table_all_columns = false; + $view->config->show_bar_chart = false; + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->disable_row_evolution = false; + } } - public function getDisplayPropertiesForGetPageUrlsOrTitlesFollowingSiteSearch($isTitle) + public function configureViewForGetPageUrlsOrTitlesFollowingSiteSearch(ViewDataTable $view, $isTitle) { $title = $isTitle ? Piwik::translate('Actions_WidgetPageTitlesFollowingSearch') : Piwik::translate('Actions_WidgetPageUrlsFollowingSearch'); @@ -904,135 +929,118 @@ class Actions extends \Piwik\Plugin 'Actions.getPageUrlsFollowingSiteSearch' => Piwik::translate('Actions_WidgetPageUrlsFollowingSearch'), ); - $result = array( - 'translations' => array( - 'label' => Piwik::translate('General_ColumnDestinationPage'), - 'nb_hits_following_search' => Piwik::translate('General_ColumnViewedAfterSearch'), - 'nb_hits' => Piwik::translate('General_ColumnTotalPageviews') - ), - 'columns_to_display' => array('label', 'nb_hits_following_search', 'nb_hits'), - 'filter_sort_column' => 'nb_hits_following_search', - 'filter_sort_order' => 'desc', - 'show_exclude_low_population' => false, - 'title' => $title, - 'related_reports' => $relatedReports - ); - - $this->addExcludeLowPopDisplayProperties($result); - $this->addBaseDisplayProperties($result); - - return $result; + $view->config->addRelatedReports($relatedReports); + $view->config->addTranslations(array( + 'label' => Piwik::translate('General_ColumnDestinationPage'), + 'nb_hits_following_search' => Piwik::translate('General_ColumnViewedAfterSearch'), + 'nb_hits' => Piwik::translate('General_ColumnTotalPageviews') + )); + + $view->config->title = $title; + $view->config->columns_to_display = array('label', 'nb_hits_following_search', 'nb_hits'); + $view->config->show_exclude_low_population = false; + $view->requestConfig->filter_sort_column = 'nb_hits_following_search'; + $view->requestConfig->filter_sort_order = 'desc'; + + $this->addExcludeLowPopDisplayProperties($view); + $this->addBaseDisplayProperties($view); } - public function getDisplayPropertiesForGetPageTitles() + public function configureViewForGetPageTitles(ViewDataTable $view) { // link to the page, not just the report, but only if not a widget $widget = Common::getRequestVar('widget', false); - $reportUrl = Request::getCurrentUrlWithoutGenericFilters(array( - 'module' => 'Actions', - 'action' => $widget === false ? 'indexPageTitles' : 'getPageTitles' - )); - - $result = array( - 'translations' => array('label' => Piwik::translate('Actions_ColumnPageName')), - 'columns_to_display' => array('label', 'nb_hits', 'nb_visits', 'bounce_rate', - 'avg_time_on_page', 'exit_rate', 'avg_time_generation'), - 'title' => Piwik::translate('Actions_SubmenuPageTitles'), - 'related_reports' => array( - 'Actions.getEntryPageTitles' => Piwik::translate('Actions_EntryPageTitles'), - 'Actions.getExitPageTitles' => Piwik::translate('Actions_ExitPageTitles'), - ), - 'self_url' => $reportUrl - ); - $this->addPageDisplayProperties($result); - $this->addBaseDisplayProperties($result); + $view->config->self_url = Request::getCurrentUrlWithoutGenericFilters(array( + 'module' => 'Actions', + 'action' => $widget === false ? 'indexPageTitles' : 'getPageTitles' + )); + + $view->config->title = Piwik::translate('Actions_SubmenuPageTitles'); + $view->config->addRelatedReports(array( + 'Actions.getEntryPageTitles' => Piwik::translate('Actions_EntryPageTitles'), + 'Actions.getExitPageTitles' => Piwik::translate('Actions_ExitPageTitles'), + )); - return $result; + $view->config->addTranslation('label', Piwik::translate('Actions_ColumnPageName')); + $view->config->columns_to_display = array('label', 'nb_hits', 'nb_visits', 'bounce_rate', + 'avg_time_on_page', 'exit_rate', 'avg_time_generation'); + + $this->addPageDisplayProperties($view); + $this->addBaseDisplayProperties($view); } - public function getDisplayPropertiesForGetEntryPageTitles() + public function configureViewForGetEntryPageTitles(ViewDataTable $view) { $entryPageUrlAction = Common::getRequestVar('widget', false) === false ? 'indexEntryPageUrls' : 'getEntryPageUrls'; - $result = array( - 'translations' => array( - 'label' => Piwik::translate('Actions_ColumnEntryPageTitle'), - 'entry_bounce_count' => Piwik::translate('General_ColumnBounces'), - 'entry_nb_visits' => Piwik::translate('General_ColumnEntrances'), - ), - 'columns_to_display' => array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate'), - 'title' => Piwik::translate('Actions_EntryPageTitles'), - 'related_reports' => array( - 'Actions.getPageTitles' => Piwik::translate('Actions_SubmenuPageTitles'), - "Actions.$entryPageUrlAction" => Piwik::translate('Actions_SubmenuPagesEntry') - ), - 'filter_sort_column' => 'entry_nb_visits' - ); + $view->config->addTranslations(array( + 'label' => Piwik::translate('Actions_ColumnEntryPageTitle'), + 'entry_bounce_count' => Piwik::translate('General_ColumnBounces'), + 'entry_nb_visits' => Piwik::translate('General_ColumnEntrances'), + )); + $view->config->addRelatedReports(array( + 'Actions.getPageTitles' => Piwik::translate('Actions_SubmenuPageTitles'), + "Actions.$entryPageUrlAction" => Piwik::translate('Actions_SubmenuPagesEntry') + )); + + $view->config->columns_to_display = array('label', 'entry_nb_visits', 'entry_bounce_count', 'bounce_rate'); + $view->config->title = Piwik::translate('Actions_EntryPageTitles'); - $this->addPageDisplayProperties($result); - $this->addBaseDisplayProperties($result); + $view->requestConfig->filter_sort_column = 'entry_nb_visits'; - return $result; + $this->addPageDisplayProperties($view); + $this->addBaseDisplayProperties($view); } - public function getDisplayPropertiesForGetExitPageTitles() + public function configureViewForGetExitPageTitles(ViewDataTable $view) { $exitPageUrlAction = Common::getRequestVar('widget', false) === false ? 'indexExitPageUrls' : 'getExitPageUrls'; - $result = array( - 'translations' => array( - 'label' => Piwik::translate('Actions_ColumnExitPageTitle'), - 'exit_nb_visits' => Piwik::translate('General_ColumnExits'), - ), - 'columns_to_display' => array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate'), - 'title' => Piwik::translate('Actions_ExitPageTitles'), - 'related_reports' => array( - 'Actions.getPageTitles' => Piwik::translate('Actions_SubmenuPageTitles'), - "Actions.$exitPageUrlAction" => Piwik::translate('Actions_SubmenuPagesExit'), - ), - ); + $view->config->addTranslations(array( + 'label' => Piwik::translate('Actions_ColumnExitPageTitle'), + 'exit_nb_visits' => Piwik::translate('General_ColumnExits'), + )); + $view->config->addRelatedReports(array( + 'Actions.getPageTitles' => Piwik::translate('Actions_SubmenuPageTitles'), + "Actions.$exitPageUrlAction" => Piwik::translate('Actions_SubmenuPagesExit'), + )); - $this->addPageDisplayProperties($result); - $this->addBaseDisplayProperties($result); + $view->config->title = Piwik::translate('Actions_ExitPageTitles'); + $view->config->columns_to_display = array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate'); - return $result; + $this->addPageDisplayProperties($view); + $this->addBaseDisplayProperties($view); } - public function getDisplayPropertiesForGetDownloads() + public function configureViewForGetDownloads(ViewDataTable $view) { - $result = array( - 'translations' => array( - 'label' => Piwik::translate('Actions_ColumnDownloadURL'), - 'nb_visits' => Piwik::translate('Actions_ColumnUniqueDownloads'), - 'nb_hits' => Piwik::translate('General_Downloads'), - ), - 'columns_to_display' => array('label', 'nb_visits', 'nb_hits'), - 'show_exclude_low_population' => false - ); + $view->config->addTranslations(array( + 'label' => Piwik::translate('Actions_ColumnDownloadURL'), + 'nb_visits' => Piwik::translate('Actions_ColumnUniqueDownloads'), + 'nb_hits' => Piwik::translate('General_Downloads'), + )); - $this->addBaseDisplayProperties($result); + $view->config->columns_to_display = array('label', 'nb_visits', 'nb_hits'); + $view->config->show_exclude_low_population = false; - return $result; + $this->addBaseDisplayProperties($view); } - public function getDisplayPropertiesForGetOutlinks() + public function configureViewForGetOutlinks(ViewDataTable $view) { - $result = array( - 'translations' => array( - 'label' => Piwik::translate('Actions_ColumnClickedURL'), - 'nb_visits' => Piwik::translate('Actions_ColumnUniqueClicks'), - 'nb_hits' => Piwik::translate('Actions_ColumnClicks'), - ), - 'columns_to_display' => array('label', 'nb_visits', 'nb_hits'), - 'show_exclude_low_population' => false - ); + $view->config->addTranslations(array( + 'label' => Piwik::translate('Actions_ColumnClickedURL'), + 'nb_visits' => Piwik::translate('Actions_ColumnUniqueClicks'), + 'nb_hits' => Piwik::translate('Actions_ColumnClicks'), + )); - $this->addBaseDisplayProperties($result); + $view->config->columns_to_display = array('label', 'nb_visits', 'nb_hits'); + $view->config->show_exclude_low_population = false; - return $result; + $this->addBaseDisplayProperties($view); } } diff --git a/plugins/CoreHome/DataTableRowAction/RowEvolution.php b/plugins/CoreHome/DataTableRowAction/RowEvolution.php index f7a730e56d83ce18edce36b4a84ebe303198104e..11039ca5a7b2c7984ce96b78c8b1542cce762641 100644 --- a/plugins/CoreHome/DataTableRowAction/RowEvolution.php +++ b/plugins/CoreHome/DataTableRowAction/RowEvolution.php @@ -194,22 +194,22 @@ class RowEvolution $view->setDataTable($this->dataTable); if (!empty($this->graphMetrics)) { // In row Evolution popover, this is empty - $view->columns_to_display = array_keys($metrics ? : $this->graphMetrics); + $view->config->columns_to_display = array_keys($metrics ? : $this->graphMetrics); } - $view->show_goals = false; - $view->show_all_views_icons = false; - $view->show_active_view_icon = false; - $view->show_related_reports = false; - $view->show_footer_message = false; - $view->visualization_properties->show_series_picker = false; + $view->config->show_goals = false; + $view->config->show_all_views_icons = false; + $view->config->show_active_view_icon = false; + $view->config->show_related_reports = false; + $view->config->show_series_picker = false; + $view->config->show_footer_message = false; foreach ($this->availableMetrics as $metric => $metadata) { - $view->translations[$metric] = $metadata['name']; + $view->config->translations[$metric] = $metadata['name']; } - $view->visualization_properties->external_series_toggle = 'RowEvolutionSeriesToggle'; - $view->visualization_properties->external_series_toggle_show_all = $this->initiallyShowAllMetrics; + $view->config->external_series_toggle = 'RowEvolutionSeriesToggle'; + $view->config->external_series_toggle_show_all = $this->initiallyShowAllMetrics; return $view; } diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 4dc2e59cee55c2b357ff9313cbc981dc6add2d4f..e570bc976c8a5168192bef27022fda906ad25089 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -504,7 +504,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { var totalRows = Number(self.param.totalRows); var offsetEndDisp = offsetEnd; - if (self.props.keep_summary_row == 1) --totalRows; + if (self.param.keep_summary_row == 1) --totalRows; if (offsetEnd > totalRows) offsetEndDisp = totalRows; @@ -522,7 +522,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { var offsetEnd = Number(self.param.filter_offset) + Number(self.param.filter_limit); var totalRows = Number(self.param.totalRows); - if (self.props.keep_summary_row == 1) --totalRows; + if (self.param.keep_summary_row == 1) --totalRows; if (offsetEnd < totalRows) { $(this).css('display', 'inline'); } diff --git a/plugins/CoreHome/templates/_dataTable.twig b/plugins/CoreHome/templates/_dataTable.twig index 56a4564d042910877bf49cb69e46d9478a4d22d3..54ed0b757bbb2fa743b4bd97dcdae58515d2fd8f 100644 --- a/plugins/CoreHome/templates/_dataTable.twig +++ b/plugins/CoreHome/templates/_dataTable.twig @@ -1,5 +1,5 @@ {% if properties.show_visualization_only %} - {% include visualization.getTemplateFile() with visualization.getTemplateVars() %} + {% include visualizationTemplate %} {%- else -%} {% set summaryRowId = constant('Piwik\\DataTable::ID_SUMMARY_ROW') %}{# ID_SUMMARY_ROW #} @@ -11,7 +11,7 @@ data-params="{% if clientSideParameters is empty %}{}{% else %}{{ clientSideParameters|json_encode }}{% endif %}"> <div class="reportDocumentation"> {% if properties.documentation|default is not empty %}<p>{{ properties.documentation|raw }}</p>{% endif %} - {% if properties.metadata.archived_date is defined %}<span class='helpDate'>{{ properties.metadata.archived_date }}</span>{% endif %} + {% if properties.report_last_updated_message is defined %}<span class='helpDate'>{{ properties.report_last_updated_message }}</span>{% endif %} </div> <div class="dataTableWrapper"> {% if error is defined %} @@ -26,7 +26,7 @@ {% endif %} </div> {% else %} - {% include visualization.getTemplateFile() with visualization.getTemplateVars() %} + {% include visualizationTemplate %} {% endif %} {% if properties.show_footer %} diff --git a/plugins/CorePluginsAdmin/Controller.php b/plugins/CorePluginsAdmin/Controller.php index 6b12dbec523fc953e5fc494f8517493411a1fc73..33a97d27b092b9ad241fa8ccbb0541a92ed82d34 100644 --- a/plugins/CorePluginsAdmin/Controller.php +++ b/plugins/CorePluginsAdmin/Controller.php @@ -192,7 +192,7 @@ class Controller extends Plugin\ControllerAdmin { Piwik::checkUserIsSuperUser(); - $activated = Common::getRequestVar('activated', false, 'integer', $_GET); + $activated = Common::getRequestVar('activated', false, 'integer', $_GET); $pluginName = Common::getRequestVar('pluginName', '', 'string'); $view = $this->configureView('@CorePluginsAdmin/' . $template); diff --git a/plugins/CoreVisualizations/CoreVisualizations.php b/plugins/CoreVisualizations/CoreVisualizations.php index 06db725f513fbb36660916c6b29aa7b25ea2b165..bab6c3f6d6f8c97d544b74b5470d8bc9601f25d8 100644 --- a/plugins/CoreVisualizations/CoreVisualizations.php +++ b/plugins/CoreVisualizations/CoreVisualizations.php @@ -37,9 +37,9 @@ class CoreVisualizations extends \Piwik\Plugin public function getAvailableDataTableVisualizations(&$visualizations) { + $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\Sparkline'; $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\HtmlTable'; $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\HtmlTable\\AllColumns'; - $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\HtmlTable\\Goals'; $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\Cloud'; $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\JqplotGraph\\Pie'; $visualizations[] = 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\JqplotGraph\\Bar'; diff --git a/plugins/CoreVisualizations/JqplotDataGenerator.php b/plugins/CoreVisualizations/JqplotDataGenerator.php index cc6022f83c7df32c789ca81f4e9d16afdd678f1c..fdc23c93c58ae1e6f3dabafb124c781a57a72ac6 100644 --- a/plugins/CoreVisualizations/JqplotDataGenerator.php +++ b/plugins/CoreVisualizations/JqplotDataGenerator.php @@ -86,7 +86,7 @@ class JqplotDataGenerator if ($dataTable->getRowsCount() > 0) { // if addTotalRow was called in GenerateGraphHTML, add a row containing totals of // different metrics - if ($this->properties['visualization_properties']->add_total_row) { + if ($this->properties['add_total_row']) { $dataTable->queueFilter('AddSummaryRow', array(0, Piwik::translate('General_Total'), null, false)); } diff --git a/plugins/CoreVisualizations/JqplotDataGenerator/Chart.php b/plugins/CoreVisualizations/JqplotDataGenerator/Chart.php index 0f1361b83af99181177eab7460c80c7ce61f2c2d..51ab4e017dd65ccf93e7a803f04e1cfba1326690 100644 --- a/plugins/CoreVisualizations/JqplotDataGenerator/Chart.php +++ b/plugins/CoreVisualizations/JqplotDataGenerator/Chart.php @@ -29,8 +29,8 @@ class Chart public function setAxisXLabels($xLabels) { - $xSteps = $this->properties['visualization_properties']->x_axis_step_size; - $showAllTicks = $this->properties['visualization_properties']->show_all_ticks; + $xSteps = $this->properties['x_axis_step_size']; + $showAllTicks = $this->properties['show_all_ticks']; $this->axes['xaxis']['labels'] = array_values($xLabels); diff --git a/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php b/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php index 8fbf5e7e783afd3df81e07ddbe110afe06ff373a..7ef36c902fd5cde58db73958458bdd8e975adabb 100644 --- a/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php +++ b/plugins/CoreVisualizations/JqplotDataGenerator/Evolution.php @@ -47,7 +47,7 @@ class Evolution extends JqplotDataGenerator $units = $this->getUnitsForColumnsToDisplay(); // if rows to display are not specified, default to all rows (TODO: perhaps this should be done elsewhere?) - $rowsToDisplay = $this->properties['visualization_properties']->rows_to_display + $rowsToDisplay = $this->properties['rows_to_display'] ? : array_unique($dataTable->getColumn('label')) ? : array(false) // make sure that a series is plotted even if there is no data ; diff --git a/plugins/CoreVisualizations/Visualizations/Cloud.php b/plugins/CoreVisualizations/Visualizations/Cloud.php index 8785ee6f1d230a208be68eddfffc7a19779660b9..8e23f5f7bcd8205256b5efe7f9adac827549f278 100644 --- a/plugins/CoreVisualizations/Visualizations/Cloud.php +++ b/plugins/CoreVisualizations/Visualizations/Cloud.php @@ -12,12 +12,10 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations; use Piwik\Common; use Piwik\DataTable; -use Piwik\DataTable\DataTableInterface; use Piwik\Log; use Piwik\View; -use Piwik\ViewDataTable\Visualization; -use Piwik\Visualization\Config; -use Piwik\Visualization\Request; +use Piwik\Plugin\Visualization; +use Piwik\ViewDataTable\Config; /** * Generates a tag cloud from a given data array. @@ -25,6 +23,8 @@ use Piwik\Visualization\Request; * * Inspired from Derek Harvey (www.derekharvey.co.uk) * + * @property Cloud\Config $config + * * @package Piwik * @subpackage Piwik_Visualization */ @@ -33,34 +33,36 @@ class Cloud extends Visualization const ID = 'cloud'; const TEMPLATE_FILE = "@CoreVisualizations/_dataTableViz_tagCloud.twig"; - /** - * Whether to display the logo assocatied with a DataTable row (stored as 'logo' row metadata) - * instead of the label in Tag Clouds. - * - * Default value: false - */ - const DISPLAY_LOGO_INSTEAD_OF_LABEL = 'display_logo_instead_of_label'; - /** Used by integration tests to make sure output is consistent. */ public static $debugDisableShuffle = false; - - public static $overridableProperties = array('display_logo_instead_of_label'); + public $truncatingLimit = 50; protected $wordsArray = array(); - public $truncatingLimit = 50; - public function afterAllFilteresAreApplied(DataTableInterface $dataTable, Config $properties, Request $request) + public static function getDefaultConfig() + { + return new Cloud\Config(); + } + + public function beforeRender() { - if ($dataTable->getRowsCount() == 0) { + $this->config->show_exclude_low_population = false; + $this->config->show_offset_information = false; + $this->config->show_limit_control = false; + } + + public function afterAllFilteresAreApplied() + { + if ($this->dataTable->getRowsCount() == 0) { return; } - $columnToDisplay = isset($properties->columns_to_display[1]) ? $properties->columns_to_display[1] : 'nb_visits'; + $columnToDisplay = isset($this->config->columns_to_display[1]) ? $this->config->columns_to_display[1] : 'nb_visits'; + $labelMetadata = array(); - $labelMetadata = array(); - foreach ($dataTable->getRows() as $row) { + foreach ($this->dataTable->getRows() as $row) { $logo = false; - if ($properties->visualization_properties->display_logo_instead_of_label) { + if ($this->config->display_logo_instead_of_label) { $logo = $row->getMetadata('logo'); } @@ -73,31 +75,14 @@ class Cloud extends Visualization $this->addWord($label, $row->getColumn($columnToDisplay)); } + $cloudValues = $this->getCloudValues(); foreach ($cloudValues as &$value) { $value['logoWidth'] = round(max(16, $value['percent'])); } - $this->labelMetadata = $labelMetadata; - $this->cloudValues = $cloudValues; - } - - public function configureVisualization(Config $properties) - { - $properties->show_exclude_low_population = false; - $properties->show_offset_information = false; - $properties->show_limit_control = false; - } - - public static function getDefaultPropertyValues() - { - return array( - 'visualization_properties' => array( - 'cloud' => array( - 'display_logo_instead_of_label' => false, - ) - ) - ); + $this->assignTemplateVar('labelMetadata', $labelMetadata); + $this->assignTemplateVar('cloudValues', $cloudValues); } /** @@ -118,25 +103,19 @@ class Cloud extends Visualization public function getCloudValues() { $this->shuffleCloud(); - $return = array(); + if (empty($this->wordsArray)) { return array(); } + + $return = array(); $maxValue = max($this->wordsArray); + foreach ($this->wordsArray as $word => $popularity) { - $wordTruncated = $word; - if (Common::mb_strlen($word) > $this->truncatingLimit) { - $wordTruncated = Common::mb_substr($word, 0, $this->truncatingLimit - 3) . '...'; - } - // case hideFutureHoursWhenToday=1 shows hours with no visits - if ($maxValue == 0) { - $percent = 0; - } else { - $percent = ($popularity / $maxValue) * 100; - } - // CSS style value - $sizeRange = $this->getClassFromPercent($percent); + $wordTruncated = $this->truncateWordIfNeeded($word); + $percent = $this->getPercentage($popularity, $maxValue); + $sizeRange = $this->getClassFromPercent($percent); $return[$word] = array( 'word' => $word, @@ -146,6 +125,7 @@ class Cloud extends Visualization 'percent' => $percent, ); } + return $return; } @@ -163,10 +143,14 @@ class Cloud extends Visualization shuffle($keys); if (count($keys) && is_array($keys)) { + $tmpArray = $this->wordsArray; + $this->wordsArray = array(); - foreach ($keys as $key => $value) + foreach ($keys as $key => $value) { $this->wordsArray[$value] = $tmpArray[$value]; + } + } } @@ -187,4 +171,29 @@ class Cloud extends Visualization } return 0; } + + /** + * @param $word + * @return string + */ + private function truncateWordIfNeeded($word) + { + if (Common::mb_strlen($word) > $this->truncatingLimit) { + return Common::mb_substr($word, 0, $this->truncatingLimit - 3) . '...'; + } + + return $word; + } + + private function getPercentage($popularity, $maxValue) + { + // case hideFutureHoursWhenToday=1 shows hours with no visits + if ($maxValue == 0) { + return 0; + } + + $percent = ($popularity / $maxValue) * 100; + + return $percent; + } } diff --git a/plugins/CoreVisualizations/Visualizations/Cloud/Config.php b/plugins/CoreVisualizations/Visualizations/Cloud/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..eda61f937d0f409ea6a18a696d232d9eb1227362 --- /dev/null +++ b/plugins/CoreVisualizations/Visualizations/Cloud/Config.php @@ -0,0 +1,37 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik_Plugins + * @package CoreVisualizations + */ + +namespace Piwik\Plugins\CoreVisualizations\Visualizations\Cloud; + +use Piwik\ViewDataTable\Config as VisualizationConfig; + +/** + * DataTable Visualization that derives from HtmlTable and sets show_extra_columns to true. + */ +class Config extends VisualizationConfig +{ + + /** + * Whether to display the logo assocatied with a DataTable row (stored as 'logo' row metadata) + * instead of the label in Tag Clouds. + * + * Default value: false + */ + public $display_logo_instead_of_label = false; + + public function __construct() + { + parent::__construct(); + + $this->addPropertiesThatCanBeOverwrittenByQueryParams(array('display_logo_instead_of_label')); + } + +} \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/Graph.php b/plugins/CoreVisualizations/Visualizations/Graph.php new file mode 100644 index 0000000000000000000000000000000000000000..1d6a47b323eed756a35fb586f16dc75742fce820 --- /dev/null +++ b/plugins/CoreVisualizations/Visualizations/Graph.php @@ -0,0 +1,140 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik + * @package Piwik + */ +namespace Piwik\Plugins\CoreVisualizations\Visualizations; + +use Piwik\DataTable\Row; +use Piwik\DataTable; +use Piwik\Piwik; +use Piwik\Plugin\Visualization; + +/** + * This is an abstract visualization that should be the base of any 'graph' visualization. + * This class defines certain visualization properties that are specific to all graph types. + * Derived visualizations can decide for themselves whether they should support individual + * properties. + * + * @property Graph\Config $config + */ +abstract class Graph extends Visualization +{ + const ID = 'graph'; + + public $selectableRows = array(); + + public static function getDefaultConfig() + { + return new Graph\Config(); + } + + public static function getDefaultRequestConfig() + { + $config = parent::getDefaultRequestConfig(); + $config->addPropertiesThatShouldBeAvailableClientSide(array('columns')); + + return $config; + } + + public function beforeRender() + { + if ($this->config->show_goals) { + $this->config->translations['nb_conversions'] = Piwik::translate('Goals_ColumnConversions'); + $this->config->translations['revenue'] = Piwik::translate('General_TotalRevenue'); + } + } + + public function beforeLoadDataTable() + { + // TODO: this should not be required here. filter_limit should not be a view property, instead HtmlTable should use 'limit' or something, + // and manually set request_parameters_to_modify['filter_limit'] based on that. (same for filter_offset). + $this->requestConfig->request_parameters_to_modify['filter_limit'] = false; + + if ($this->config->max_graph_elements) { + $this->requestConfig->request_parameters_to_modify['filter_truncate'] = $this->config->max_graph_elements - 1; + } + } + + /** + * Determines what rows are selectable and stores them in the selectable_rows property in + * a format the SeriesPicker JavaScript class can use. + */ + public function beforeGenericFiltersAreAppliedToLoadedDataTable() + { + if ($this->config->row_picker_match_rows_by === false) { + return; + } + + // collect all selectable rows + $self = $this; + + $this->dataTable->filter(function ($dataTable) use ($self) { + /** @var DataTable $dataTable */ + + foreach ($dataTable->getRows() as $row) { + $rowLabel = $row->getColumn('label'); + + if (false === $rowLabel) { + continue; + } + + // determine whether row is visible + $isVisible = true; + if ('label' == $self->config->row_picker_match_rows_by) { + $isVisible = in_array($rowLabel, $self->config->rows_to_display); + } + + // build config + if (!isset($self->selectableRows[$rowLabel])) { + $self->selectableRows[$rowLabel] = array( + 'label' => $rowLabel, + 'matcher' => $rowLabel, + 'displayed' => $isVisible + ); + } + } + }); + } + + /** + * Defaults the selectable_columns property if it has not been set and then transforms + * it into something the SeriesPicker JavaScript class can use. + */ + public function afterAllFilteresAreApplied() + { + $this->config->selectable_rows = array_values($this->selectableRows); + + $selectableColumns = $this->config->selectable_columns; + + // set default selectable columns, if none specified + if (false === $selectableColumns) { + $selectableColumns = array('nb_visits', 'nb_actions'); + + if (in_array('nb_uniq_visitors', $this->dataTable->getColumns())) { + $selectableColumns[] = 'nb_uniq_visitors'; + } + } + + if ($this->config->show_goals) { + $goalMetrics = array('nb_conversions', 'revenue'); + $selectableColumns = array_merge($selectableColumns, $goalMetrics); + } + + $transformed = array(); + foreach ($selectableColumns as $column) { + $transformed[] = array( + 'column' => $column, + 'translation' => @$this->config->translations[$column], + 'displayed' => in_array($column, $this->config->columns_to_display) + ); + } + + $this->config->selectable_columns = $transformed; + } +} \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/Graph/Config.php b/plugins/CoreVisualizations/Visualizations/Graph/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..ada068b39ac81178343c3c3719db8db032c3fb7b --- /dev/null +++ b/plugins/CoreVisualizations/Visualizations/Graph/Config.php @@ -0,0 +1,124 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik_Plugins + * @package CoreVisualizations + */ + +namespace Piwik\Plugins\CoreVisualizations\Visualizations\Graph; + +use Piwik\ViewDataTable\Config as VisualizationConfig; + +/** + * DataTable Visualization that derives from HtmlTable and sets show_extra_columns to true. + */ +class Config extends VisualizationConfig +{ + + /** + * Whether the series picker should allow picking more than one series or not. + * + * Default value: true + */ + public $allow_multi_select_series_picker = true; + + /** + * The maximum number of rows to render. All other rows will be aggregated in an 'Others' row. + * + * Default value: false (no limit) + */ + public $max_graph_elements = false; + + /** + * Array property that contains the names of columns that can be selected in the Series Picker. + * + * Default value: false + */ + public $selectable_columns = false; + + /** + * Contains the column (if any) of the values used in the Row Picker. + * + * @see self::ROWS_TO_DISPLAY + * + * Default value: false + */ + public $row_picker_match_rows_by = false; + + /** + * Contains the list of values identifying rows that should be displayed as separate series. + * The values are of a specific column determined by the row_picker_match_rows_by column. + * + * @see self::ROW_PICKER_VALUE_COLUMN + * + * Default value: false + */ + public $rows_to_display = false; + + /** + * Contains the list of values available for the Row Picker. Currently set to be all visible + * rows, if the row_picker_match_rows_by property is set. + * + * @see self::ROW_PICKER_VALUE_COLUMN + */ + public $selectable_rows = 'selectable_rows'; + + /** + * Controls whether all ticks & labels are shown on a graph's x-axis or just some. + * + * Default value: false + */ + public $show_all_ticks = false; + + /** + * If true, a row with totals of each DataTable column is added. + * + * Default value: false + */ + public $add_total_row = false; + + /** + * Controls whether the Series Picker is shown or not. The Series Picker allows users to + * choose between displaying data of different columns. + * + * Default value: true + */ + public $show_series_picker = true; + + /** + * Controls whether the percentage of the total is displayed as a tooltip when hovering over + * data points. + * + * NOTE: Sometimes this percentage is meaningless (when the total of the column values is + * not the total number of elements in the set). In this case the tooltip should not be + * displayed. + * + * Default value: true + */ + public $display_percentage_in_tooltip = true; + + public function __construct() + { + parent::__construct(); + + $this->show_limit_control = false; + + $this->addPropertiesThatShouldBeAvailableClientSide(array( + 'show_series_picker', + 'allow_multi_select_series_picker', + 'selectable_columns', + 'selectable_rows', + 'display_percentage_in_tooltip' + )); + + $this->addPropertiesThatCanBeOverwrittenByQueryParams(array( + 'show_all_ticks', + 'show_series_picker' + )); + } + +} \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable.php b/plugins/CoreVisualizations/Visualizations/HtmlTable.php index bc7704812699d83fe3827d3e85b4bd163f917750..87b297921eb20f19fdd617eaf6439b312c206ccd 100644 --- a/plugins/CoreVisualizations/Visualizations/HtmlTable.php +++ b/plugins/CoreVisualizations/Visualizations/HtmlTable.php @@ -11,180 +11,41 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations; use Piwik\Common; -use Piwik\Config; use Piwik\DataTable\Filter\AddColumnsProcessedMetricsGoal; use Piwik\MetricsFormatter; use Piwik\Piwik; use Piwik\Plugins\Goals\API as APIGoals; use Piwik\Site; use Piwik\View; -use Piwik\ViewDataTable\Visualization; -use Piwik\Visualization\Config as VizConfig; - -require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php'; -require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/HtmlTable/Goals.php'; +use Piwik\Plugin\Visualization; /** * DataTable visualization that shows DataTable data in an HTML table. + * + * @property HtmlTable\Config $config */ class HtmlTable extends Visualization { const ID = 'table'; - const TEMPLATE_FILE = "@CoreVisualizations/_dataTableViz_htmlTable.twig"; - /** - * If this property is set to true, subtables will be shown as embedded in the original table. - * If false, subtables will be shown as whole tables between rows. - * - * Default value: false - */ - const SHOW_EMBEDDED_SUBTABLE = 'show_embedded_subtable'; - - /** - * Controls whether the entire DataTable should be rendered (including subtables) or just one - * specific table in the tree. - * - * Default value: false - */ - const SHOW_EXPANDED = 'show_expanded'; - - /** - * When showing an expanded datatable, this property controls whether rows with subtables are - * replaced with their subtables, or if they are shown alongside their subtables. - * - * Default value: false - */ - const REPLACE_ROW_WITH_SUBTABLE = 'replace_row_with_subtable'; - - /** - * Controls whether any DataTable Row Action icons are shown. If true, no icons are shown. - * - * @see also self::DISABLE_ROW_EVOLUTION - * - * Default value: false - */ - const DISABLE_ROW_ACTIONS = 'disable_row_actions'; - - /** - * Controls whether the row evolution DataTable Row Action icon is shown or not. - * - * @see also self::DISABLE_ROW_ACTIONS - * - * Default value: false - */ - const DISABLE_ROW_EVOLUTION = 'disable_row_evolution'; - - /** - * If true, the 'label', 'nb_visits', 'nb_uniq_visitors' (if present), 'nb_actions', - * 'nb_actions_per_visit', 'avg_time_on_site', 'bounce_rate' and 'conversion_rate' (if - * goals view is not allowed) are displayed. - * - * Default value: false - */ - const SHOW_EXTRA_COLUMNS = 'show_extra_columns'; - - /** - * If true, conversions for each existing goal will be displayed for the visits in - * each row. - * - * Default value: false - */ - const SHOW_GOALS_COLUMNS = 'show_goals_columns'; - - /** - * If true, subtables will not be loaded when rows are clicked, but only if the - * 'show_goals_columns' property is also true. - * - * @see also self::SHOW_GOALS_COLUMNS - * - * Default value: false - */ - const DISABLE_SUBTABLE_IN_GOALS_VIEW = 'disable_subtable_when_show_goals'; - - /** - * Controls whether the summary row is displayed on every page of the datatable view or not. - * If false, the summary row will be treated as the last row of the dataset and will only visible - * when viewing the last rows. - * - * Default value: false - */ - const KEEP_SUMMARY_ROW = 'keep_summary_row'; - - /** - * If true, the summary row will be colored differently than all other DataTable rows. - * - * @see also self::KEEP_SUMMARY_ROW - * - * Default value: false - */ - const HIGHLIGHT_SUMMARY_ROW = 'highlight_summary_row'; - - static public $clientSideRequestParameters = array( - 'search_recursive', - 'filter_limit', - 'filter_offset', - 'filter_sort_column', - 'filter_sort_order', - ); - - static public $clientSideConfigProperties = array( - 'show_extra_columns', - 'show_goals_columns', - 'disable_row_evolution', - 'disable_row_actions', - 'enable_sort', - 'keep_summary_row', - 'subtable_controller_action', - ); - - public static $overridableProperties = array( - 'show_expanded', - 'disable_row_actions', - 'disable_row_evolution', - 'show_extra_columns', - 'show_goals_columns', - 'disable_subtable_when_show_goals', - 'keep_summary_row', - 'highlight_summary_row', - ); + public static function getDefaultConfig() + { + return new HtmlTable\Config(); + } - public function configureVisualization(VizConfig $properties) + public static function getDefaultRequestConfig() { - if (Common::getRequestVar('idSubtable', false) - && $properties->visualization_properties->show_embedded_subtable - ) { - $properties->show_visualization_only = true; - } + return new HtmlTable\RequestConfig(); } - public static function getDefaultPropertyValues() + public function beforeRender() { - $defaults = array( - 'enable_sort' => true, - 'datatable_js_type' => 'DataTable', - 'filter_limit' => Config::getInstance()->General['datatable_default_limit'], - 'visualization_properties' => array( - 'table' => array( - 'disable_row_evolution' => false, - 'disable_row_actions' => false, - 'show_extra_columns' => false, - 'show_goals_columns' => false, - 'disable_subtable_when_show_goals' => false, - 'keep_summary_row' => false, - 'highlight_summary_row' => false, - 'show_expanded' => false, - 'show_embedded_subtable' => false - ), - ), - ); + if ($this->requestConfig->idSubtable + && $this->config->show_embedded_subtable) { - if (Common::getRequestVar('enable_filter_excludelowpop', false) == '1') { - $defaults['filter_excludelowpop'] = 'nb_visits'; - $defaults['filter_excludelowpop_value'] = false; + $this->config->show_visualization_only = true; } - - return $defaults; } } \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php b/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php index 04d50f3d8be96e393b2b57c2aa8bb3f745379b54..4a8a51c55e925ae73066fcb5e7cc363cb0ae475f 100644 --- a/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php +++ b/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php @@ -11,9 +11,7 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; -use Piwik\DataTable\DataTableInterface; use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; -use Piwik\Visualization\Config; use Piwik\Common; use Piwik\DataTable\Filter\AddColumnsProcessedMetricsGoal; use Piwik\MetricsFormatter; @@ -21,8 +19,6 @@ use Piwik\Piwik; use Piwik\Plugins\Goals\API as APIGoals; use Piwik\Site; use Piwik\View; -use Piwik\ViewDataTable\Visualization; -use Piwik\Visualization\Request; /** * DataTable Visualization that derives from HtmlTable and sets show_extra_columns to true. @@ -31,21 +27,22 @@ class AllColumns extends HtmlTable { const ID = 'tableAllColumns'; - public function configureVisualization(Config $properties) + public function beforeRender() { - $properties->visualization_properties->show_extra_columns = true; + $this->config->show_extra_columns = true; + $this->config->datatable_css_class = 'dataTableVizAllColumns'; + $this->config->show_exclude_low_population = true; - $properties->show_exclude_low_population = true; - $properties->datatable_css_class = 'dataTableVizAllColumns'; - - parent::configureVisualization($properties); + parent::beforeRender(); } - public function beforeGenericFiltersAreAppliedToLoadedDataTable(DataTableInterface $dataTable, Config $properties, Request $request) + public function beforeGenericFiltersAreAppliedToLoadedDataTable() { - $dataTable->filter('AddColumnsProcessedMetrics'); + $this->dataTable->filter('AddColumnsProcessedMetrics'); + + $properties = $this->config; - $dataTable->filter(function ($dataTable) use ($properties) { + $this->dataTable->filter(function ($dataTable) use ($properties) { $columnsToDisplay = array('label', 'nb_visits'); if (in_array('nb_uniq_visitors', $dataTable->getColumns())) { @@ -66,9 +63,10 @@ class AllColumns extends HtmlTable }); } - public function afterGenericFiltersAreAppliedToLoadedDataTable(DataTableInterface $dataTable, Config $properties, Request $request) + public function afterGenericFiltersAreAppliedToLoadedDataTable() { $prettifyTime = array('\Piwik\MetricsFormatter', 'getPrettyTimeFromSeconds'); - $dataTable->filter('ColumnCallbackReplace', array('avg_time_on_site', $prettifyTime)); + + $this->dataTable->filter('ColumnCallbackReplace', array('avg_time_on_site', $prettifyTime)); } } \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable/Config.php b/plugins/CoreVisualizations/Visualizations/HtmlTable/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..10a72cc1523ac8e2e127b14f926f586ef8c9847b --- /dev/null +++ b/plugins/CoreVisualizations/Visualizations/HtmlTable/Config.php @@ -0,0 +1,121 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik_Plugins + * @package CoreVisualizations + */ + +namespace Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; + +use Piwik\Common; +use Piwik\ViewDataTable\Config as VisualizationConfig; +/** + * DataTable Visualization that derives from HtmlTable and sets show_extra_columns to true. + */ +class Config extends VisualizationConfig +{ + + /** + * If this property is set to true, subtables will be shown as embedded in the original table. + * If false, subtables will be shown as whole tables between rows. + * + * Default value: false + */ + public $show_embedded_subtable = false; + + /** + * Controls whether the entire DataTable should be rendered (including subtables) or just one + * specific table in the tree. + * + * Default value: false + */ + public $show_expanded = false; + + /** + * When showing an expanded datatable, this property controls whether rows with subtables are + * replaced with their subtables, or if they are shown alongside their subtables. + * + * Default value: false + */ + public $replace_row_with_subtable = false; + + /** + * Controls whether any DataTable Row Action icons are shown. If true, no icons are shown. + * + * Default value: false + */ + public $disable_row_actions = false; + + /** + * Controls whether the row evolution DataTable Row Action icon is shown or not. + * + * Default value: false + */ + public $disable_row_evolution = false; + + /** + * If true, the 'label', 'nb_visits', 'nb_uniq_visitors' (if present), 'nb_actions', + * 'nb_actions_per_visit', 'avg_time_on_site', 'bounce_rate' and 'conversion_rate' (if + * goals view is not allowed) are displayed. + * + * Default value: false + */ + public $show_extra_columns = false; + + /** + * If true, conversions for each existing goal will be displayed for the visits in + * each row. + * + * Default value: false + */ + public $show_goals_columns = false; + + /** + * If true, subtables will not be loaded when rows are clicked, but only if the + * 'show_goals_columns' property is also true. + * + * Default value: false + */ + public $disable_subtable_when_show_goals = false; + + /** + * If true, the summary row will be colored differently than all other DataTable rows. + * + * Default value: false + */ + public $highlight_summary_row = false; + + public function __construct() + { + parent::__construct(); + + $this->enable_sort = true; + $this->datatable_js_type = 'DataTable'; + + $this->addPropertiesThatShouldBeAvailableClientSide(array( + 'show_extra_columns', + 'show_goals_columns', + 'disable_row_evolution', + 'disable_row_actions', + 'enable_sort', + 'keep_summary_row', + 'subtable_controller_action', + )); + + $this->addPropertiesThatCanBeOverwrittenByQueryParams(array( + 'show_expanded', + 'disable_row_actions', + 'disable_row_evolution', + 'show_extra_columns', + 'show_goals_columns', + 'disable_subtable_when_show_goals', + 'keep_summary_row', + 'highlight_summary_row', + )); + } + +} \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable/RequestConfig.php b/plugins/CoreVisualizations/Visualizations/HtmlTable/RequestConfig.php new file mode 100644 index 0000000000000000000000000000000000000000..5fc97a398d788b62fd9604ac495d53d5b711b308 --- /dev/null +++ b/plugins/CoreVisualizations/Visualizations/HtmlTable/RequestConfig.php @@ -0,0 +1,56 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik_Plugins + * @package CoreVisualizations + */ + +namespace Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; + +use Piwik\Common; +use Piwik\ViewDataTable\RequestConfig as VisualizationRequestConfig; +use Piwik\Config as PiwikConfig; + +/** + * DataTable Visualization that derives from HtmlTable and sets show_extra_columns to true. + */ +class RequestConfig extends VisualizationRequestConfig +{ + + /** + * Controls whether the summary row is displayed on every page of the datatable view or not. + * If false, the summary row will be treated as the last row of the dataset and will only visible + * when viewing the last rows. + * + * Default value: false + */ + public $keep_summary_row = false; + + public function __construct() + { + $this->filter_limit = PiwikConfig::getInstance()->General['datatable_default_limit']; + + if (Common::getRequestVar('enable_filter_excludelowpop', false) == '1') { + $this->filter_excludelowpop = 'nb_visits'; + $this->filter_excludelowpop_value = false; + } + + $this->addPropertiesThatShouldBeAvailableClientSide(array( + 'search_recursive', + 'filter_limit', + 'filter_offset', + 'filter_sort_column', + 'filter_sort_order', + 'keep_summary_row' + )); + + $this->addPropertiesThatCanBeOverwrittenByQueryParams(array( + 'keep_summary_row', + )); + } + +} \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph.php index 9e4550326481bde5ef759af6c83247ba45a8debb..b3ca71dfe91f864f09f41f3d5d69edd4ce760cb4 100644 --- a/plugins/CoreVisualizations/Visualizations/JqplotGraph.php +++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph.php @@ -14,82 +14,35 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations; use Piwik\DataTable; use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator; use Piwik\View; -use Piwik\ViewDataTable\Graph; -use Piwik\Visualization\Config; -use Piwik\Visualization\Request; /** * DataTable visualization that displays DataTable data in a JQPlot graph. * TODO: should merge all this logic w/ jqplotdatagenerator & 'Chart' visualizations. + * + * @property JqplotGraph\Config $config */ -class JqplotGraph extends Graph +abstract class JqplotGraph extends Graph { const ID = 'jqplot_graph'; const TEMPLATE_FILE = '@CoreVisualizations/_dataTableViz_jqplotGraph.twig'; - /** - * The name of the JavaScript class to use as this graph's external series toggle. The class - * must be a subclass of JQPlotExternalSeriesToggle. - * - * @see self::EXTERNAL_SERIES_TOGGLE_SHOW_ALL - * - * Default value: false - */ - const EXTERNAL_SERIES_TOGGLE = 'external_series_toggle'; - - /** - * Whether the graph should show all loaded series upon initial display. - * - * @see self::EXTERNAL_SERIES_TOGGLE - * - * Default value: false - */ - const EXTERNAL_SERIES_TOGGLE_SHOW_ALL = 'external_series_toggle_show_all'; - - /** - * The number of x-axis ticks for each x-axis label. - * - * Default: 2 - */ - const X_AXIS_STEP_SIZE = 'x_axis_step_size'; - - public static $clientSideConfigProperties = array( - 'external_series_toggle', - 'external_series_toggle_show_all' - ); - - public static $overridableProperties = array('x_axis_step_size'); - - /** - * Returns an array mapping property names with default values for this visualization. - * - * @return array - */ - public static function getDefaultPropertyValues() + public static function getDefaultConfig() { - $result = parent::getDefaultPropertyValues(); - return array_merge_recursive($result, array( - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_exclude_low_population' => false, - 'show_search' => false, - 'show_export_as_image_icon' => true, - 'y_axis_unit' => '', - 'visualization_properties' => array( - 'jqplot_graph' => array( - 'external_series_toggle' => false, - 'external_series_toggle_show_all' => false, - 'x_axis_step_size' => 2 - ) - ) - )); + return new JqplotGraph\Config(); } public function getGraphData($dataTable, $properties) { $dataGenerator = $this->makeDataGenerator($properties); + return $dataGenerator->generate($dataTable); } + + /** + * @param $properties + * @return JqplotDataGenerator + */ + abstract protected function makeDataGenerator($properties); } require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php'; diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php index bb364e5f761d9c171e740ea101ebdea8be520ce4..7973da33be059b55b958ebd042bac266e9f174f7 100644 --- a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php +++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Bar.php @@ -13,7 +13,6 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph; use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator; use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph; -use Piwik\Visualization\Config; /** * Visualization that renders HTML for a Bar graph using jqPlot. @@ -22,18 +21,19 @@ class Bar extends JqplotGraph { const ID = 'graphVerticalBar'; - public function configureVisualization(Config $properties) + public function beforeRender() { - parent::configureVisualization($properties); + parent::beforeRender(); - $properties->datatable_js_type = 'JqplotBarGraphDataTable'; + $this->config->datatable_js_type = 'JqplotBarGraphDataTable'; } - public static function getDefaultPropertyValues() + public static function getDefaultConfig() { - $result = parent::getDefaultPropertyValues(); - $result['visualization_properties']['graph']['max_graph_elements'] = 6; - return $result; + $config = new Config(); + $config->max_graph_elements = 6; + + return $config; } protected function makeDataGenerator($properties) diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Config.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..25dc9f38426ac7bfb33fca103c327ddf27a0f5bb --- /dev/null +++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Config.php @@ -0,0 +1,67 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik_Plugins + * @package CoreVisualizations + */ + +namespace Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph; + +use Piwik\Plugins\CoreVisualizations\Visualizations\Graph\Config as GraphConfig; + +/** + * DataTable Visualization that derives from HtmlTable and sets show_extra_columns to true. + */ +class Config extends GraphConfig +{ + /** + * The name of the JavaScript class to use as this graph's external series toggle. The class + * must be a subclass of JQPlotExternalSeriesToggle. + * + * @see self::EXTERNAL_SERIES_TOGGLE_SHOW_ALL + * + * Default value: false + */ + public $external_series_toggle = false; + + /** + * Whether the graph should show all loaded series upon initial display. + * + * @see self::EXTERNAL_SERIES_TOGGLE + * + * Default value: false + */ + public $external_series_toggle_show_all = false; + + /** + * The number of x-axis ticks for each x-axis label. + * + * Default: 2 + */ + public $x_axis_step_size = 2; + + public function __construct() + { + parent::__construct(); + + $this->show_exclude_low_population = false; + $this->show_offset_information = false; + $this->show_pagination_control = false; + $this->show_exclude_low_population = false; + $this->show_search = false; + $this->show_export_as_image_icon = true; + $this->y_axis_unit = ''; + + $this->addPropertiesThatShouldBeAvailableClientSide(array( + 'external_series_toggle', + 'external_series_toggle_show_all' + )); + + $this->addPropertiesThatCanBeOverwrittenByQueryParams(array('x_axis_step_size')); + } + +} \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution.php index 75f07864270cb937e847ec218651317f93e95c70..921ed01e5db586bf6df432d4c141afe13796ce45 100644 --- a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution.php +++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution.php @@ -13,78 +13,59 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph; use Piwik\Common; use Piwik\DataTable; -use Piwik\DataTable\DataTableInterface; use Piwik\Period\Range; use Piwik\Plugin\Controller; use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator; use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph; use Piwik\Site; -use Piwik\Visualization\Config; -use Piwik\Visualization\Request; /** * Visualization that renders HTML for a line graph using jqPlot. + * + * @property Evolution\Config $config */ class Evolution extends JqplotGraph { const ID = 'graphEvolution'; const SERIES_COLOR_COUNT = 8; - /** - * Whether to show a line graph or a bar graph. - * - * Default value: true - */ - const SHOW_LINE_GRAPH = 'show_line_graph'; - - public static $clientSideConfigProperties = array('show_line_graph'); - - public static $overridableProperties = array('show_line_graph'); - - public function configureVisualization(Config $properties) + public static function getDefaultConfig() { - $this->calculateEvolutionDateRange($properties); + return new Evolution\Config(); + } - parent::configureVisualization($properties); + public function beforeRender() + { + parent::beforeRender(); - $properties->datatable_js_type = 'JqplotEvolutionGraphDataTable'; + $this->config->datatable_js_type = 'JqplotEvolutionGraphDataTable'; } - public function beforeLoadDataTable(Request $request, Config $properties) + public function beforeLoadDataTable() { - parent::beforeLoadDataTable($request, $properties); + $this->calculateEvolutionDateRange(); + + parent::beforeLoadDataTable(); // period will be overridden when 'range' is requested in the UI // but the graph will display for each day of the range. // Default 'range' behavior is to return the 'sum' for the range if (Common::getRequestVar('period', false) == 'range') { - $request->request_parameters_to_modify['period'] = 'day'; + $this->requestConfig->request_parameters_to_modify['period'] = 'day'; } } - public function afterAllFilteresAreApplied(DataTableInterface $dataTable, Config $properties, Request $request) + public function afterAllFilteresAreApplied() { - parent::afterAllFilteresAreApplied($dataTable, $properties, $request); + parent::afterAllFilteresAreApplied(); - if ($properties->visualization_properties->x_axis_step_size === false) { + if (false === $this->config->x_axis_step_size) { + $rowCount = $this->dataTable->getRowsCount(); - $size = $this->getDefaultXAxisStepSize($dataTable->getRowsCount()); - $properties->visualization_properties->x_axis_step_size = $size; + $this->config->x_axis_step_size = $this->getDefaultXAxisStepSize($rowCount); } } - public static function getDefaultPropertyValues() - { - $result = parent::getDefaultPropertyValues(); - $result['show_all_views_icons'] = false; - $result['show_table'] = false; - $result['show_table_all_columns'] = false; - $result['hide_annotations_view'] = false; - $result['visualization_properties']['jqplot_graph']['x_axis_step_size'] = false; - $result['visualization_properties']['graphEvolution']['show_line_graph'] = true; - return $result; - } - protected function makeDataGenerator($properties) { return JqplotDataGenerator::factory('evolution', $properties); @@ -94,29 +75,34 @@ class Evolution extends JqplotGraph * Based on the period, date and evolution_{$period}_last_n query parameters, * calculates the date range this evolution chart will display data for. */ - private function calculateEvolutionDateRange(Config $properties) + private function calculateEvolutionDateRange() { - $view = $this->viewDataTable; $period = Common::getRequestVar('period'); $defaultLastN = self::getDefaultLastN($period); $originalDate = Common::getRequestVar('date', 'last' . $defaultLastN, 'string'); - if ($period != 'range') { // show evolution limit if the period is not a range - $properties->show_limit_control = true; + if ('range' != $period) { // show evolution limit if the period is not a range + $this->config->show_limit_control = true; // set the evolution_{$period}_last_n query param - if (Range::parseDateRange($originalDate)) { // if a multiple period + if (Range::parseDateRange($originalDate)) { + // if a multiple period + // overwrite last_n param using the date range $oPeriod = new Range($period, $originalDate); - $lastN = count($oPeriod->getSubperiods()); - } else { // if not a multiple period + $lastN = count($oPeriod->getSubperiods()); + + } else { + + // if not a multiple period list($newDate, $lastN) = self::getDateRangeAndLastN($period, $originalDate, $defaultLastN); - $view->request_parameters_to_modify['date'] = $newDate; - $properties->custom_parameters['dateUsedInGraph'] = $newDate; + $this->requestConfig->request_parameters_to_modify['date'] = $newDate; + $this->config->custom_parameters['dateUsedInGraph'] = $newDate; } + $lastNParamName = self::getLastNParamName($period); - $properties->custom_parameters[$lastNParamName] = $lastN; + $this->config->custom_parameters[$lastNParamName] = $lastN; } } @@ -188,6 +174,7 @@ class Evolution extends JqplotGraph } $periodLabel = Common::getRequestVar('period'); + switch ($periodLabel) { case 'day': case 'range': @@ -208,6 +195,7 @@ class Evolution extends JqplotGraph } $paddedCount = $countGraphElements + 2; // pad count so last label won't be cut off + return ceil($paddedCount / $steps); } } \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution/Config.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..7d3ac54bcc110b77f549a42d87bed43e5d6cfccf --- /dev/null +++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Evolution/Config.php @@ -0,0 +1,43 @@ +<?php +/** + * Piwik - Open source web analytics + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * @category Piwik_Plugins + * @package CoreVisualizations + */ + +namespace Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution; + +use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Config as JqplotGraphConfig; + +/** + * DataTable Visualization that derives from HtmlTable and sets show_extra_columns to true. + */ +class Config extends JqplotGraphConfig +{ + /** + * Whether to show a line graph or a bar graph. + * + * Default value: true + */ + public $show_line_graph = true; + + public function __construct() + { + parent::__construct(); + + $this->show_all_views_icons = false; + $this->show_table = false; + $this->show_table_all_columns = false; + $this->hide_annotations_view = false; + $this->x_axis_step_size = false; + $this->show_line_graph = true; + + $this->addPropertiesThatShouldBeAvailableClientSide(array('show_line_graph')); + $this->addPropertiesThatCanBeOverwrittenByQueryParams(array('show_line_graph')); + } + +} \ No newline at end of file diff --git a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Pie.php b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Pie.php index e6db071c9ff9787b64ca372cb69b79657572a7c1..5411979ab541c5c35c07e1831e7565d33e6e4c54 100644 --- a/plugins/CoreVisualizations/Visualizations/JqplotGraph/Pie.php +++ b/plugins/CoreVisualizations/Visualizations/JqplotGraph/Pie.php @@ -11,11 +11,8 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph; -use Piwik\DataTable\DataTableInterface; use Piwik\Plugins\CoreVisualizations\JqplotDataGenerator; use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph; -use Piwik\Visualization\Config; -use Piwik\Visualization\Request; /** * Visualization that renders HTML for a Pie graph using jqPlot. @@ -24,33 +21,34 @@ class Pie extends JqplotGraph { const ID = 'graphPie'; - public function configureVisualization(Config $properties) + public static function getDefaultConfig() { - parent::configureVisualization($properties); + $config = new Config(); + $config->max_graph_elements = 6; + $config->allow_multi_select_series_picker = false; - $properties->visualization_properties->show_all_ticks = true; - $properties->datatable_js_type = 'JqplotPieGraphDataTable'; + return $config; } - public function afterAllFilteresAreApplied(DataTableInterface $dataTable, Config $properties, Request $request) + public function beforeRender() { - parent::afterAllFilteresAreApplied($dataTable, $properties, $request); + parent::beforeRender(); - $metricColumn = reset($properties->columns_to_display); + $this->config->show_all_ticks = true; + $this->config->datatable_js_type = 'JqplotPieGraphDataTable'; + } + + public function afterAllFilteresAreApplied() + { + parent::afterAllFilteresAreApplied(); + + $metricColumn = reset($this->config->columns_to_display); if ($metricColumn == 'label') { - $metricColumn = next($properties->columns_to_display); + $metricColumn = next($this->config->columns_to_display); } - $properties->columns_to_display = array($metricColumn ? : 'nb_visits'); - } - - public static function getDefaultPropertyValues() - { - $result = parent::getDefaultPropertyValues(); - $result['visualization_properties']['graph']['max_graph_elements'] = 6; - $result['visualization_properties']['graph']['allow_multi_select_series_picker'] = false; - return $result; + $this->config->columns_to_display = array($metricColumn ? : 'nb_visits'); } protected function makeDataGenerator($properties) diff --git a/core/ViewDataTable/Sparkline.php b/plugins/CoreVisualizations/Visualizations/Sparkline.php similarity index 90% rename from core/ViewDataTable/Sparkline.php rename to plugins/CoreVisualizations/Visualizations/Sparkline.php index 5197c8b671686add9dc0815998e70ccaf72cf2d7..338dcb611ddeb1a3c6a1401645a1d011324a62c2 100644 --- a/core/ViewDataTable/Sparkline.php +++ b/plugins/CoreVisualizations/Visualizations/Sparkline.php @@ -8,12 +8,12 @@ * @category Piwik * @package Piwik */ -namespace Piwik\ViewDataTable; +namespace Piwik\Plugins\CoreVisualizations\Visualizations; use Exception; use Piwik\Common; use Piwik\DataTable; -use Piwik\ViewDataTable; +use Piwik\Plugin\ViewDataTable; /** * Reads the requested DataTable from the API and prepare data for the Sparkline view. @@ -23,15 +23,7 @@ use Piwik\ViewDataTable; */ class Sparkline extends ViewDataTable { - /** - * Returns dataTable id for view - * - * @return string - */ - public function getViewDataTableId() - { - return 'sparkline'; - } + const ID = 'sparkline'; /** * @see ViewDataTable::main() @@ -44,7 +36,9 @@ class Sparkline extends ViewDataTable if ($period == 'range') { $_GET['period'] = 'day'; } + $this->loadDataTableFromAPI(); + // then revert the hack for potentially subsequent getRequestVar $_GET['period'] = $period; @@ -81,14 +75,19 @@ class Sparkline extends ViewDataTable protected function getValuesFromDataTableMap($dataTableMap, $columnToPlot) { $dataTableMap->applyQueuedFilters(); + $values = array(); + foreach ($dataTableMap->getDataTables() as $table) { + if ($table->getRowsCount() > 1) { throw new Exception("Expecting only one row per DataTable"); } - $value = 0; + + $value = 0; $onlyRow = $table->getFirstRow(); - if ($onlyRow !== false) { + + if (false !== $onlyRow) { if (!empty($columnToPlot)) { $value = $onlyRow->getColumn($columnToPlot); } // if not specified, we load by default the first column found @@ -98,29 +97,36 @@ class Sparkline extends ViewDataTable $value = current($columns); } } + $values[] = $value; } + return $values; } protected function getValuesFromDataTable($dataTable) { - $columns = $this->vizConfig->columns_to_display; + $columns = $this->config->columns_to_display; + $columnToPlot = false; + if (!empty($columns)) { $columnToPlot = reset($columns); if ($columnToPlot == 'label') { $columnToPlot = next($columns); } } - $values = false; + // a Set is returned when using the normal code path to request data from Archives, in all core plugins // however plugins can also return simple datatable, hence why the sparkline can accept both data types if ($this->dataTable instanceof DataTable\Map) { $values = $this->getValuesFromDataTableMap($dataTable, $columnToPlot); } elseif ($this->dataTable instanceof DataTable) { $values = $this->dataTable->getColumn($columnToPlot); + } else { + $values = false; } + return $values; } } diff --git a/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig b/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig index f18a7afa99c09f75fce0eae127ee8c5e9cf10d58..a0f868288174e2d3022e795a21ce82983c0b48de 100644 --- a/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig +++ b/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig @@ -1,6 +1,6 @@ -{%- set subtablesAreDisabled = properties.visualization_properties.show_goals_columns|default(false) - and properties.visualization_properties.disable_subtable_when_show_goals|default(false) -%} -{%- set showingEmbeddedSubtable = properties.visualization_properties.show_embedded_subtable is not empty +{%- set subtablesAreDisabled = properties.show_goals_columns|default(false) + and properties.disable_subtable_when_show_goals|default(false) -%} +{%- set showingEmbeddedSubtable = properties.show_embedded_subtable is not empty and idSubtable|default(false) -%} {% if error is defined %} {{ error.message }} @@ -18,13 +18,13 @@ {% else %} {%- for rowId, row in dataTable.getRows() -%} {%- set rowHasSubtable = not subtablesAreDisabled and row.getIdSubDataTable() and properties.subtable_controller_action is not null -%} - {%- set shouldHighlightRow = rowId == constant('Piwik\\DataTable::ID_SUMMARY_ROW') and properties.visualization_properties.highlight_summary_row -%} + {%- set shouldHighlightRow = rowId == constant('Piwik\\DataTable::ID_SUMMARY_ROW') and properties.highlight_summary_row -%} {# display this row if it doesn't have a subtable or if we don't replace the row with the subtable #} {%- set showRow = subtablesAreDisabled or not rowHasSubtable - or not properties.visualization_properties.show_expanded|default(false) - or not properties.visualization_properties.replace_row_with_subtable|default(false) -%} + or not properties.show_expanded|default(false) + or not properties.replace_row_with_subtable|default(false) -%} {% if showRow %} <tr {% if rowHasSubtable %}id="{{ row.getIdSubDataTable() }}"{% endif %} @@ -36,9 +36,9 @@ {% endfor %} </tr> {% endif %} - + {# display subtable if present and showing expanded datatable #} - {% if properties.visualization_properties.show_expanded|default(false) and rowHasSubtable %} + {% if properties.show_expanded|default(false) and rowHasSubtable %} {% include "@CoreVisualizations/_dataTableViz_htmlTable.twig" with {'dataTable': row.getSubtable(), 'idSubtable': row.getIdSubDataTable()} %} {% endif %} {%- endfor -%} diff --git a/plugins/CustomVariables/CustomVariables.php b/plugins/CustomVariables/CustomVariables.php index 763ee09634bbf4fe3880f0bd852b774364dd9cc5..63c85655e31ce6ffa8ebc3fc0f1303a43db797fb 100644 --- a/plugins/CustomVariables/CustomVariables.php +++ b/plugins/CustomVariables/CustomVariables.php @@ -13,6 +13,7 @@ namespace Piwik\Plugins\CustomVariables; use Piwik\ArchiveProcessor; use Piwik\Menu\MenuMain; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; use Piwik\Tracker; use Piwik\WidgetsList; @@ -34,14 +35,14 @@ class CustomVariables extends \Piwik\Plugin public function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'WidgetsList.addWidgets' => 'addWidgets', - 'Menu.Reporting.addItems' => 'addMenus', - 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'WidgetsList.addWidgets' => 'addWidgets', + 'Menu.Reporting.addItems' => 'addMenus', + 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.configure' => 'configureViewDataTable', ); return $hooks; } @@ -152,39 +153,40 @@ class CustomVariables extends \Piwik\Plugin } } - public function getReportDisplayProperties(&$properties) + public function configureViewDataTable(ViewDataTable $view) { - $properties['CustomVariables.getCustomVariables'] = $this->getDisplayPropertiesForGetCustomVariables(); - $properties['CustomVariables.getCustomVariablesValuesFromNameId'] = - $this->getDisplayPropertiesForGetCustomVariablesValuesFromNameId(); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'CustomVariables.getCustomVariables': + $this->configureViewForGetCustomVariables($view); + break; + case 'CustomVariables.getCustomVariablesValuesFromNameId': + $this->configureViewForGetCustomVariablesValuesFromNameId($view); + break; + } } - private function getDisplayPropertiesForGetCustomVariables() + private function configureViewForGetCustomVariables(ViewDataTable $view) { $footerMessage = Piwik::translate('CustomVariables_TrackingHelp', array('<a target="_blank" href="http://piwik.org/docs/custom-variables/">', '</a>')); - return array( - 'columns_to_display' => array('label', 'nb_actions', 'nb_visits'), - 'filter_sort_column' => 'nb_actions', - 'filter_sort_order' => 'desc', - 'show_goals' => true, - 'subtable_controller_action' => 'getCustomVariablesValuesFromNameId', - 'translations' => array('label' => Piwik::translate('CustomVariables_ColumnCustomVariableName')), - 'show_footer_message' => $footerMessage - ); + $view->config->columns_to_display = array('label', 'nb_actions', 'nb_visits'); + $view->config->show_goals = true; + $view->config->subtable_controller_action = 'getCustomVariablesValuesFromNameId'; + $view->config->show_footer_message = $footerMessage; + $view->config->addTranslation('label', Piwik::translate('CustomVariables_ColumnCustomVariableName')); + $view->requestConfig->filter_sort_column = 'nb_actions'; + $view->requestConfig->filter_sort_order = 'desc'; } - private function getDisplayPropertiesForGetCustomVariablesValuesFromNameId() + private function configureViewForGetCustomVariablesValuesFromNameId(ViewDataTable $view) { - return array( - 'columns_to_display' => array('label', 'nb_actions', 'nb_visits'), - 'filter_sort_column' => 'nb_actions', - 'filter_sort_order' => 'desc', - 'show_goals' => true, - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate('CustomVariables_ColumnCustomVariableValue')) - ); + $view->config->columns_to_display = array('label', 'nb_actions', 'nb_visits'); + $view->config->show_goals = true; + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('CustomVariables_ColumnCustomVariableValue')); + $view->requestConfig->filter_sort_column = 'nb_actions'; + $view->requestConfig->filter_sort_order = 'desc'; } } diff --git a/plugins/DBStats/DBStats.php b/plugins/DBStats/DBStats.php index be12d261fa856f28b5e32b07ab752ff8224f9e3f..52535defdacb6c846fe8c01b8acb56f2e5ae2136 100644 --- a/plugins/DBStats/DBStats.php +++ b/plugins/DBStats/DBStats.php @@ -16,8 +16,12 @@ use Piwik\Date; use Piwik\Menu\MenuAdmin; use Piwik\Option; use Piwik\Piwik; +use Piwik\Plugins\CoreVisualizations\Visualizations\Graph; +use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; +use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Pie; use Piwik\ScheduledTask; use Piwik\ScheduledTime\Weekly; +use \Piwik\Plugin\ViewDataTable; /** * @@ -33,10 +37,11 @@ class DBStats extends \Piwik\Plugin public function getListHooksRegistered() { return array( - 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', - 'Menu.Admin.addItems' => 'addMenu', - 'TaskScheduler.getScheduledTasks' => 'getScheduledTasks', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', + 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', + 'Menu.Admin.addItems' => 'addMenu', + 'TaskScheduler.getScheduledTasks' => 'getScheduledTasks', + 'ViewDataTable.configure' => 'configureViewDataTable', + 'Visualization.getDefaultViewTypeForReports' => 'getDefaultViewTypeForReports' ); } @@ -88,28 +93,63 @@ class DBStats extends \Piwik\Plugin return Option::get(self::TIME_OF_LAST_TASK_RUN_OPTION); } - public function getReportDisplayProperties(&$properties) + public function getDefaultViewTypeForReports(&$defaultViewTypes) { - $properties['DBStats.getDatabaseUsageSummary'] = $this->getDisplayPropertiesForGetDatabaseUsageSummary(); - $properties['DBStats.getTrackerDataSummary'] = $this->getDisplayPropertiesForGetTrackerDataSummary(); - $properties['DBStats.getMetricDataSummary'] = $this->getDisplayPropertiesForGetMetricDataSummary(); - $properties['DBStats.getMetricDataSummaryByYear'] = $this->getDisplayPropertiesForGetMetricDataSummaryByYear(); - $properties['DBStats.getReportDataSummary'] = $this->getDisplayPropertiesForGetReportDataSummary(); - $properties['DBStats.getReportDataSummaryByYear'] = $this->getDisplayPropertiesForGetReportDataSummaryByYear(); - $properties['DBStats.getIndividualReportsSummary'] = $this->getDisplayPropertiesForGetIndividualReportsSummary(); - $properties['DBStats.getIndividualMetricsSummary'] = $this->getDisplayPropertiesForGetIndividualMetricsSummary(); - $properties['DBStats.getAdminDataSummary'] = $this->getDisplayPropertiesForGetAdminDataSummary(); + $defaultViewTypes['DBStats.getDatabaseUsageSummary'] = Pie::ID; + $defaultViewTypes['DBStats.getTrackerDataSummary'] = HtmlTable::ID; + $defaultViewTypes['DBStats.getMetricDataSummary'] = HtmlTable::ID; + $defaultViewTypes['DBStats.getMetricDataSummaryByYear'] = HtmlTable::ID; + $defaultViewTypes['DBStats.getReportDataSummary'] = HtmlTable::ID; + $defaultViewTypes['DBStats.getReportDataSummaryByYear'] = HtmlTable::ID; + $defaultViewTypes['DBStats.getIndividualReportsSummary'] = HtmlTable::ID; + $defaultViewTypes['DBStats.getIndividualMetricsSummary'] = HtmlTable::ID; + $defaultViewTypes['DBStats.getAdminDataSummary'] = HtmlTable::ID; } - private function getDisplayPropertiesForGetDatabaseUsageSummary() + public function configureViewDataTable(ViewDataTable $view) { - $result = array('default_view_type' => 'graphPie'); - $this->addBaseDisplayProperties($result); - $this->addPresentationFilters($result, $addTotalSizeColumn = true, $addPercentColumn = true); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'DBStats.getDatabaseUsageSummar': + $this->configureViewForGetDatabaseUsageSummary($view); + break; + case 'DBStats.getTrackerDataSummary': + $this->configureViewForGetTrackerDataSummary($view); + break; + case 'DBStats.getMetricDataSummary': + $this->configureViewForGetMetricDataSummary($view); + break; + case 'DBStats.getMetricDataSummaryByYear': + $this->configureViewForGetMetricDataSummaryByYear($view); + break; + case 'DBStats.getReportDataSummary': + $this->configureViewForGetReportDataSummary($view); + break; + case 'DBStats.getReportDataSummaryByYear': + $this->configureViewForGetReportDataSummaryByYear($view); + break; + case 'DBStats.getIndividualReportsSummary': + $this->configureViewForGetIndividualReportsSummary($view); + break; + case 'DBStats.getIndividualMetricsSummary': + $this->configureViewForGetIndividualMetricsSummary($view); + break; + case 'DBStats.getAdminDataSummary': + $this->configureViewForGetAdminDataSummary($view); + break; + } + } + + private function configureViewForGetDatabaseUsageSummary(ViewDataTable $view) + { + $this->addBaseDisplayProperties($view); + $this->addPresentationFilters($view, $addTotalSizeColumn = true, $addPercentColumn = true); - $result['show_offset_information'] = false; - $result['show_pagination_control'] = false; - $result['visualization_properties']['graph']['show_all_ticks'] = true; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + + if ($view->isViewDataTableId(Graph::ID)) { + $view->config->show_all_ticks = true; + } // translate the labels themselves $valueToTranslationStr = array( @@ -125,143 +165,122 @@ class DBStats extends \Piwik\Plugin : $value; }; - $result['filters'][] = array('ColumnCallbackReplace', array('label', $translateSummaryLabel), $isPriority = true); - - return $result; + $view->config->filters[] = array('ColumnCallbackReplace', array('label', $translateSummaryLabel), $isPriority = true); } - private function getDisplayPropertiesForGetTrackerDataSummary() + private function configureViewForGetTrackerDataSummary(ViewDataTable $view) { - $result = array(); - $this->addBaseDisplayProperties($result); - $this->addPresentationFilters($result); + $this->addBaseDisplayProperties($view); + $this->addPresentationFilters($view); - $result['filter_sort_order'] = 'asc'; - $result['show_offset_information'] = false; - $result['show_pagination_control'] = false; - - return $result; + $view->requestConfig->filter_sort_order = 'asc'; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; } - private function getDisplayPropertiesForGetMetricDataSummary() + private function configureViewForGetMetricDataSummary(ViewDataTable $view) { - $result = array(); - $this->addBaseDisplayProperties($result); - $this->addPresentationFilters($result); + $this->addBaseDisplayProperties($view); + $this->addPresentationFilters($view); - $result['title'] = Piwik::translate('DBStats_MetricTables'); - $result['related_reports'] = array( + $view->config->title = Piwik::translate('DBStats_MetricTables'); + $view->config->addRelatedReports(array( 'DBStats.getMetricDataSummaryByYear' => Piwik::translate('DBStats_MetricDataByYear') - ); - - return $result; + )); } - private function getDisplayPropertiesForGetMetricDataSummaryByYear() + private function configureViewForGetMetricDataSummaryByYear(ViewDataTable $view) { - $result = array(); - $this->addBaseDisplayProperties($result); - $this->addPresentationFilters($result); + $this->addBaseDisplayProperties($view); + $this->addPresentationFilters($view); - $result['translations']['label'] = Piwik::translate('CoreHome_PeriodYear'); - $result['title'] = Piwik::translate('DBStats_MetricDataByYear'); - $result['related_reports'] = array( + $view->config->title = Piwik::translate('DBStats_MetricDataByYear'); + $view->config->addTranslation('label', Piwik::translate('CoreHome_PeriodYear')); + $view->config->addRelatedReports(array( 'DBStats.getMetricDataSummary' => Piwik::translate('DBStats_MetricTables') - ); - - return $result; + )); } - private function getDisplayPropertiesForGetReportDataSummary() + private function configureViewForGetReportDataSummary(ViewDataTable $view) { - $result = array(); - $this->addBaseDisplayProperties($result); - $this->addPresentationFilters($result); + $this->addBaseDisplayProperties($view); + $this->addPresentationFilters($view); - $result['title'] = Piwik::translate('DBStats_ReportTables'); - $result['related_reports'] = array( + $view->config->title = Piwik::translate('DBStats_ReportTables'); + $view->config->addRelatedReports(array( 'DBStats.getReportDataSummaryByYear' => Piwik::translate('DBStats_ReportDataByYear') - ); - - return $result; + )); } - private function getDisplayPropertiesForGetReportDataSummaryByYear() + private function configureViewForGetReportDataSummaryByYear(ViewDataTable $view) { - $result = array(); - $this->addBaseDisplayProperties($result); - $this->addPresentationFilters($result); + $this->addBaseDisplayProperties($view); + $this->addPresentationFilters($view); - $result['translations']['label'] = Piwik::translate('CoreHome_PeriodYear'); - $result['title'] = Piwik::translate('DBStats_ReportDataByYear'); - $result['related_reports'] = array( + $view->config->title = Piwik::translate('DBStats_ReportDataByYear'); + $view->config->addTranslation('label', Piwik::translate('CoreHome_PeriodYear')); + $view->config->addRelatedReports(array( 'DBStats.getReportDataSummary' => Piwik::translate('DBStats_ReportTables') - ); - - return $result; + )); } - private function getDisplayPropertiesForGetIndividualReportsSummary() + private function configureViewForGetIndividualReportsSummary(ViewDataTable $view) { - $result = array(); - $this->addBaseDisplayProperties($result); - $viewDataTable = $this->addPresentationFilters($result, $addTotalSizeColumn = false, $addPercentColumn = false, - $sizeColumns = array('estimated_size')); + $this->addBaseDisplayProperties($view); + $this->addPresentationFilters($view, $addTotalSizeColumn = false, $addPercentColumn = false, + $sizeColumns = array('estimated_size')); - $result['filter_sort_order'] = 'asc'; - $result['translations']['label'] = Piwik::translate('General_Report'); + $view->requestConfig->filter_sort_order = 'asc'; + $view->config->addTranslation('label', Piwik::translate('General_Report')); // this report table has some extra columns that shouldn't be shown - if ($viewDataTable == 'table') { - $result['columns_to_display'] = array('label', 'row_count', 'estimated_size'); + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->columns_to_display = array('label', 'row_count', 'estimated_size'); } - $this->setIndividualSummaryFooterMessage($result); - - return $result; + $this->setIndividualSummaryFooterMessage($view); } - private function getDisplayPropertiesForGetIndividualMetricsSummary() + private function configureViewForGetIndividualMetricsSummary(ViewDataTable $view) { - $result = array(); - $this->addBaseDisplayProperties($result); - $this->addPresentationFilters($result, $addTotalSizeColumn = false, $addPercentColumn = false, + $this->addBaseDisplayProperties($view); + $this->addPresentationFilters($view, $addTotalSizeColumn = false, $addPercentColumn = false, $sizeColumns = array('estimated_size')); - $result['filter_sort_order'] = 'asc'; - $result['translations']['label'] = Piwik::translate('General_Metric'); + $view->requestConfig->filter_sort_order = 'asc'; + $view->config->addTranslation('label', Piwik::translate('General_Metric')); - $this->setIndividualSummaryFooterMessage($result); - - return $result; + $this->setIndividualSummaryFooterMessage($view); } - private function getDisplayPropertiesForGetAdminDataSummary() + private function configureViewForGetAdminDataSummary(ViewDataTable $view) { - $result = array(); - $this->addBaseDisplayProperties($result); - $this->addPresentationFilters($result); - - $result['filter_sort_order'] = 'asc'; - $result['show_offset_information'] = false; - $result['show_pagination_control'] = false; + $this->addBaseDisplayProperties($view); + $this->addPresentationFilters($view); - return $result; + $view->requestConfig->filter_sort_order = 'asc'; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; } - private function addBaseDisplayProperties(&$properties) + private function addBaseDisplayProperties(ViewDataTable $view) { - $properties['filter_sort_column'] = 'label'; - $properties['filter_sort_order'] = 'desc'; - $properties['filter_limit'] = 25; - $properties['show_search'] = false; - $properties['show_exclude_low_population'] = false; - $properties['show_tag_cloud'] = false; - $properties['show_table_all_columns'] = false; - $properties['visualization_properties']['table']['keep_summary_row'] = true; - $properties['visualization_properties']['table']['disable_row_evolution'] = true; - $properties['visualization_properties']['table']['highlight_summary_row'] = true; - $properties['translations'] = array( + $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'desc'; + $view->requestConfig->filter_limit = 25; + + $view->config->show_exclude_low_population = false; + $view->config->show_table_all_columns = false; + $view->config->show_tag_cloud = false; + $view->config->show_search = false; + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->keep_summary_row = true; + $view->config->disable_row_evolution = true; + $view->config->highlight_summary_row = true; + } + + $view->config->addTranslations(array( 'label' => Piwik::translate('DBStats_Table'), 'year' => Piwik::translate('CoreHome_PeriodYear'), 'data_size' => Piwik::translate('DBStats_DataSize'), @@ -270,10 +289,10 @@ class DBStats extends \Piwik\Plugin 'row_count' => Piwik::translate('DBStats_RowCount'), 'percent_total' => '% ' . Piwik::translate('DBStats_DBSize'), 'estimated_size' => Piwik::translate('DBStats_EstimatedSize') - ); + )); } - private function addPresentationFilters(&$properties, $addTotalSizeColumn = true, $addPercentColumn = false, + private function addPresentationFilters(ViewDataTable $view, $addTotalSizeColumn = true, $addPercentColumn = false, $sizeColumns = array('data_size', 'index_size')) { // add total_size column @@ -282,7 +301,7 @@ class DBStats extends \Piwik\Plugin return $dataSize + $indexSize; }; - $properties['filters'][] = array('ColumnCallbackAddColumn', + $view->config->filters[] = array('ColumnCallbackAddColumn', array(array('data_size', 'index_size'), 'total_size', $getTotalTableSize), $isPriority = true); $sizeColumns[] = 'total_size'; @@ -290,78 +309,74 @@ class DBStats extends \Piwik\Plugin $runPrettySizeFilterBeforeGeneric = false; - $viewDataTable = empty($properties['default_view_type']) ? 'table' : $properties['default_view_type']; - $viewDataTable = Common::getRequestVar('viewDataTable', $viewDataTable); + if ($view->isViewDataTableId(HtmlTable::ID)) { - if ($viewDataTable == 'table') { // add summary row only if displaying a table - $properties['filters'][] = array( + $view->config->filters[] = array( 'AddSummaryRow', array(0, Piwik::translate('General_Total'), 'label', false), $isPriority = true); // add percentage column if desired if ($addPercentColumn && $addTotalSizeColumn ) { - $properties['filters'][] = array('ColumnCallbackAddColumnPercentage', + $view->config->filters[] = array('ColumnCallbackAddColumnPercentage', array('percent_total', 'total_size', 'total_size', $quotientPrecision = 0, $shouldSkipRows = false, $getDivisorFromSummaryRow = true), $isPriority = true ); - $properties['filter_sort_column'] = 'percent_total'; + $view->requestConfig->filter_sort_column = 'percent_total'; } - } else if (strpos($viewDataTable, 'graph') === 0) { + + } else if ($view->isViewDataTableId(Graph::ID)) { if ($addTotalSizeColumn) { - $properties['columns_to_display'] = array('label', 'total_size'); + $view->config->columns_to_display = array('label', 'total_size'); // when displaying a graph, we force sizes to be shown as the same unit so axis labels // will be readable. NOTE: The unit should depend on the smallest value of the data table, // however there's no way to know this information, short of creating a custom filter. For // now, just assume KB. $fixedMemoryUnit = 'K'; - $properties['y_axis_unit'] = ' K'; - - $properties['filter_sort_column'] = 'total_size'; - $properties['filter_sort_order'] = 'desc'; + $view->config->y_axis_unit = ' K'; + $view->requestConfig->filter_sort_column = 'total_size'; + $view->requestConfig->filter_sort_order = 'desc'; $runPrettySizeFilterBeforeGeneric = true; } else { - $properties['columns_to_display'] = array('label', 'row_count'); - $properties['y_axis_unit'] = ' ' . Piwik::translate('General_Rows'); + $view->config->columns_to_display = array('label', 'row_count'); + $view->config->y_axis_unit = ' ' . Piwik::translate('General_Rows'); - $properties['filter_sort_column'] = 'row_count'; - $properties['filter_sort_order'] = 'desc'; + $view->requestConfig->filter_sort_column = 'row_count'; + $view->requestConfig->filter_sort_order = 'desc'; } } $getPrettySize = array('\Piwik\MetricsFormatter', 'getPrettySizeFromBytes'); - $params = !isset($fixedMemoryUnit) ? array() : array($fixedMemoryUnit); - $properties['filters'][] = array( - 'ColumnCallbackReplace', array($sizeColumns, $getPrettySize, $params), $runPrettySizeFilterBeforeGeneric); + $params = !isset($fixedMemoryUnit) ? array() : array($fixedMemoryUnit); + + $view->config->filters[] = array('ColumnCallbackReplace', array($sizeColumns, $getPrettySize, $params), $runPrettySizeFilterBeforeGeneric); // jqPlot will display as, well, ' ', so don't replace the spaces when rendering as a graph - if ($viewDataTable == 'table') { + if ($view->isViewDataTableId(HtmlTable::ID)) { $replaceSpaces = function ($value) { return str_replace(' ', ' ', $value); }; - $properties['filters'][] = array('ColumnCallbackReplace', array($sizeColumns, $replaceSpaces)); + $view->config->filters[] = array('ColumnCallbackReplace', array($sizeColumns, $replaceSpaces)); } $getPrettyNumber = array('\Piwik\MetricsFormatter', 'getPrettyNumber'); - $properties['filters'][] = array('ColumnCallbackReplace', array('row_count', $getPrettyNumber)); - - return $viewDataTable; + $view->config->filters[] = array('ColumnCallbackReplace', array('row_count', $getPrettyNumber)); } /** * Sets the footer message for the Individual...Summary reports. */ - private function setIndividualSummaryFooterMessage($result) + private function setIndividualSummaryFooterMessage(ViewDataTable $view) { $lastGenerated = self::getDateOfLastCachingRun(); if ($lastGenerated !== false) { - $result['show_footer_message'] = Piwik::translate('Mobile_LastUpdated', $lastGenerated); + $view->config->show_footer_message = Piwik::translate('Mobile_LastUpdated', $lastGenerated); } } } diff --git a/plugins/DevicesDetection/DevicesDetection.php b/plugins/DevicesDetection/DevicesDetection.php index 1fdbb01613c099f2492dfce3b77ddc304bcbc43c..0fb275341e7cdf75cc79de14c73eeb789b67f694 100644 --- a/plugins/DevicesDetection/DevicesDetection.php +++ b/plugins/DevicesDetection/DevicesDetection.php @@ -19,6 +19,7 @@ use Piwik\Config; use Piwik\Db; use Piwik\Menu\MenuMain; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; use Piwik\WidgetsList; use UserAgentParserEnhanced; @@ -90,14 +91,14 @@ class DevicesDetection extends \Piwik\Plugin public function getListHooksRegistered() { return array( - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'Menu.Reporting.addItems' => 'addMenu', - 'Tracker.newVisitorInformation' => 'parseMobileVisitData', - 'WidgetsList.addWidgets' => 'addWidgets', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'Menu.Reporting.addItems' => 'addMenu', + 'Tracker.newVisitorInformation' => 'parseMobileVisitData', + 'WidgetsList.addWidgets' => 'addWidgets', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.configure' => 'configureViewDataTable', ); } @@ -293,85 +294,87 @@ class DevicesDetection extends \Piwik\Plugin MenuMain::getInstance()->add('General_Visitors', 'DevicesDetection_submenu', array('module' => 'DevicesDetection', 'action' => 'index')); } - public function getReportDisplayProperties(&$properties) + public function configureViewDataTable(ViewDataTable $view) { - $properties['DevicesDetection.getType'] = $this->getDisplayPropertiesForGetType(); - $properties['DevicesDetection.getBrand'] = $this->getDisplayPropertiesForGetBrand(); - $properties['DevicesDetection.getModel'] = $this->getDisplayPropertiesForGetModel(); - $properties['DevicesDetection.getOsFamilies'] = $this->getDisplayPropertiesForGetOsFamilies(); - $properties['DevicesDetection.getOsVersions'] = $this->getDisplayPropertiesForGetOsVersions(); - $properties['DevicesDetection.getBrowserFamilies'] = $this->getDisplayPropertiesForGetBrowserFamilies(); - $properties['DevicesDetection.getBrowserVersions'] = $this->getDisplayPropertiesForGetBrowserVersions(); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'DevicesDetection.getType': + $this->configureViewForGetType($view); + break; + case 'DevicesDetection.getBrand': + $this->configureViewForGetBrand($view); + break; + case 'DevicesDetection.getModel': + $this->configureViewForGetModel($view); + break; + case 'DevicesDetection.getOsFamilies': + $this->configureViewForGetOsFamilies($view); + break; + case 'DevicesDetection.getOsVersions': + $this->configureViewForGetOsVersions($view); + break; + case 'DevicesDetection.getBrowserFamilies': + $this->configureViewForGetBrowserFamilies($view); + break; + case 'DevicesDetection.getBrowserVersions': + $this->configureViewForGetBrowserVersions($view); + break; + } } - private function getDisplayPropertiesForGetType() + private function configureViewForGetType(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate("DevicesDetection_dataTableLabelTypes")) - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate("DevicesDetection_dataTableLabelTypes")); } - private function getDisplayPropertiesForGetBrand() + private function configureViewForGetBrand(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate("DevicesDetection_dataTableLabelBrands")) - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate("DevicesDetection_dataTableLabelBrands")); } - private function getDisplayPropertiesForGetModel() + private function configureViewForGetModel(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate("DevicesDetection_dataTableLabelModels")) - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate("DevicesDetection_dataTableLabelModels")); } - private function getDisplayPropertiesForGetOsFamilies() + private function configureViewForGetOsFamilies(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate("DevicesDetection_dataTableLabelSystemFamily")), - 'title' => Piwik::translate('DevicesDetection_OperatingSystemFamilies'), - 'related_reports' => $this->getOsRelatedReports() - ); + $view->config->title = Piwik::translate('DevicesDetection_OperatingSystemFamilies'); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate("DevicesDetection_dataTableLabelSystemFamily")); + $view->config->addRelatedReports($this->getOsRelatedReports()); } - private function getDisplayPropertiesForGetOsVersions() + private function configureViewForGetOsVersions(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate("DevicesDetection_dataTableLabelSystemVersion")), - 'title' => Piwik::translate('DevicesDetection_OperatingSystemVersions'), - 'related_reports' => $this->getOsRelatedReports() - ); + $view->config->title = Piwik::translate('DevicesDetection_OperatingSystemVersions'); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate("DevicesDetection_dataTableLabelSystemVersion")); + $view->config->addRelatedReports($this->getOsRelatedReports()); } - private function getDisplayPropertiesForGetBrowserFamilies() + private function configureViewForGetBrowserFamilies(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate("DevicesDetection_dataTableLabelBrowserFamily")), - 'title' => Piwik::translate('DevicesDetection_BrowsersFamily'), - 'related_reports' => $this->getBrowserRelatedReports() - ); + $view->config->title = Piwik::translate('DevicesDetection_BrowsersFamily'); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate("DevicesDetection_dataTableLabelBrowserFamily")); + $view->config->addRelatedReports($this->getBrowserRelatedReports()); } - private function getDisplayPropertiesForGetBrowserVersions() + private function configureViewForGetBrowserVersions(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate("DevicesDetection_dataTableLabelBrowserVersion")), - 'related_reports' => $this->getBrowserRelatedReports() - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate("DevicesDetection_dataTableLabelBrowserVersion")); + $view->config->addRelatedReports($this->getBrowserRelatedReports()); } private function getOsRelatedReports() diff --git a/plugins/ExampleUI/Controller.php b/plugins/ExampleUI/Controller.php index f4dd86c6fb6f150c504e7f754be186bea856e179..46d2627a3c51f863a0f377baa148c80d6bf224e3 100644 --- a/plugins/ExampleUI/Controller.php +++ b/plugins/ExampleUI/Controller.php @@ -52,7 +52,7 @@ class Controller extends \Piwik\Plugin\Controller $view = $this->getLastUnitGraphAcrossPlugins($this->pluginName, __FUNCTION__, $columns, $selectableColumns = array('server1', 'server2'), 'My documentation', 'ExampleUI.getTemperaturesEvolution'); - $view->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_column = 'label'; return $this->renderView($view, $fetch); } @@ -62,11 +62,11 @@ class Controller extends \Piwik\Plugin\Controller $view = ViewDataTable::factory( 'graphVerticalBar', 'ExampleUI.getTemperatures', $controllerAction = 'ExampleUI.barGraph'); - $view->y_axis_unit = '°C'; - $view->show_footer = false; - $view->translations['value'] = "Temperature"; - $view->visualization_properties->selectable_columns = array("value"); - $view->visualization_properties->max_graph_elements = 24; + $view->config->y_axis_unit = '°C'; + $view->config->show_footer = false; + $view->config->translations['value'] = "Temperature"; + $view->config->selectable_columns = array("value"); + $view->config->max_graph_elements = 24; echo $view->render(); } @@ -76,11 +76,11 @@ class Controller extends \Piwik\Plugin\Controller $view = ViewDataTable::factory( 'graphPie', 'ExampleUI.getPlanetRatios', $controllerAction = 'ExampleUI.pieGraph'); - $view->columns_to_display = array('value'); - $view->translations['value'] = "times the diameter of Earth"; - $view->show_footer_icons = false; - $view->visualization_properties->selectable_columns = array("value"); - $view->visualization_properties->max_graph_elements = 10; + $view->config->columns_to_display = array('value'); + $view->config->translations['value'] = "times the diameter of Earth"; + $view->config->show_footer_icons = false; + $view->config->selectable_columns = array("value"); + $view->config->max_graph_elements = 10; echo $view->render(); } @@ -103,9 +103,9 @@ class Controller extends \Piwik\Plugin\Controller $view = ViewDataTable::factory( 'cloud', 'ExampleUI.getPlanetRatios', $controllerAction = 'ExampleUI.echoSimpleTagClouds'); - $view->columns_to_display = array('label', 'value'); - $view->translations['value'] = "times the diameter of Earth"; - $view->show_footer = false; + $view->config->columns_to_display = array('label', 'value'); + $view->config->translations['value'] = "times the diameter of Earth"; + $view->config->show_footer = false; echo $view->render(); } @@ -115,13 +115,9 @@ class Controller extends \Piwik\Plugin\Controller $view = ViewDataTable::factory( 'cloud', 'ExampleUI.getPlanetRatiosWithLogos', $controllerAction = 'ExampleUI.echoAdvancedTagClouds'); - $view->visualization_properties->setForVisualization( - 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\Cloud', - 'display_logo_instead_of_label', - true - ); - $view->columns_to_display = array('label', 'value'); - $view->translations['value'] = "times the diameter of Earth"; + $view->config->display_logo_instead_of_label = true; + $view->config->columns_to_display = array('label', 'value'); + $view->config->translations['value'] = "times the diameter of Earth"; echo $view->render(); } @@ -142,7 +138,7 @@ class Controller extends \Piwik\Plugin\Controller $serverRequested = Common::getRequestVar('server', false); if (false !== $serverRequested) { - $view->columns_to_display = array($serverRequested); + $view->config->columns_to_display = array($serverRequested); } echo $view->render(); diff --git a/plugins/ExampleUI/CustomDataTable.php b/plugins/ExampleUI/CustomDataTable.php index bfda92a70422808dd50e8c42cf2b8a5fd66c2ebd..3f8b780a81692abbd6b812fe3bd0128a06c580a6 100644 --- a/plugins/ExampleUI/CustomDataTable.php +++ b/plugins/ExampleUI/CustomDataTable.php @@ -20,24 +20,17 @@ class CustomDataTable { $view = ViewDataTable::factory('table', $apiAction, $controllerAction); - $view->translations['value'] = $value; - $view->translations['label'] = $label; - $view->filter_sort_column = 'label'; - $view->filter_sort_order = 'asc'; - $view->filter_limit = 24; - $view->y_axis_unit = '°C'; // useful if the user requests the bar graph - $view->show_exclude_low_population = false; - $view->show_table_all_columns = false; - $view->visualization_properties->setForVisualization( - 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\HtmlTable', - 'disable_row_evolution', - true - ); - $view->visualization_properties->setForVisualization( - 'Piwik\\Plugins\\CoreVisualizations\\Visualizations\\JqplotGraph', - 'max_graph_elements', - 24 - ); + $view->config->translations['value'] = $value; + $view->config->translations['label'] = $label; + $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'asc'; + $view->requestConfig->filter_limit = 24; + $view->config->columns_to_display = array('label', 'value'); + $view->config->y_axis_unit = '°C'; // useful if the user requests the bar graph + $view->config->show_exclude_low_population = false; + $view->config->show_table_all_columns = false; + $view->config->disable_row_evolution = true; + $view->config->max_graph_elements = 24; return $view->render(); } diff --git a/plugins/ExampleVisualization/SimpleTable.php b/plugins/ExampleVisualization/SimpleTable.php index abd5c8aff2030d7fecbfd93bcbbadde64ada3807..6b70c1fdc5ddfa1f14315c7b01cff7fe8a186bdd 100644 --- a/plugins/ExampleVisualization/SimpleTable.php +++ b/plugins/ExampleVisualization/SimpleTable.php @@ -12,58 +12,52 @@ namespace Piwik\Plugins\ExampleVisualization; use Piwik\DataTable; -use Piwik\DataTable\DataTableInterface; -use Piwik\ViewDataTable\Visualization; -use Piwik\Visualization\Config; -use Piwik\Visualization\Request; +use Piwik\Plugin\Visualization; /** * SimpleTable Visualization. */ class SimpleTable extends Visualization { + const ID = 'simpleTable'; const TEMPLATE_FILE = '@ExampleVisualization/simpleTable.twig'; const FOOTER_ICON_TITLE = 'Simple Table'; const FOOTER_ICON = 'plugins/ExampleVisualization/images/table.png'; - /** - * You do not have to implement the init method. It is just an example how to assign view variables. - */ - public function init() - { - $this->vizTitle = 'MyAwesomeTitle'; - } - - public function configureVisualization(Config $properties) - { - // Configure how your visualization should look like, for instance you can disable search - // $properties->show_search = false - } - - public function beforeLoadDataTable(Request $request, Config $properties) + public function beforeLoadDataTable() { // Here you can change the request that is sent to the API, for instance - // $properties->filter_sort_order = 'desc'; + // $this->requestConfig->filter_sort_order = 'desc'; } - public function beforeGenericFiltersAreAppliedToLoadedDataTable(DataTableInterface $dataTable, Config $properties, Request $request) + public function beforeGenericFiltersAreAppliedToLoadedDataTable() { // this hook is executed before generic filters like "filter_limit" and "filter_offset" are applied // Usage: - // $dateTable->filter($nameOrClosure); + // $this->dateTable->filter($nameOrClosure); } - public function afterGenericFiltersAreAppliedToLoadedDataTable(DataTableInterface $dataTable, Config $properties, Request $request) + public function afterGenericFiltersAreAppliedToLoadedDataTable() { // this hook is executed after generic filters like "filter_limit" and "filter_offset" are applied // Usage: - // $dateTable->filter($nameOrClosure, $parameters); + // $this->dateTable->filter($nameOrClosure, $parameters); } - public function afterAllFilteresAreApplied(DataTableInterface $dataTable, Config $properties, Request $request) + public function afterAllFilteresAreApplied() { // this hook is executed after the data table is loaded and after all filteres are applied. // format your data here that you want to pass to the view - // $this->myCustomViewVariable = $dataTable->getRows(); + + $this->assignTemplateVar('vizTitle', 'MyAwesomeTitle'); + } + + public function beforeRender() + { + // Configure how your visualization should look like, for instance you can disable search + // By defining the config properties shortly before rendering you make sure the config properties have a certain + // value because they could be changed by a report or by request parameters ($_GET / $_POST) before. + // $this->config->show_search = false } + } \ No newline at end of file diff --git a/plugins/ExampleVisualization/templates/simpleTable.twig b/plugins/ExampleVisualization/templates/simpleTable.twig index 6cb0fdadd86492106163f9803c83dafca094b594..6b0748711d2216436d68faa5cda83aace5a303cf 100644 --- a/plugins/ExampleVisualization/templates/simpleTable.twig +++ b/plugins/ExampleVisualization/templates/simpleTable.twig @@ -4,7 +4,7 @@ <table class="dataTable"> <thead> <tr> - {% for name,value in dataTable.getFirstRow.getColumns %} + {% for name in properties.columns_to_display %} {% if name in properties.translations|keys %} <th>{{ properties.translations[name]|translate }}</th> {% else %} @@ -16,8 +16,8 @@ <tbody> {% for tableRow in dataTable.getRows %} <tr> - {% for column in tableRow.getColumns %} - <td>{{ column|truncate(50)|raw }}</td> + {% for column in properties.columns_to_display %} + <td>{{ tableRow.getColumn(column)|default('-')|truncate(50)|raw }}</td> {% endfor %} </tr> {% endfor %} diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php index 752edf55804f855d82176db6d7e35c3c31a4d855..87ea5ed1582a2e1cd9cae9033d24ef89f0986ea2 100644 --- a/plugins/Goals/Controller.php +++ b/plugins/Goals/Controller.php @@ -255,7 +255,7 @@ class Controller extends \Piwik\Plugin\Controller $idGoal = Common::getRequestVar('idGoal', false, 'string'); } $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.get'); - $view->request_parameters_to_modify['idGoal'] = $idGoal; + $view->requestConfig->request_parameters_to_modify['idGoal'] = $idGoal; $nameToLabel = $this->goalColumnNameToLabel; if ($idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) { @@ -287,13 +287,13 @@ class Controller extends \Piwik\Plugin\Controller $goalName = $this->goals[$idGoal]['name']; $columnTranslation = "$columnTranslation (" . Piwik::translate('Goals_GoalX', "$goalName") . ")"; } - $view->translations[$columnName] = $columnTranslation; + $view->config->translations[$columnName] = $columnTranslation; } - $view->columns_to_display = $columns; - $view->visualization_properties->selectable_columns = $selectableColumns; + $view->config->columns_to_display = $columns; + $view->config->selectable_columns = $selectableColumns; $langString = $idGoal ? 'Goals_SingleGoalOverviewDocumentation' : 'Goals_GoalsOverviewDocumentation'; - $view->documentation = Piwik::translate($langString, '<br />'); + $view->config->documentation = Piwik::translate($langString, '<br />'); return $this->renderView($view, $fetch); } diff --git a/plugins/Goals/Goals.php b/plugins/Goals/Goals.php index 1d60a52966fddb8cd818672ca0e6241abc09b405..31db9f742e00a63003c4aca4c2fa29bfc545c592 100644 --- a/plugins/Goals/Goals.php +++ b/plugins/Goals/Goals.php @@ -16,6 +16,7 @@ use Piwik\Common; use Piwik\Db; use Piwik\Menu\MenuMain; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; use Piwik\Site; use Piwik\Tracker\GoalManager; use Piwik\Translate; @@ -88,23 +89,29 @@ class Goals extends \Piwik\Plugin public function getListHooksRegistered() { $hooks = array( - 'AssetManager.getJavaScriptFiles' => 'getJsFiles', - 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', - 'Site.getSiteAttributes' => 'fetchGoalsFromDb', - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'API.getReportMetadata.end' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', - 'WidgetsList.addWidgets' => 'addWidgets', - 'Menu.Reporting.addItems' => 'addMenus', - 'SitesManager.deleteSite.end' => 'deleteSiteGoals', - 'Goals.getReportsWithGoalMetrics' => 'getActualReportsWithGoalMetrics', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', - 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys' + 'AssetManager.getJavaScriptFiles' => 'getJsFiles', + 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', + 'Site.getSiteAttributes' => 'fetchGoalsFromDb', + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'API.getReportMetadata.end' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'WidgetsList.addWidgets' => 'addWidgets', + 'Menu.Reporting.addItems' => 'addMenus', + 'SitesManager.deleteSite.end' => 'deleteSiteGoals', + 'Goals.getReportsWithGoalMetrics' => 'getActualReportsWithGoalMetrics', + 'ViewDataTable.configure' => 'configureViewDataTable', + 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', + 'Visualization.addVisualizations' => 'getAvailableDataTableVisualizations' ); return $hooks; } + public function getAvailableDataTableVisualizations(&$visualizations) + { + $visualizations[] = 'Piwik\\Plugins\\Goals\\Visualizations\\Goals'; + } + /** * Delete goals recorded for this site */ @@ -518,71 +525,83 @@ class Goals extends \Piwik\Plugin } } - public function getReportDisplayProperties(&$properties) + public function configureViewDataTable(ViewDataTable $view) { - $properties['Goals.getItemsSku'] = $this->getDisplayPropertiesForGetItemsSku(); - $properties['Goals.getItemsName'] = $this->getDisplayPropertiesForGetItemsName(); - $properties['Goals.getItemsCategory'] = $this->getDisplayPropertiesForGetItemsCategory(); - $properties['Goals.getVisitsUntilConversion'] = $this->getDisplayPropertiesForGetVisitsUntilConversion(); - $properties['Goals.getDaysToConversion'] = $this->getDisplayPropertiesForGetDaysToConversion(); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'Goals.getItemsSku': + $this->configureViewForGetItemsSku($view); + break; + case 'Goals.getItemsName': + $this->configureViewForGetItemsName($view); + break; + case 'Goals.getItemsCategory': + $this->configureViewForGetItemsCategory($view); + break; + case 'Goals.getVisitsUntilConversion': + $this->configureViewForGetVisitsUntilConversion($view); + break; + case 'Goals.getDaysToConversion': + $this->configureViewForGetDaysToConversion($view); + break; + } } - private function getDisplayPropertiesForGetItemsSku() + private function configureViewForGetItemsSku(ViewDataTable $view) { - return $this->getDisplayPropertiesForItemsReport(Piwik::translate('Goals_ProductSKU')); + return $this->configureViewForItemsReport($view, Piwik::translate('Goals_ProductSKU')); } - private function getDisplayPropertiesForGetItemsName() + private function configureViewForGetItemsName(ViewDataTable $view) { - return $this->getDisplayPropertiesForItemsReport(Piwik::translate('Goals_ProductName')); + return $this->configureViewForItemsReport($view, Piwik::translate('Goals_ProductName')); } - private function getDisplayPropertiesForGetItemsCategory() + private function configureViewForGetItemsCategory(ViewDataTable $view) { - return $this->getDisplayPropertiesForItemsReport(Piwik::translate('Goals_ProductCategory')); + return $this->configureViewForItemsReport($view, Piwik::translate('Goals_ProductCategory')); } - private function getDisplayPropertiesForGetVisitsUntilConversion() + private function configureViewForGetVisitsUntilConversion(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'show_table_all_columns' => false, - 'columns_to_display' => array('label', 'nb_conversions'), - 'filter_sort_column' => 'label', - 'filter_sort_order' => 'asc', - 'translations' => array( - 'label' => Piwik::translate('Goals_VisitsUntilConv'), - 'nb_conversions' => Piwik::translate('Goals_ColumnConversions'), - ), - 'filter_limit' => count(Archiver::$visitCountRanges), - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_all_views_icons' => false - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->show_table_all_columns = false; + $view->config->columns_to_display = array('label', 'nb_conversions'); + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_all_views_icons = false; + + $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'asc'; + $view->requestConfig->filter_limit = count(Archiver::$visitCountRanges); + + $view->config->addTranslations(array( + 'label' => Piwik::translate('Goals_VisitsUntilConv'), + 'nb_conversions' => Piwik::translate('Goals_ColumnConversions'), + )); } - private function getDisplayPropertiesForGetDaysToConversion() + private function configureViewForGetDaysToConversion(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'show_table_all_columns' => false, - 'columns_to_display' => array('label', 'nb_conversions'), - 'filter_sort_column' => 'label', - 'filter_sort_order' => 'asc', - 'translations' => array( - 'label' => Piwik::translate('Goals_DaysToConv'), - 'nb_conversions' => Piwik::translate('Goals_ColumnConversions'), - ), - 'filter_limit' => count(Archiver::$daysToConvRanges), - 'show_all_views_icons' => false, - 'show_offset_information' => false, - 'show_pagination_control' => false, - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->show_table_all_columns = false; + $view->config->show_all_views_icons = false; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->columns_to_display = array('label', 'nb_conversions'); + + $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'asc'; + $view->requestConfig->filter_limit = count(Archiver::$daysToConvRanges); + + $view->config->addTranslations(array( + 'label' => Piwik::translate('Goals_DaysToConv'), + 'nb_conversions' => Piwik::translate('Goals_ColumnConversions'), + )); } - private function getDisplayPropertiesForItemsReport($label) + private function configureViewForItemsReport(ViewDataTable $view, $label) { $idSite = Common::getRequestVar('idSite'); @@ -590,18 +609,17 @@ class Goals extends \Piwik\Plugin $prettifyMoneyColumns = array( 'ColumnCallbackReplace', array($moneyColumns, '\Piwik\MetricsFormatter::getPrettyMoney', array($idSite))); - $result = array( - 'show_ecommerce' => true, - 'show_all_views_icons' => false, - 'show_table' => false, - 'show_exclude_low_population' => false, - 'show_table_all_columns' => false, - 'filter_limit' => 10, - 'translations' => array('label' => $label), - 'filter_sort_column' => 'revenue', - 'filter_sort_order' => 'desc', - 'filters' => array($prettifyMoneyColumns) - ); + $view->config->show_ecommerce = true; + $view->config->show_table = false; + $view->config->show_all_views_icons = false; + $view->config->show_exclude_low_population = false; + $view->config->show_table_all_columns = false; + $view->config->addTranslation('label', $label); + $view->config->filters[] = $prettifyMoneyColumns; + + $view->requestConfig->filter_limit = 10; + $view->requestConfig->filter_sort_column = 'revenue'; + $view->requestConfig->filter_sort_order = 'desc'; // set columns/translations which differ based on viewDataTable TODO: shouldn't have to do this check... amount of reports should be dynamic, but metadata should be static $columns = Goals::getProductReportColumns(); @@ -615,15 +633,17 @@ class Goals extends \Piwik\Plugin unset($columns['orders']); unset($columns['conversion_rate']); - $result['request_parameters_to_modify'] = array('abandonedCarts' => '1'); + $view->requestConfig->request_parameters_to_modify['abandonedCarts'] = '1'; } - $result['translations'] = array_merge(array('label' => $label), $columns); - $result['columns_to_display'] = array_keys($result['translations']); + $translations = array_merge(array('label' => $label), $columns); + + $view->config->addTranslations($translations); + $view->config->columns_to_display = array_keys($translations); // set metrics documentation in normal ecommerce report if (!$abandonedCart) { - $result['metrics_documentation'] = array( + $view->config->metrics_documentation = array( 'revenue' => Piwik::translate('Goals_ColumnRevenueDocumentation', Piwik::translate('Goals_DocumentationRevenueGeneratedByProductSales')), 'quantity' => Piwik::translate('Goals_ColumnQuantityDocumentation', $label), @@ -635,10 +655,8 @@ class Goals extends \Piwik\Plugin ); } - $result['custom_parameters']['viewDataTable'] = + $view->config->custom_parameters['viewDataTable'] = $abandonedCart ? Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART : Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER; - - return $result; } diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable/Goals.php b/plugins/Goals/Visualizations/Goals.php similarity index 66% rename from plugins/CoreVisualizations/Visualizations/HtmlTable/Goals.php rename to plugins/Goals/Visualizations/Goals.php index 71aec3fe2fd2b7775f7bdd9a9a83fffa222f0621..7835d8afb15cf7dcb3d0cbf8fe6a6d2205f831da 100644 --- a/plugins/CoreVisualizations/Visualizations/HtmlTable/Goals.php +++ b/plugins/Goals/Visualizations/Goals.php @@ -9,18 +9,16 @@ * @package CoreVisualizations */ -namespace Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; +namespace Piwik\Plugins\Goals\Visualizations; use Piwik\Piwik; use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; -use Piwik\Visualization\Config; use Piwik\Common; use Piwik\DataTable\Filter\AddColumnsProcessedMetricsGoal; use Piwik\MetricsFormatter; use Piwik\Plugins\Goals\API as APIGoals; use Piwik\Site; use Piwik\View; -use Piwik\ViewDataTable\Visualization; /** * DataTable Visualization that derives from HtmlTable and sets show_goals_columns to true. @@ -29,63 +27,69 @@ class Goals extends HtmlTable { const ID = 'tableGoals'; - public function configureVisualization(Config $properties) + public function beforeLoadDataTable() { - $properties->visualization_properties->show_goals_columns = true; + parent::beforeLoadDataTable(); - $properties->datatable_css_class = 'dataTableVizGoals'; - $properties->show_exclude_low_population = true; - $properties->show_goals = true; + if (!$this->config->disable_subtable_when_show_goals) { + $this->config->subtable_controller_action = null; + } + + $this->setShowGoalsColumnsProperties(); + } - $properties->translations += array( + public function beforeRender() + { + $this->config->show_goals = true; + $this->config->show_goals_columns = true; + $this->config->datatable_css_class = 'dataTableVizGoals'; + $this->config->show_exclude_low_population = true; + + $this->config->translations += array( 'nb_conversions' => Piwik::translate('Goals_ColumnConversions'), 'conversion_rate' => Piwik::translate('General_ColumnConversionRate'), 'revenue' => Piwik::translate('General_ColumnRevenue'), 'revenue_per_visit' => Piwik::translate('General_ColumnValuePerVisit'), ); - $properties->metrics_documentation['nb_visits'] = Piwik::translate('Goals_ColumnVisits'); - if (Common::getRequestVar('documentationForGoalsPage', 0, 'int') == 1) { // TODO: should not use query parameter - $properties->documentation = Piwik::translate('Goals_ConversionByTypeReportDocumentation', - array('<br />', '<br />', '<a href="http://piwik.org/docs/tracking-goals-web-analytics/" target="_blank">', '</a>')); - } + $this->config->metrics_documentation['nb_visits'] = Piwik::translate('Goals_ColumnVisits'); - if (!$properties->visualization_properties->disable_subtable_when_show_goals) { - $properties->subtable_controller_action = null; + if (1 == Common::getRequestVar('documentationForGoalsPage', 0, 'int')) { + // TODO: should not use query parameter + $this->config->documentation = Piwik::translate('Goals_ConversionByTypeReportDocumentation', + array('<br />', '<br />', '<a href="http://piwik.org/docs/tracking-goals-web-analytics/" target="_blank">', '</a>')); } - $this->setShowGoalsColumnsProperties(); - - parent::configureVisualization($properties); + parent::beforeRender(); } private function setShowGoalsColumnsProperties() { - $view = $this->viewDataTable; - // set view properties based on goal requested $idSite = Common::getRequestVar('idSite', null, 'int'); $idGoal = Common::getRequestVar('idGoal', AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW, 'string'); - if ($idGoal == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) { - $this->setPropertiesForEcommerceView($view); - } else if ($idGoal == AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE) { - $this->setPropertiesForGoals($view, $idSite, 'all'); - } else if ($idGoal == AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW) { - $this->setPropertiesForGoalsOverview($view, $idSite); + + if (Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER == $idGoal) { + $this->setPropertiesForEcommerceView(); + } else if (AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE == $idGoal) { + $this->setPropertiesForGoals($idSite, 'all'); + } else if (AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW == $idGoal) { + $this->setPropertiesForGoalsOverview($idSite); } else { - $this->setPropertiesForGoals($view, $idSite, array($idGoal)); + $this->setPropertiesForGoals($idSite, array($idGoal)); } // add goals columns - $view->filters[] = array('AddColumnsProcessedMetricsGoal', array($ignore = true, $idGoal), $priority = true); + $this->config->filters[] = array('AddColumnsProcessedMetricsGoal', array($ignore = true, $idGoal), $priority = true); // prettify columns $setRatePercent = function ($rate, $thang = false) { return $rate == 0 ? "0%" : $rate; }; - foreach ($view->columns_to_display as $columnName) { - if (strpos($columnName, 'conversion_rate') !== false) { - $view->filters[] = array('ColumnCallbackReplace', array($columnName, $setRatePercent)); + + foreach ($this->config->columns_to_display as $columnName) { + if (false !== strpos($columnName, 'conversion_rate')) { + $this->config->filters[] = array('ColumnCallbackReplace', array($columnName, $setRatePercent)); } } @@ -93,9 +97,9 @@ class Goals extends HtmlTable return MetricsFormatter::getPrettyMoney(sprintf("%.1f", $value), $idSite); }; - foreach ($view->columns_to_display as $columnName) { + foreach ($this->config->columns_to_display as $columnName) { if ($this->isRevenueColumn($columnName)) { - $view->filters[] = array('ColumnCallbackReplace', array($columnName, $formatPercent)); + $this->config->filters[] = array('ColumnCallbackReplace', array($columnName, $formatPercent)); } } @@ -103,25 +107,26 @@ class Goals extends HtmlTable $identityFunction = function ($value) { return $value; }; - foreach ($view->columns_to_display as $columnName) { + + foreach ($this->config->columns_to_display as $columnName) { if (!$this->isRevenueColumn($columnName)) { - $view->filters[] = array('ColumnCallbackReplace', array($columnName, $identityFunction)); + $this->config->filters[] = array('ColumnCallbackReplace', array($columnName, $identityFunction)); } } } - private function setPropertiesForEcommerceView($view) + private function setPropertiesForEcommerceView() { - $view->filter_sort_column = 'goal_ecommerceOrder_revenue'; - $view->filter_sort_order = 'desc'; + $this->requestConfig->filter_sort_column = 'goal_ecommerceOrder_revenue'; + $this->requestConfig->filter_sort_order = 'desc'; - $view->columns_to_display = array( + $this->config->columns_to_display = array( 'label', 'nb_visits', 'goal_ecommerceOrder_nb_conversions', 'goal_ecommerceOrder_revenue', 'goal_ecommerceOrder_conversion_rate', 'goal_ecommerceOrder_avg_order_revenue', 'goal_ecommerceOrder_items', 'goal_ecommerceOrder_revenue_per_visit' ); - $view->translations += array( + $this->config->translations += array( 'goal_ecommerceOrder_conversion_rate' => Piwik::translate('Goals_ConversionRate', Piwik::translate('Goals_EcommerceOrder')), 'goal_ecommerceOrder_nb_conversions' => Piwik::translate('General_EcommerceOrders'), 'goal_ecommerceOrder_revenue' => Piwik::translate('General_TotalRevenue'), @@ -131,7 +136,7 @@ class Goals extends HtmlTable ); $goalName = Piwik::translate('General_EcommerceOrders'); - $view->metrics_documentation += array( + $this->config->metrics_documentation += array( 'goal_ecommerceOrder_conversion_rate' => Piwik::translate('Goals_ColumnConversionRateDocumentation', $goalName), 'goal_ecommerceOrder_nb_conversions' => Piwik::translate('Goals_ColumnConversionsDocumentation', $goalName), 'goal_ecommerceOrder_revenue' => Piwik::translate('Goals_ColumnRevenueDocumentation', $goalName), @@ -142,40 +147,40 @@ class Goals extends HtmlTable ); } - private function setPropertiesForGoalsOverview($view, $idSite) + private function setPropertiesForGoalsOverview($idSite) { $allGoals = $this->getGoals($idSite); // set view properties - $view->columns_to_display = array('label', 'nb_visits'); + $this->config->columns_to_display = array('label', 'nb_visits'); foreach ($allGoals as $goal) { - $column = "goal_{$goal['idgoal']}_conversion_rate"; + $column = "goal_{$goal['idgoal']}_conversion_rate"; + $documentation = Piwik::translate('Goals_ColumnConversionRateDocumentation', $goal['quoted_name'] ? : $goal['name']); - $view->columns_to_display[] = $column; - $view->translations[$column] = Piwik::translate('Goals_ConversionRate', $goal['name']); - $view->metrics_documentation[$column] - = Piwik::translate('Goals_ColumnConversionRateDocumentation', $goal['quoted_name'] ? : $goal['name']); + $this->config->columns_to_display[] = $column; + $this->config->translations[$column] = Piwik::translate('Goals_ConversionRate', $goal['name']); + $this->config->metrics_documentation[$column] = $documentation; } - $view->columns_to_display[] = 'revenue_per_visit'; - $view->metrics_documentation['revenue_per_visit'] = + $this->config->columns_to_display[] = 'revenue_per_visit'; + $this->config->metrics_documentation['revenue_per_visit'] = Piwik::translate('Goals_ColumnRevenuePerVisitDocumentation', Piwik::translate('Goals_EcommerceAndGoalsMenu')); } - private function setPropertiesForGoals($view, $idSite, $idGoals) + private function setPropertiesForGoals($idSite, $idGoals) { $allGoals = $this->getGoals($idSite); - if ($idGoals == 'all') { + if ('all' == $idGoals) { $idGoals = array_keys($allGoals); } else { // only sort by a goal's conversions if not showing all goals (for FULL_REPORT) - $view->filter_sort_column = 'goal_' . reset($idGoals) . '_nb_conversions'; - $view->filter_sort_order = 'desc'; + $this->requestConfig->filter_sort_column = 'goal_' . reset($idGoals) . '_nb_conversions'; + $this->requestConfig->filter_sort_order = 'desc'; } - $view->columns_to_display = array('label', 'nb_visits'); + $this->config->columns_to_display = array('label', 'nb_visits'); $goalColumnTemplates = array( 'goal_%s_nb_conversions', @@ -188,8 +193,7 @@ class Goals extends HtmlTable // ie, goal_0_nb_conversions, goal_1_nb_conversions, etc.) foreach ($goalColumnTemplates as $idx => $columnTemplate) { foreach ($idGoals as $idGoal) { - $column = sprintf($columnTemplate, $idGoal); - $view->columns_to_display[] = $column; + $this->config->columns_to_display[] = sprintf($columnTemplate, $idGoal); } } @@ -198,7 +202,7 @@ class Goals extends HtmlTable $goalName = $allGoals[$idGoal]['name']; $quotedGoalName = $allGoals[$idGoal]['quoted_name'] ? : $goalName; - $view->translations += array( + $this->config->translations += array( 'goal_' . $idGoal . '_nb_conversions' => Piwik::translate('Goals_Conversions', $goalName), 'goal_' . $idGoal . '_conversion_rate' => Piwik::translate('Goals_ConversionRate', $goalName), 'goal_' . $idGoal . '_revenue' => @@ -207,7 +211,7 @@ class Goals extends HtmlTable Piwik::translate('%s ' . Piwik::translate('General_ColumnValuePerVisit'), $goalName), ); - $view->metrics_documentation += array( + $this->config->metrics_documentation += array( 'goal_' . $idGoal . '_nb_conversions' => Piwik::translate('Goals_ColumnConversionsDocumentation', $quotedGoalName), 'goal_' . $idGoal . '_conversion_rate' => Piwik::translate('Goals_ColumnConversionRateDocumentation', $quotedGoalName), 'goal_' . $idGoal . '_revenue' => Piwik::translate('Goals_ColumnRevenueDocumentation', $quotedGoalName), @@ -216,7 +220,7 @@ class Goals extends HtmlTable ); } - $view->columns_to_display[] = 'revenue_per_visit'; + $this->config->columns_to_display[] = 'revenue_per_visit'; } private function getGoals($idSite) @@ -236,6 +240,7 @@ class Goals extends HtmlTable // add the site's goals (and escape all goal names) $siteGoals = APIGoals::getInstance()->getGoals($idSite); + foreach ($siteGoals as &$goal) { $goal['name'] = Common::sanitizeInputValue($goal['name']); diff --git a/plugins/Live/Live.php b/plugins/Live/Live.php index f309877ce00bfdc5e02f6dbfdf40fff85bdb8c56..53e735114e7711f854510de8a2ad4a904b2f9953 100644 --- a/plugins/Live/Live.php +++ b/plugins/Live/Live.php @@ -14,6 +14,8 @@ namespace Piwik\Plugins\Live; use Piwik\Common; use Piwik\Menu\MenuMain; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; +use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; use Piwik\WidgetsList; /** @@ -29,12 +31,13 @@ class Live extends \Piwik\Plugin public function getListHooksRegistered() { return array( - 'AssetManager.getJavaScriptFiles' => 'getJsFiles', - 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', - 'WidgetsList.addWidgets' => 'addWidget', - 'Menu.Reporting.addItems' => 'addMenu', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', - 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', + 'AssetManager.getJavaScriptFiles' => 'getJsFiles', + 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', + 'WidgetsList.addWidgets' => 'addWidget', + 'Menu.Reporting.addItems' => 'addMenu', + 'ViewDataTable.configure' => 'configureViewDataTable', + 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', + 'Visualization.getDefaultViewTypeForReports' => 'getDefaultViewTypeForReports' ); } @@ -73,51 +76,59 @@ class Live extends \Piwik\Plugin $translationKeys[] = "Live_PageRefreshed"; } - public function getReportDisplayProperties(&$properties) + public function configureViewDataTable(ViewDataTable $view) { - $properties['Live.getLastVisitsDetails'] = $this->getDisplayPropertiesForGetLastVisitsDetails(); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'Live.getLastVisitsDetails': + $this->configureViewForGetLastVisitsDetails($view); + break; + } } - private function getDisplayPropertiesForGetLastVisitsDetails() + public function getDefaultViewTypeForReports(&$defaultViewTypes) { - return array( - 'default_view_type' => 'Piwik\\Plugins\\Live\\VisitorLog', - 'disable_generic_filters' => true, - 'enable_sort' => false, - 'filter_sort_column' => 'idVisit', - 'filter_sort_order' => 'asc', - 'show_search' => false, - 'filter_limit' => 20, - 'show_offset_information' => false, - 'show_exclude_low_population' => false, - 'show_all_views_icons' => false, - 'show_table_all_columns' => false, - 'show_export_as_rss_feed' => false, - 'documentation' => Piwik::translate('Live_VisitorLogDocumentation', array('<br />', '<br />')), - 'custom_parameters' => array( - // set a very high row count so that the next link in the footer of the data table is always shown - 'totalRows' => 10000000, - - 'filterEcommerce' => Common::getRequestVar('filterEcommerce', 0, 'int'), - 'pageUrlNotDefined' => Piwik::translate('General_NotDefined', Piwik::translate('Actions_ColumnPageURL')) - ), - 'footer_icons' => array( - array( - 'class' => 'tableAllColumnsSwitch', - 'buttons' => array( - array( - 'id' => 'Piwik\\Plugins\\Live\\VisitorLog', - 'title' => Piwik::translate('Live_LinkVisitorLog'), - 'icon' => 'plugins/Zeitgeist/images/table.png' - ) + $defaultViewTypes['Live.getLastVisitsDetails'] = VisitorLog::ID; + } + + private function configureViewForGetLastVisitsDetails(ViewDataTable $view) + { + $view->config->disable_generic_filters = true; + $view->config->enable_sort = false; + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->show_offset_information = false; + $view->config->show_all_views_icons = false; + $view->config->show_table_all_columns = false; + $view->config->show_export_as_rss_feed = false; + + $view->requestConfig->filter_sort_column = 'idVisit'; + $view->requestConfig->filter_sort_order = 'asc'; + $view->requestConfig->filter_limit = 20; + + $view->config->documentation = Piwik::translate('Live_VisitorLogDocumentation', array('<br />', '<br />')); + $view->config->custom_parameters = array( + // set a very high row count so that the next link in the footer of the data table is always shown + 'totalRows' => 10000000, + + 'filterEcommerce' => Common::getRequestVar('filterEcommerce', 0, 'int'), + 'pageUrlNotDefined' => Piwik::translate('General_NotDefined', Piwik::translate('Actions_ColumnPageURL')) + ); + + $view->config->footer_icons = array( + array( + 'class' => 'tableAllColumnsSwitch', + 'buttons' => array( + array( + 'id' => 'Piwik\\Plugins\\Live\\VisitorLog', + 'title' => Piwik::translate('Live_LinkVisitorLog'), + 'icon' => 'plugins/Zeitgeist/images/table.png' ) ) - ), - 'visualization_properties' => array( - 'table' => array( - 'disable_row_actions' => true, - ) ) ); + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->disable_row_actions = true; + } } } \ No newline at end of file diff --git a/plugins/Live/VisitorLog.php b/plugins/Live/VisitorLog.php index 88b7260bbe9eb8f3fd22ba1c635423a50b139754..4fd5ffd5aa9d4d1d81e5b1f855f277c38e5eff5e 100644 --- a/plugins/Live/VisitorLog.php +++ b/plugins/Live/VisitorLog.php @@ -11,28 +11,31 @@ namespace Piwik\Plugins\Live; use Piwik\View; -use Piwik\ViewDataTable\Visualization; -use Piwik\Visualization\Config; +use Piwik\Plugin\Visualization; /** * A special DataTable visualization for the Live.getLastVisitsDetails API method. */ class VisitorLog extends Visualization { + const ID = 'Piwik\\Plugins\\Live\\VisitorLog'; const TEMPLATE_FILE = "@Live/_dataTableViz_visitorLog.twig"; - static public $clientSideRequestParameters = array( - 'filter_limit', - 'filter_offset', - 'filter_sort_column', - 'filter_sort_order', - ); + public function beforeLoadDataTable() + { + $this->requestConfig->addPropertiesThatShouldBeAvailableClientSide(array( + 'filter_limit', + 'filter_offset', + 'filter_sort_column', + 'filter_sort_order', + )); + } /** * Configure visualization. */ - public function configureVisualization(Config $properties) + public function beforeRender() { - $properties->datatable_js_type = 'VisitorLog'; + $this->config->datatable_js_type = 'VisitorLog'; } } \ No newline at end of file diff --git a/plugins/PrivacyManager/PrivacyManager.php b/plugins/PrivacyManager/PrivacyManager.php index 5b4126a768229b0203c8fbc8ded852de18b5fb01..b647eaa6e5e6eea8a52512d0626167a569a438be 100644 --- a/plugins/PrivacyManager/PrivacyManager.php +++ b/plugins/PrivacyManager/PrivacyManager.php @@ -17,12 +17,16 @@ use Piwik\Date; use Piwik\Db; use Piwik\Menu\MenuAdmin; use Piwik\Metrics; +use Piwik\DataTable\DataTableInterface; use Piwik\Option; +use Piwik\Period\Range; +use Piwik\Period; use Piwik\Piwik; use Piwik\Plugins\Goals\Archiver; use Piwik\ScheduledTask; use Piwik\ScheduledTime\Daily; +use Piwik\Site; use Piwik\Tracker\GoalManager; /** @@ -36,7 +40,6 @@ require_once PIWIK_INCLUDE_PATH . '/plugins/PrivacyManager/LogDataPurger.php'; require_once PIWIK_INCLUDE_PATH . '/plugins/PrivacyManager/ReportsPurger.php'; /** - * * @package PrivacyManager */ class PrivacyManager extends \Piwik\Plugin @@ -63,6 +66,63 @@ class PrivacyManager extends \Piwik\Plugin 'delete_reports_keep_segment_reports' => 0, ); + /** + * Returns true if it is likely that the data for this report has been purged and if the + * user should be told about that. + * + * In order for this function to return true, the following must also be true: + * - The data table for this report must either be empty or not have been fetched. + * - The period of this report is not a multiple period. + * - The date of this report must be older than the delete_reports_older_than config option. + * @param DataTableInterface $dataTable + * @return bool + */ + public static function hasReportBeenPurged($dataTable) + { + $strPeriod = Common::getRequestVar('period', false); + $strDate = Common::getRequestVar('date', false); + + if (false !== $strPeriod + && false !== $strDate + && (is_null($dataTable) + || (!empty($dataTable) && $dataTable->getRowsCount() == 0)) + ) { + // if range, only look at the first date + if ($strPeriod == 'range') { + + $idSite = Common::getRequestVar('idSite', ''); + + if (intval($idSite) != 0) { + $site = new Site($idSite); + $timezone = $site->getTimezone(); + } else { + $timezone = 'UTC'; + } + + $period = new Range('range', $strDate, $timezone); + $reportDate = $period->getDateStart(); + + } elseif (Period::isMultiplePeriod($strDate, $strPeriod)) { + + // if a multiple period, this function is irrelevant + return false; + + } else { + // otherwise, use the date as given + $reportDate = Date::factory($strDate); + } + + $reportYear = $reportDate->toString('Y'); + $reportMonth = $reportDate->toString('m'); + + if (static::shouldReportBePurged($reportYear, $reportMonth)) { + return true; + } + } + + return false; + } + /** * @see Piwik_Plugin::getListHooksRegistered */ diff --git a/plugins/Provider/Provider.php b/plugins/Provider/Provider.php index 41dc2e6fffd9c664f2f8cf76a4e89f339d66c377..8537b8527fb070eec18e92e2db96e81e86ded10b 100644 --- a/plugins/Provider/Provider.php +++ b/plugins/Provider/Provider.php @@ -19,6 +19,7 @@ use Piwik\FrontController; use Piwik\IP; use Piwik\Menu\MenuMain; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; use Piwik\WidgetsList; /** @@ -33,14 +34,14 @@ class Provider extends \Piwik\Plugin public function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'Tracker.newVisitorInformation' => 'logProviderInfo', - 'WidgetsList.addWidgets' => 'addWidget', - 'Menu.Reporting.addItems' => 'addMenu', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'Tracker.newVisitorInformation' => 'logProviderInfo', + 'WidgetsList.addWidgets' => 'addWidget', + 'Menu.Reporting.addItems' => 'addMenu', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.configure' => 'configureViewDataTable', ); return $hooks; } @@ -235,16 +236,18 @@ class Provider extends \Piwik\Plugin } } - public function getReportDisplayProperties(&$properties) + public function configureViewDataTable(ViewDataTable $view) { - $properties['Provider.getProvider'] = $this->getDisplayPropertiesForGetProvider(); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'Provider.getProvider': + $this->configureViewForGetProvider($view); + break; + } } - private function getDisplayPropertiesForGetProvider() + private function configureViewForGetProvider(ViewDataTable $view) { - return array( - 'translations' => array('label' => Piwik::translate('Provider_ColumnProvider')), - 'filter_limit' => 5 - ); + $view->requestConfig->filter_limit = 5; + $view->config->addTranslation('label', Piwik::translate('Provider_ColumnProvider')); } } diff --git a/plugins/Referrers/Controller.php b/plugins/Referrers/Controller.php index 2c4cfd5fb9f5094c6b9dd14bba81c7c30cc78f73..bf15aa9f74848b4302117119423d27dc66d62f9b 100644 --- a/plugins/Referrers/Controller.php +++ b/plugins/Referrers/Controller.php @@ -265,7 +265,7 @@ class Controller extends \Piwik\Plugin\Controller { $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Referrers.getReferrerType'); - $view->visualization_properties->add_total_row = true; + $view->config->add_total_row = true; // configure displayed columns if (empty($columns)) { @@ -273,7 +273,7 @@ class Controller extends \Piwik\Plugin\Controller $columns = Piwik::getArrayFromApiParameter($columns); } $columns = !is_array($columns) ? array($columns) : $columns; - $view->columns_to_display = $columns; + $view->config->columns_to_display = $columns; // configure selectable columns if (Common::getRequestVar('period', false) == 'day') { @@ -281,7 +281,7 @@ class Controller extends \Piwik\Plugin\Controller } else { $selectable = array('nb_visits', 'nb_actions'); } - $view->visualization_properties->selectable_columns = $selectable; + $view->config->selectable_columns = $selectable; // configure displayed rows $visibleRows = Common::getRequestVar('rows', false); @@ -290,7 +290,7 @@ class Controller extends \Piwik\Plugin\Controller $visibleRows = Piwik::getArrayFromApiParameter($visibleRows); // typeReferrer is redundant if rows are defined, so make sure it's not used - $view->custom_parameters['typeReferrer'] = false; + $view->config->custom_parameters['typeReferrer'] = false; } else { // use $typeReferrer as default if ($typeReferrer === false) { @@ -299,12 +299,12 @@ class Controller extends \Piwik\Plugin\Controller $label = self::getTranslatedReferrerTypeLabel($typeReferrer); $total = Piwik::translate('General_Total'); $visibleRows = array($label, $total); - $view->request_parameters_to_modify['rows'] = $label . ',' . $total; + $view->requestConfig->request_parameters_to_modify['rows'] = $label . ',' . $total; } - $view->visualization_properties->row_picker_match_rows_by = 'label'; - $view->visualization_properties->rows_to_display = $visibleRows; + $view->config->row_picker_match_rows_by = 'label'; + $view->config->rows_to_display = $visibleRows; - $view->documentation = Piwik::translate('Referrers_EvolutionDocumentation') . '<br />' + $view->config->documentation = Piwik::translate('Referrers_EvolutionDocumentation') . '<br />' . Piwik::translate('General_BrokenDownReportDocumentation') . '<br />' . Piwik::translate('Referrers_EvolutionDocumentationMoreInfo', '"' . Piwik::translate('Referrers_DetailsByReferrerType') . '"'); @@ -315,32 +315,32 @@ class Controller extends \Piwik\Plugin\Controller public function getLastDistinctSearchEnginesGraph($fetch = false) { $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "Referrers.getNumberOfDistinctSearchEngines"); - $view->translations['Referrers_distinctSearchEngines'] = ucfirst(Piwik::translate('Referrers_DistinctSearchEngines')); - $view->columns_to_display = array('Referrers_distinctSearchEngines'); + $view->config->translations['Referrers_distinctSearchEngines'] = ucfirst(Piwik::translate('Referrers_DistinctSearchEngines')); + $view->config->columns_to_display = array('Referrers_distinctSearchEngines'); return $this->renderView($view, $fetch); } public function getLastDistinctKeywordsGraph($fetch = false) { $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "Referrers.getNumberOfDistinctKeywords"); - $view->translations['Referrers_distinctKeywords'] = ucfirst(Piwik::translate('Referrers_DistinctKeywords')); - $view->columns_to_display = array('Referrers_distinctKeywords'); + $view->config->translations['Referrers_distinctKeywords'] = ucfirst(Piwik::translate('Referrers_DistinctKeywords')); + $view->config->columns_to_display = array('Referrers_distinctKeywords'); return $this->renderView($view, $fetch); } public function getLastDistinctWebsitesGraph($fetch = false) { $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "Referrers.getNumberOfDistinctWebsites"); - $view->translations['Referrers_distinctWebsites'] = ucfirst(Piwik::translate('Referrers_DistinctWebsites')); - $view->columns_to_display = array('Referrers_distinctWebsites'); + $view->config->translations['Referrers_distinctWebsites'] = ucfirst(Piwik::translate('Referrers_DistinctWebsites')); + $view->config->columns_to_display = array('Referrers_distinctWebsites'); return $this->renderView($view, $fetch); } public function getLastDistinctCampaignsGraph($fetch = false) { $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "Referrers.getNumberOfDistinctCampaigns"); - $view->translations['Referrers_distinctCampaigns'] = ucfirst(Piwik::translate('Referrers_DistinctCampaigns')); - $view->columns_to_display = array('Referrers_distinctCampaigns'); + $view->config->translations['Referrers_distinctCampaigns'] = ucfirst(Piwik::translate('Referrers_DistinctCampaigns')); + $view->config->columns_to_display = array('Referrers_distinctCampaigns'); return $this->renderView($view, $fetch); } diff --git a/plugins/Referrers/Referrers.php b/plugins/Referrers/Referrers.php index e2714706ebe29124ad4a3d260ff764c561de718c..099c0b10758b8ef6f92c2e3602657546b353b6e8 100644 --- a/plugins/Referrers/Referrers.php +++ b/plugins/Referrers/Referrers.php @@ -14,6 +14,10 @@ use Piwik\ArchiveProcessor; use Piwik\Common; use Piwik\Menu\MenuMain; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; +use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable\AllColumns; +use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; +use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Pie; use Piwik\SettingsPiwik; use Piwik\WidgetsList; @@ -33,14 +37,15 @@ class Referrers extends \Piwik\Plugin public function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'WidgetsList.addWidgets' => 'addWidgets', - 'Menu.Reporting.addItems' => 'addMenus', - 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'WidgetsList.addWidgets' => 'addWidgets', + 'Menu.Reporting.addItems' => 'addMenus', + 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.configure' => 'configureViewDataTable', + 'Visualization.getDefaultViewTypeForReports' => 'getDefaultViewTypeForReports' ); return $hooks; } @@ -295,26 +300,59 @@ class Referrers extends \Piwik\Plugin } } - public function getReportDisplayProperties(&$properties) + public function getDefaultViewTypeForReports(&$defaultViewTypes) { - $properties['Referrers.getReferrerType'] = $this->getDisplayPropertiesForGetReferrerType(); - $properties['Referrers.getAll'] = $this->getDisplayPropertiesForGetAll(); - $properties['Referrers.getKeywords'] = $this->getDisplayPropertiesForGetKeywords(); - $properties['Referrers.getSearchEnginesFromKeywordId'] = $this->getDisplayPropertiesForGetSearchEnginesFromKeywordId(); - $properties['Referrers.getSearchEngines'] = $this->getDisplayPropertiesForGetSearchEngines(); - $properties['Referrers.getKeywordsFromSearchEngineId'] = $this->getDisplayPropertiesForGetKeywordsFromSearchEngineId(); - $properties['Referrers.getWebsites'] = $this->getDisplayPropertiesForGetWebsites(); - $properties['Referrers.getSocials'] = $this->getDisplayPropertiesForGetSocials(); - $properties['Referrers.getUrlsForSocial'] = $this->getDisplayPropertiesForGetUrlsForSocial(); - $properties['Referrers.getCampaigns'] = $this->getDisplayPropertiesForGetCampaigns(); - $properties['Referrers.getKeywordsFromCampaignId'] = $this->getDisplayPropertiesForGetKeywordsFromCampaignId(); - $properties['Referrers.getUrlsFromWebsiteId'] = $this->getDisplayPropertiesForGetUrlsFromWebsiteId(); + $defaultViewTypes['Referrers.getReferrerType'] = AllColumns::ID; + $defaultViewTypes['Referrers.getSocials'] = Pie::ID; } - private function getDisplayPropertiesForGetReferrerType() + public function configureViewDataTable(ViewDataTable $view) { - $idSubtable = Common::getRequestVar('idSubtable', false); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'Referrers.getReferrerType': + $this->configureViewForGetReferrerType($view); + break; + case 'Referrers.getAll': + $this->configureViewForGetAll($view); + break; + case 'Referrers.getKeywords': + $this->configureViewForGetKeywords($view); + break; + case 'Referrers.getSearchEnginesFromKeywordId': + $this->configureViewForGetSearchEnginesFromKeywordId($view); + break; + case 'Referrers.getSearchEngines': + $this->configureViewForGetSearchEngines($view); + break; + case 'Referrers.getKeywordsFromSearchEngineId': + $this->configureViewForGetKeywordsFromSearchEngineId($view); + break; + case 'Referrers.getWebsites': + $this->configureViewForGetWebsites($view); + break; + case 'Referrers.getSocials': + $this->configureViewForGetSocials($view); + break; + case 'Referrers.getUrlsForSocial': + $this->configureViewForGetUrlsForSocial($view); + break; + case 'Referrers.getCampaigns': + $this->configureViewForGetCampaigns($view); + break; + case 'Referrers.getKeywordsFromCampaignId': + $this->configureViewForGetKeywordsFromCampaignId($view); + break; + case 'Referrers.getUrlsFromWebsiteId': + $this->configureViewForGetUrlsFromWebsiteId($view); + break; + } + } + + private function configureViewForGetReferrerType(ViewDataTable $view) + { + $idSubtable = Common::getRequestVar('idSubtable', false); $labelColumnTitle = Piwik::translate('Referrers_Type'); + switch ($idSubtable) { case Common::REFERRER_TYPE_SEARCH_ENGINE: $labelColumnTitle = Piwik::translate('Referrers_ColumnSearchEngine'); @@ -329,182 +367,154 @@ class Referrers extends \Piwik\Plugin break; } - return array( - 'default_view_type' => 'tableAllColumns', - 'show_search' => false, - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'show_exclude_low_population' => false, - 'show_goals' => true, - 'filter_limit' => 10, - 'translations' => array('label' => $labelColumnTitle), - 'visualization_properties' => array( - 'table' => array( - 'disable_subtable_when_show_goals' => true, - ) - ), - ); + $view->config->show_search = false; + $view->config->show_goals = true; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_limit_control = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', $labelColumnTitle); + + $view->requestConfig->filter_limit = 10; + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->disable_subtable_when_show_goals = true; + } } - private function getDisplayPropertiesForGetAll() + private function configureViewForGetAll(ViewDataTable $view) { $setGetAllHtmlPrefix = array($this, 'setGetAllHtmlPrefix'); - return array( - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate('Referrers_Referrer')), - 'show_goals' => true, - 'filter_limit' => 20, - 'visualization_properties' => array( - 'table' => array( - 'disable_row_actions' => true - ) - ), - 'filters' => array( - array('MetadataCallbackAddMetadata', array('referer_type', 'html_label_prefix', $setGetAllHtmlPrefix)) - ) - ); + + $view->config->show_exclude_low_population = false; + $view->config->show_goals = true; + $view->config->addTranslation('label', Piwik::translate('Referrers_Referrer')); + + $view->requestConfig->filter_limit = 20; + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->disable_row_actions = true; + } + + $view->config->filters[] = array('MetadataCallbackAddMetadata', array('referer_type', 'html_label_prefix', $setGetAllHtmlPrefix)); } - private function getDisplayPropertiesForGetKeywords() + private function configureViewForGetKeywords(ViewDataTable $view) { - return array( - 'subtable_controller_action' => 'getSearchEnginesFromKeywordId', - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate('General_ColumnKeyword')), - 'show_goals' => true, - 'filter_limit' => 25, - 'visualization_properties' => array( - 'table' => array( - 'disable_subtable_when_show_goals' => true, - ) - ), - ); + $view->config->subtable_controller_action = 'getSearchEnginesFromKeywordId'; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('General_ColumnKeyword')); + $view->config->show_goals = true; + + $view->requestConfig->filter_limit = 25; + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->disable_subtable_when_show_goals = true; + } } - private function getDisplayPropertiesForGetSearchEnginesFromKeywordId() + private function configureViewForGetSearchEnginesFromKeywordId(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate('Referrers_ColumnSearchEngine')) - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('Referrers_ColumnSearchEngine')); } - private function getDisplayPropertiesForGetSearchEngines() + private function configureViewForGetSearchEngines(ViewDataTable $view) { - return array( - 'subtable_controller_action' => 'getKeywordsFromSearchEngineId', - 'show_search' => false, - 'show_exclude_low_population' => false, - 'show_goals' => true, - 'filter_limit' => 25, - 'translations' => array('label' => Piwik::translate('Referrers_ColumnSearchEngine')), - 'visualization_properties' => array( - 'table' => array( - 'disable_subtable_when_show_goals' => true, - ) - ), - ); + $view->config->subtable_controller_action = 'getKeywordsFromSearchEngineId'; + $view->config->show_exclude_low_population = false; + $view->config->show_search = false; + $view->config->show_goals = true; + $view->config->addTranslation('label', Piwik::translate('Referrers_ColumnSearchEngine')); + + $view->requestConfig->filter_limit = 25; + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->disable_subtable_when_show_goals = true; + } } - private function getDisplayPropertiesForGetKeywordsFromSearchEngineId() + private function configureViewForGetKeywordsFromSearchEngineId(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate('General_ColumnKeyword')) - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('General_ColumnKeyword')); } - private function getDisplayPropertiesForGetWebsites() + private function configureViewForGetWebsites(ViewDataTable $view) { - return array( - 'subtable_controller_action' => 'getUrlsFromWebsiteId', - 'show_exclude_low_population' => false, - 'show_goals' => true, - 'filter_limit' => 25, - 'translations' => array('label' => Piwik::translate('Referrers_ColumnWebsite')), - 'visualization_properties' => array( - 'table' => array( - 'disable_subtable_when_show_goals' => true, - ) - ), - ); + $view->config->subtable_controller_action = 'getUrlsFromWebsiteId'; + $view->config->show_exclude_low_population = false; + $view->config->show_goals = true; + $view->config->addTranslation('label', Piwik::translate('Referrers_ColumnWebsite')); + + $view->requestConfig->filter_limit = 25; + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->disable_subtable_when_show_goals = true; + } } - private function getDisplayPropertiesForGetSocials() + private function configureViewForGetSocials(ViewDataTable $view) { - $result = array( - 'default_view_type' => 'graphPie', - 'subtable_controller_action' => 'getUrlsForSocial', - 'show_exclude_low_population' => false, - 'filter_limit' => 10, - 'show_goals' => true, - 'translations' => array('label' => Piwik::translate('Referrers_ColumnSocial')), - 'visualization_properties' => array( - 'table' => array( - 'disable_subtable_when_show_goals' => true, - ) - ), - ); + $view->config->subtable_controller_action = 'getUrlsForSocial'; + $view->config->show_exclude_low_population = false; + $view->config->show_goals = true; + $view->config->addTranslation('label', Piwik::translate('Referrers_ColumnSocial')); + + $view->requestConfig->filter_limit = 10; + + if ($view->isViewDataTableId(HtmlTable::ID)) { + $view->config->disable_subtable_when_show_goals = true; + } $widget = Common::getRequestVar('widget', false); if (empty($widget)) { - $result['show_footer_message'] = Piwik::translate('Referrers_SocialFooterMessage'); + $view->config->show_footer_message = Piwik::translate('Referrers_SocialFooterMessage'); } - - return $result; } - private function getDisplayPropertiesForGetUrlsForSocial() + private function configureViewForGetUrlsForSocial(ViewDataTable $view) { - return array( - 'show_exclude_low_population' => false, - 'filter_limit' => 10, - 'show_goals' => true, - 'translations' => array('label' => Piwik::translate('Referrers_ColumnWebsitePage')) - ); + $view->config->show_goals = true; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('Referrers_ColumnWebsitePage')); + + $view->requestConfig->filter_limit = 10; } - private function getDisplayPropertiesForGetCampaigns() + private function configureViewForGetCampaigns(ViewDataTable $view) { - $result = array( - 'subtable_controller_action' => 'getKeywordsFromCampaignId', - 'show_exclude_low_population' => false, - 'show_goals' => true, - 'filter_limit' => 25, - 'translations' => array('label' => Piwik::translate('Referrers_ColumnCampaign')), - ); + $view->config->show_goals = true; + $view->config->subtable_controller_action = 'getKeywordsFromCampaignId'; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('Referrers_ColumnCampaign')); + + $view->requestConfig->filter_limit = 25; if (Common::getRequestVar('viewDataTable', false) != 'graphEvolution') { - $result['show_footer_message'] = Piwik::translate('Referrers_CampaignFooterHelp', + $view->config->show_footer_message = Piwik::translate('Referrers_CampaignFooterHelp', array('<a target="_blank" href="http://piwik.org/docs/tracking-campaigns/">', '</a> - <a target="_blank" href="http://piwik.org/docs/tracking-campaigns/url-builder/">', '</a>') ); } - - return $result; } - private function getDisplayPropertiesForGetKeywordsFromCampaignId() + private function configureViewForGetKeywordsFromCampaignId(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate('General_ColumnKeyword')) - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('General_ColumnKeyword')); } - private function getDisplayPropertiesForGetUrlsFromWebsiteId() + private function configureViewForGetUrlsFromWebsiteId(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'translations' => array('label' => Piwik::translate('Referrers_ColumnWebsitePage')), - 'tooltip_metadata_name' => 'url' - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + $view->config->tooltip_metadata_name = 'url'; + $view->config->addTranslation('label', Piwik::translate('Referrers_ColumnWebsitePage')); } /** diff --git a/plugins/SecurityInfo b/plugins/SecurityInfo index 2eb4c066acbe1293abde25017fa100637ad5bd2d..fd8f764b9b6af55ed821aa6737a88d43ba3e76ac 160000 --- a/plugins/SecurityInfo +++ b/plugins/SecurityInfo @@ -1 +1 @@ -Subproject commit 2eb4c066acbe1293abde25017fa100637ad5bd2d +Subproject commit fd8f764b9b6af55ed821aa6737a88d43ba3e76ac diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php index 612d6de6f1d231c52623f11649db3e520c40e4e9..3a8ba91bfa3ce21b92eb0e9dba3968eb9b7c5451 100644 --- a/plugins/SitesManager/API.php +++ b/plugins/SitesManager/API.php @@ -42,7 +42,7 @@ use Piwik\UrlHelper; * The existing values can be fetched via "getExcludedIpsGlobal" and "getExcludedQueryParametersGlobal". * See also the documentation about <a href='http://piwik.org/docs/manage-websites/' target='_blank'>Managing Websites</a> in Piwik. * @package SitesManager - * @method \Piwik\Plugins\SitesManager\API getInstance() + * @static \Piwik\Plugins\SitesManager\API getInstance() */ class API extends \Piwik\Plugin\API { diff --git a/plugins/TreemapVisualization b/plugins/TreemapVisualization index c7aa4ca6d2f24f9a105134ea533d43e90c5b1890..dd0a8cdc4a377d4eff49f53d0015dd25332ef9d7 160000 --- a/plugins/TreemapVisualization +++ b/plugins/TreemapVisualization @@ -1 +1 @@ -Subproject commit c7aa4ca6d2f24f9a105134ea533d43e90c5b1890 +Subproject commit dd0a8cdc4a377d4eff49f53d0015dd25332ef9d7 diff --git a/plugins/UserCountry/Controller.php b/plugins/UserCountry/Controller.php index b207bc24970b187f0e4d3391e4131748ac0bf3ef..7390c8d687b89bd8984d978ae82738d9ab165b99 100644 --- a/plugins/UserCountry/Controller.php +++ b/plugins/UserCountry/Controller.php @@ -365,7 +365,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin public function getLastDistinctCountriesGraph($fetch = false) { $view = $this->getLastUnitGraph('UserCountry', __FUNCTION__, "UserCountry.getNumberOfDistinctCountries"); - $view->columns_to_display = array('UserCountry_distinctCountries'); + $view->config->columns_to_display = array('UserCountry_distinctCountries'); return $this->renderView($view, $fetch); } diff --git a/plugins/UserCountry/UserCountry.php b/plugins/UserCountry/UserCountry.php index 2a8fb5af51c21b95fe8c350149eb80ece2b1fc14..64bd49c3b26bc5028e499509553297a1cb3cf4d3 100644 --- a/plugins/UserCountry/UserCountry.php +++ b/plugins/UserCountry/UserCountry.php @@ -16,6 +16,7 @@ use Piwik\IP; use Piwik\Menu\MenuAdmin; use Piwik\Menu\MenuMain; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; use Piwik\Plugins\UserCountry\LocationProvider\DefaultProvider; use Piwik\Plugins\UserCountry\LocationProvider; use Piwik\Plugins\UserCountry\LocationProvider\GeoIp; @@ -40,21 +41,21 @@ class UserCountry extends \Piwik\Plugin public function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'WidgetsList.addWidgets' => 'addWidgets', - 'Menu.Reporting.addItems' => 'addMenu', - 'Menu.Admin.addItems' => 'addAdminMenu', - 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', - 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', - 'AssetManager.getJavaScriptFiles' => 'getJsFiles', - 'Tracker.newVisitorInformation' => 'getVisitorLocation', - 'TaskScheduler.getScheduledTasks' => 'getScheduledTasks', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', - 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', - 'Tracker.setTrackerCacheGeneral' => 'setTrackerCacheGeneral' + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'WidgetsList.addWidgets' => 'addWidgets', + 'Menu.Reporting.addItems' => 'addMenu', + 'Menu.Admin.addItems' => 'addAdminMenu', + 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', + 'AssetManager.getJavaScriptFiles' => 'getJsFiles', + 'Tracker.newVisitorInformation' => 'getVisitorLocation', + 'TaskScheduler.getScheduledTasks' => 'getScheduledTasks', + 'ViewDataTable.configure' => 'configureViewDataTable', + 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', + 'Tracker.setTrackerCacheGeneral' => 'setTrackerCacheGeneral' ); return $hooks; } @@ -363,23 +364,32 @@ class UserCountry extends \Piwik\Plugin 'bind' => '-'); // HACK: SegmentExpression requires a $bind, even if there's nothing to bind } - public function getReportDisplayProperties(&$properties) + public function configureViewDataTable(ViewDataTable $view) { - $properties['UserCountry.getCountry'] = $this->getDisplayPropertiesForGetCountry(); - $properties['UserCountry.getContinent'] = $this->getDisplayPropertiesForGetContinent(); - $properties['UserCountry.getRegion'] = $this->getDisplayPropertiesForGetRegion(); - $properties['UserCountry.getCity'] = $this->getDisplayPropertiesForGetCity(); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'UserCountry.getCountry': + $this->configureViewForGetCountry($view); + break; + case 'UserCountry.getContinent': + $this->configureViewForGetContinent($view); + break; + case 'UserCountry.getRegion': + $this->configureViewForGetRegion($view); + break; + case 'UserCountry.getCity': + $this->configureViewForGetCity($view); + break; + } } - private function getDisplayPropertiesForGetCountry() + private function configureViewForGetCountry(ViewDataTable $view) { - $result = array( - 'show_exclude_low_population' => false, - 'show_goals' => true, - 'filter_limit' => 5, - 'translations' => array('label' => Piwik::translate('UserCountry_Country')), - 'documentation' => Piwik::translate('UserCountry_getCountryDocumentation') - ); + $view->config->show_goals = true; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('UserCountry_Country')); + $view->config->documentation = Piwik::translate('UserCountry_getCountryDocumentation'); + + $view->requestConfig->filter_limit = 5; if (LocationProvider::getCurrentProviderId() == DefaultProvider::ID) { // if we're using the default location provider, add a note explaining how it works @@ -387,52 +397,44 @@ class UserCountry extends \Piwik\Plugin . Piwik::translate('UserCountry_DefaultLocationProviderExplanation', array('<a target="_blank" href="http://piwik.org/docs/geo-locate/">', '</a>')); - $result['show_footer_message'] = $footerMessage; + $view->config->show_footer_message = $footerMessage; } - - return $result; } - private function getDisplayPropertiesForGetContinent() + private function configureViewForGetContinent(ViewDataTable $view) { - return array( - 'show_exclude_low_population' => false, - 'show_goals' => true, - 'show_search' => false, - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'translations' => array('label' => Piwik::translate('UserCountry_Continent')), - 'documentation' => Piwik::translate('UserCountry_getContinentDocumentation') - ); + $view->config->show_exclude_low_population = false; + $view->config->show_goals = true; + $view->config->show_search = false; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_limit_control = false; + $view->config->documentation = Piwik::translate('UserCountry_getContinentDocumentation'); + $view->config->addTranslation('label', Piwik::translate('UserCountry_Continent')); } - private function getDisplayPropertiesForGetRegion() + private function configureViewForGetRegion(ViewDataTable $view) { - $result = array( - 'show_exclude_low_population' => false, - 'show_goals' => true, - 'filter_limit' => 5, - 'translations' => array('label' => Piwik::translate('UserCountry_Region')), - 'documentation' => Piwik::translate('UserCountry_getRegionDocumentation') . '<br/>' - . $this->getGeoIPReportDocSuffix() - ); - $this->checkIfNoDataForGeoIpReport($result); - return $result; + $view->config->show_exclude_low_population = false; + $view->config->show_goals = true; + $view->config->documentation = Piwik::translate('UserCountry_getRegionDocumentation') . '<br/>' . $this->getGeoIPReportDocSuffix(); + $view->config->addTranslation('label', Piwik::translate('UserCountry_Region')); + + $view->requestConfig->filter_limit = 5; + + $this->checkIfNoDataForGeoIpReport($view); } - private function getDisplayPropertiesForGetCity() + private function configureViewForGetCity(ViewDataTable $view) { - $result = array( - 'show_exclude_low_population' => false, - 'show_goals' => true, - 'filter_limit' => 5, - 'translations' => array('label' => Piwik::translate('UserCountry_City')), - 'documentation' => Piwik::translate('UserCountry_getCityDocumentation') . '<br/>' - . $this->getGeoIPReportDocSuffix() - ); - $this->checkIfNoDataForGeoIpReport($result); - return $result; + $view->config->show_exclude_low_population = false; + $view->config->show_goals = true; + $view->config->documentation = Piwik::translate('UserCountry_getCityDocumentation') . '<br/>' . $this->getGeoIPReportDocSuffix(); + $view->config->addTranslation('label', Piwik::translate('UserCountry_City')); + + $view->requestConfig->filter_limit = 5; + + $this->checkIfNoDataForGeoIpReport($view); } private function getGeoIPReportDocSuffix() @@ -449,10 +451,10 @@ class UserCountry extends \Piwik\Plugin * Checks if a datatable for a view is empty and if so, displays a message in the footer * telling users to configure GeoIP. */ - private function checkIfNoDataForGeoIpReport(&$properties) + private function checkIfNoDataForGeoIpReport(ViewDataTable $view) { $self = $this; - $properties['filters'][] = function ($dataTable, $view) use ($self) { + $view->config->filters[] = function ($dataTable) use ($self, $view) { // if there's only one row whose label is 'Unknown', display a message saying there's no data if ($dataTable->getRowsCount() == 1 && $dataTable->getFirstRow()->getColumn('label') == Piwik::translate('General_Unknown') @@ -472,7 +474,7 @@ class UserCountry extends \Piwik\Plugin array('<a target="_blank" href="http://piwik.org/faq/how-to/#faq_167">', '</a>')); } - $view->show_footer_message = $footerMessage; + $view->config->show_footer_message = $footerMessage; } }; } diff --git a/plugins/UserSettings/UserSettings.php b/plugins/UserSettings/UserSettings.php index 8db1ba1dbf23ab1cb0e4fd6f4c1043a8e726f957..2f0124952ea973563433d3f08fd9722ba623d282 100644 --- a/plugins/UserSettings/UserSettings.php +++ b/plugins/UserSettings/UserSettings.php @@ -13,6 +13,10 @@ namespace Piwik\Plugins\UserSettings; use Piwik\ArchiveProcessor; use Piwik\Menu\MenuMain; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; +use Piwik\Plugins\CoreVisualizations\Visualizations\Graph; +use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; +use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Pie; use Piwik\WidgetsList; /** @@ -165,150 +169,185 @@ class UserSettings extends \Piwik\Plugin public function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'WidgetsList.addWidgets' => 'addWidgets', - 'Menu.Reporting.addItems' => 'addMenu', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'WidgetsList.addWidgets' => 'addWidgets', + 'Menu.Reporting.addItems' => 'addMenu', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.configure' => 'configureViewDataTable', + 'Visualization.getDefaultViewTypeForReports' => 'getDefaultViewTypeForReports' ); return $hooks; } - public function getReportDisplayProperties(&$properties) + public function getDefaultViewTypeForReports(&$defaultViewTypes) { - $properties['UserSettings.getResolution'] = $this->getDisplayPropertiesForGetResolution(); - $properties['UserSettings.getConfiguration'] = $this->getDisplayPropertiesForGetConfiguration(); - $properties['UserSettings.getOS'] = $this->getDisplayPropertiesForGetOS(); - $properties['UserSettings.getOSFamily'] = $this->getDisplayPropertiesForGetOSFamily(); - $properties['UserSettings.getBrowserVersion'] = $this->getDisplayPropertiesForGetBrowserVersion(); - $properties['UserSettings.getBrowser'] = $this->getDisplayPropertiesForGetBrowser(); - $properties['UserSettings.getBrowserType'] = $this->getDisplayPropertiesForGetBrowserType(); - $properties['UserSettings.getWideScreen'] = $this->getDisplayPropertiesForGetWideScreen(); - $properties['UserSettings.getMobileVsDesktop'] = $this->getDisplayPropertiesForGetMobileVsDesktop(); - $properties['UserSettings.getPlugin'] = $this->getDisplayPropertiesForGetPlugin(); - $properties['UserSettings.getLanguage'] = $this->getDisplayPropertiesForGetLanguage(); + $defaultViewTypes['UserSettings.getBrowserType'] = Pie::ID; } - private function getDisplayPropertiesForGetResolution() + public function configureViewDataTable(ViewDataTable $view) { - return array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'translations' => array('label' => Piwik::translate('UserSettings_ColumnResolution')) - )); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'UserSettings.getResolution': + $this->configureViewForGetResolution($view); + break; + case 'UserSettings.getConfiguration': + $this->configureViewForGetConfiguration($view); + break; + case 'UserSettings.getOS': + $this->configureViewForGetOS($view); + break; + case 'UserSettings.getOSFamily': + $this->configureViewForGetOSFamily($view); + break; + case 'UserSettings.getBrowserVersion': + $this->configureViewForGetBrowserVersion($view); + break; + case 'UserSettings.getBrowser': + $this->configureViewForGetBrowser($view); + break; + case 'UserSettings.getBrowserType': + $this->configureViewForGetBrowserType($view); + break; + case 'UserSettings.getWideScreen': + $this->configureViewForGetWideScreen($view); + break; + case 'UserSettings.getMobileVsDesktop': + $this->configureViewForGetMobileVsDesktop($view); + break; + case 'UserSettings.getPlugin': + $this->configureViewForGetPlugin($view); + break; + case 'UserSettings.getLanguage': + $this->configureViewForGetLanguage($view); + break; + } } - private function getDisplayPropertiesForGetConfiguration() + private function configureViewForGetResolution(ViewDataTable $view) { - return array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'filter_limit' => 3, - 'translations' => array('label' => Piwik::translate('UserSettings_ColumnConfiguration')) - )); + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->addTranslation('label', Piwik::translate('UserSettings_ColumnResolution')); } - private function getDisplayPropertiesForGetOS() + private function configureViewForGetConfiguration(ViewDataTable $view) { - return array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'translations' => array('label' => Piwik::translate('UserSettings_ColumnOperatingSystem')), - 'title' => Piwik::translate('UserSettings_OperatingSystems'), - 'related_reports' => $this->getOsRelatedReports() - )); + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->addTranslation('label', Piwik::translate('UserSettings_ColumnConfiguration')); + + $view->requestConfig->filter_limit = 3; } - private function getDisplayPropertiesForGetOSFamily() + private function configureViewForGetOS(ViewDataTable $view) { - return array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'translations' => array('label' => Piwik::translate('UserSettings_OperatingSystemFamily')), - 'title' => Piwik::translate('UserSettings_OperatingSystemFamily'), - 'related_reports' => $this->getOsRelatedReports() - )); + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->title = Piwik::translate('UserSettings_OperatingSystems'); + $view->config->addTranslation('label', Piwik::translate('UserSettings_ColumnOperatingSystem')); + $view->config->addRelatedReports($this->getOsRelatedReports()); } - private function getDisplayPropertiesForGetBrowserVersion() + private function configureViewForGetOSFamily(ViewDataTable $view) { - $result = array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'translations' => array('label' => Piwik::translate('UserSettings_ColumnBrowserVersion')), - 'title' => Piwik::translate('UserSettings_ColumnBrowserVersion'), - 'related_reports' => $this->getBrowserRelatedReports() - )); - $result['visualization_properties']['graph']['max_graph_elements'] = 7; - return $result; + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->title = Piwik::translate('UserSettings_OperatingSystemFamily'); + $view->config->addTranslation('label', Piwik::translate('UserSettings_OperatingSystemFamily')); + $view->config->addRelatedReports($this->getOsRelatedReports()); } - private function getDisplayPropertiesForGetBrowser() + private function configureViewForGetBrowserVersion(ViewDataTable $view) { - $result = array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'translations' => array('label' => Piwik::translate('UserSettings_ColumnBrowser')), - 'title' => Piwik::translate('UserSettings_Browsers'), - 'related_reports' => $this->getBrowserRelatedReports() - )); - $result['visualization_properties']['graph']['max_graph_elements'] = 7; - return $result; + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->title = Piwik::translate('UserSettings_ColumnBrowserVersion'); + $view->config->addTranslation('label', Piwik::translate('UserSettings_ColumnBrowserVersion')); + $view->config->addRelatedReports($this->getBrowserRelatedReports()); + + if ($view->isViewDataTableId(Graph::ID)) { + $view->config->max_graph_elements = 7; + } } - private function getDisplayPropertiesForGetBrowserType() + private function configureViewForGetBrowser(ViewDataTable $view) { - return array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'translations' => array('label' => Piwik::translate('UserSettings_ColumnBrowserFamily')), - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'default_view_type' => 'graphPie', - )); + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->title = Piwik::translate('UserSettings_Browsers'); + $view->config->addTranslation('label', Piwik::translate('UserSettings_ColumnBrowser')); + $view->config->addRelatedReports($this->getBrowserRelatedReports()); + + if ($view->isViewDataTableId(Graph::ID)) { + $view->config->max_graph_elements = 7; + } } - private function getDisplayPropertiesForGetWideScreen() + private function configureViewForGetBrowserType(ViewDataTable $view) { - return array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'translations' => array('label' => Piwik::translate('UserSettings_ColumnTypeOfScreen')), - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'title' => Piwik::translate('UserSettings_ColumnTypeOfScreen'), - 'related_reports' => $this->getWideScreenDeviceTypeRelatedReports() - )); + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->addTranslation('label', Piwik::translate('UserSettings_ColumnBrowserFamily')); + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_limit_control = false; } - private function getDisplayPropertiesForGetMobileVsDesktop() + private function configureViewForGetWideScreen(ViewDataTable $view) { - return array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'translations' => array('label' => Piwik::translate('UserSettings_MobileVsDesktop')), - 'title' => Piwik::translate('UserSettings_MobileVsDesktop'), - 'related_reports' => $this->getWideScreenDeviceTypeRelatedReports() - )); + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->title = Piwik::translate('UserSettings_ColumnTypeOfScreen'); + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_limit_control = false; + $view->config->addTranslation('label', Piwik::translate('UserSettings_ColumnTypeOfScreen')); + $view->config->addRelatedReports($this->getWideScreenDeviceTypeRelatedReports()); } - private function getDisplayPropertiesForGetPlugin() + private function configureViewForGetMobileVsDesktop(ViewDataTable $view) { - return array_merge($this->getBasicUserSettingsDisplayProperties(), array( - 'translations' => array( - 'label' => Piwik::translate('General_Plugin'), - 'nb_visits_percentage' => - str_replace(' ', ' ', Piwik::translate('General_ColumnPercentageVisits')) - ), - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'show_all_views_icons' => false, - 'show_table_all_columns' => false, - 'columns_to_display' => array('label', 'nb_visits_percentage', 'nb_visits'), - 'filter_sort_column' => 'nb_visits_percentage', - 'filter_sort_order' => 'desc', - 'filter_limit' => 10, - 'show_footer_message' => Piwik::translate('UserSettings_PluginDetectionDoesNotWorkInIE'), - )); + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->title = Piwik::translate('UserSettings_MobileVsDesktop'); + $view->config->addTranslation('label', Piwik::translate('UserSettings_MobileVsDesktop')); + $view->config->addRelatedReports($this->getWideScreenDeviceTypeRelatedReports()); } - private function getDisplayPropertiesForGetLanguage() + private function configureViewForGetPlugin(ViewDataTable $view) { - return array( - 'translations' => array('label' => Piwik::translate('General_Language')), - 'filter_sort_column' => 'nb_visits', - 'filter_sort_order' => 'desc', - 'show_search' => false, - 'columns_to_display' => array('label', 'nb_visits'), - 'show_exclude_low_population' => false, - ); + $this->getBasicUserSettingsDisplayProperties($view); + + $view->config->addTranslations(array( + 'label' => Piwik::translate('General_Plugin'), + 'nb_visits_percentage' => + str_replace(' ', ' ', Piwik::translate('General_ColumnPercentageVisits')) + )); + + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_limit_control = false; + $view->config->show_all_views_icons = false; + $view->config->show_table_all_columns = false; + $view->config->columns_to_display = array('label', 'nb_visits_percentage', 'nb_visits'); + $view->config->show_footer_message = Piwik::translate('UserSettings_PluginDetectionDoesNotWorkInIE'); + + $view->requestConfig->filter_sort_column = 'nb_visits_percentage'; + $view->requestConfig->filter_sort_order = 'desc'; + $view->requestConfig->filter_limit = 10; + } + + private function configureViewForGetLanguage(ViewDataTable $view) + { + $view->config->show_search = false; + $view->config->columns_to_display = array('label', 'nb_visits'); + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('General_Language')); + + $view->requestConfig->filter_sort_column = 'nb_visits'; + $view->requestConfig->filter_sort_order = 'desc'; } private function getWideScreenDeviceTypeRelatedReports() @@ -335,18 +374,16 @@ class UserSettings extends \Piwik\Plugin ); } - private function getBasicUserSettingsDisplayProperties() + private function getBasicUserSettingsDisplayProperties(ViewDataTable $view) { - return array( - 'show_search' => false, - 'show_exclude_low_population' => false, - 'filter_limit' => 5, - 'visualization_properties' => array( - 'graph' => array( - 'max_graph_elements' => 5 - ) - ) - ); + $view->config->show_search = false; + $view->config->show_exclude_low_population = false; + + $view->requestConfig->filter_limit = 5; + + if ($view->isViewDataTableId(Graph::ID)) { + $view->config->max_graph_elements = 5; + } } /** diff --git a/plugins/VisitTime/VisitTime.php b/plugins/VisitTime/VisitTime.php index 62c3f6fc9f7cbb2623e9cc0125824ab0ebd38053..0f4ad71b28e725709584d4859e9b4c9c045e9857 100644 --- a/plugins/VisitTime/VisitTime.php +++ b/plugins/VisitTime/VisitTime.php @@ -17,6 +17,9 @@ use Piwik\Common; use Piwik\Menu\MenuMain; use Piwik\Period; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; +use Piwik\Plugins\CoreVisualizations\Visualizations\Graph; +use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Bar; use Piwik\Site; use Piwik\WidgetsList; @@ -32,14 +35,15 @@ class VisitTime extends \Piwik\Plugin public function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'WidgetsList.addWidgets' => 'addWidgets', - 'Menu.Reporting.addItems' => 'addMenu', - 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', - 'API.getReportMetadata' => 'getReportMetadata', - 'API.getSegmentsMetadata' => 'getSegmentsMetadata', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'WidgetsList.addWidgets' => 'addWidgets', + 'Menu.Reporting.addItems' => 'addMenu', + 'Goals.getReportsWithGoalMetrics' => 'getReportsWithGoalMetrics', + 'API.getReportMetadata' => 'getReportMetadata', + 'API.getSegmentsMetadata' => 'getSegmentsMetadata', + 'ViewDataTable.configure' => 'configureViewDataTable', + 'Visualization.getDefaultViewTypeForReports' => 'getDefaultViewTypeForReports' ); return $hooks; } @@ -122,61 +126,73 @@ class VisitTime extends \Piwik\Plugin ); } - public function getReportDisplayProperties(&$properties) + public function getDefaultViewTypeForReports(&$defaultViewTypes) { - $commonProperties = array( - 'filter_sort_column' => 'label', - 'filter_sort_order' => 'asc', - 'show_search' => false, - 'show_exclude_low_population' => false, - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'default_view_type' => 'graphVerticalBar' - ); + $defaultViewTypes['VisitTime.getVisitInformationPerServerTime'] = Bar::ID; + $defaultViewTypes['VisitTime.getVisitInformationPerLocalTime'] = Bar::ID; + $defaultViewTypes['VisitTime.getByDayOfWeek'] = Bar::ID; + } + + public function configureViewDataTable(ViewDataTable $view) + { + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'VisitTime.getVisitInformationPerServerTime': + $this->setBasicConfigViewProperties($view); + $this->configureViewForVisitInformationPerServerTime($view); + break; + case 'VisitTime.getVisitInformationPerLocalTime': + $this->setBasicConfigViewProperties($view); + $this->configureViewForVisitInformationPerLocalTime($view); + break; + case 'VisitTime.getByDayOfWeek': + $this->setBasicConfigViewProperties($view); + $this->configureViewForByDayOfWeek($view); + break; + } + } + + protected function configureViewForVisitInformationPerServerTime(ViewDataTable $view) + { + $view->requestConfig->filter_limit = 24; + $view->requestConfig->request_parameters_to_modify['hideFutureHoursWhenToday'] = 1; + + $view->config->show_goals = true; + $view->config->addTranslation('label', Piwik::translate('VisitTime_ColumnServerTime')); + + if ($view->isViewDataTableId(Graph::ID)) { + $view->config->max_graph_elements = false; + } + } + + protected function configureViewForVisitInformationPerLocalTime(ViewDataTable $view) + { + $view->requestConfig->filter_limit = 24; - $properties['VisitTime.getVisitInformationPerServerTime'] = array_merge($commonProperties, array( - 'filter_limit' => 24, - 'show_goals' => true, - 'translations' => array('label' => Piwik::translate('VisitTime_ColumnServerTime')), - 'request_parameters_to_modify' => array('hideFutureHoursWhenToday' => 1), - 'visualization_properties' => array( - 'graph' => array( - 'max_graph_elements' => false, - ) - ) - )); - - $properties['VisitTime.getVisitInformationPerLocalTime'] = array_merge($commonProperties, array( - 'filter_limit' => 24, - 'title' => Piwik::translate('VisitTime_ColumnLocalTime'), - 'translations' => array('label' => Piwik::translate('VisitTime_LocalTime')), - 'visualization_properties' => array( - 'graph' => array( - 'max_graph_elements' => false, - ) - ) - )); - - $properties['VisitTime.getByDayOfWeek'] = array_merge($commonProperties, array( - 'filter_limit' => 7, - 'enable_sort' => false, - 'show_footer_message' => - Piwik::translate('General_ReportGeneratedFrom', self::getDateRangeForFooterMessage()), - 'translations' => array('label' => Piwik::translate('VisitTime_DayOfWeek')), - 'visualization_properties' => array( - 'graph' => array( - 'show_all_ticks' => true, - 'max_graph_elements' => false, - ) - ) - )); + $view->config->title = Piwik::translate('VisitTime_ColumnLocalTime'); + $view->config->addTranslation('label', Piwik::translate('VisitTime_LocalTime')); + + if ($view->isViewDataTableId(Graph::ID)) { + $view->config->max_graph_elements = false; + } // add the visits by day of week as a related report, if the current period is not 'day' if (Common::getRequestVar('period', 'day') != 'day') { - $properties['VisitTime.getVisitInformationPerLocalTime']['related_reports'] = array( - 'VisitTime.getByDayOfWeek' => Piwik::translate('VisitTime_VisitsByDayOfWeek') - ); + $view->config->addRelatedReport('VisitTime.getByDayOfWeek', Piwik::translate('VisitTime_VisitsByDayOfWeek')); + } + + } + + protected function configureViewForByDayOfWeek(ViewDataTable $view) + { + $view->requestConfig->filter_limit = 7; + + $view->config->enable_sort = false; + $view->config->show_footer_message = Piwik::translate('General_ReportGeneratedFrom', self::getDateRangeForFooterMessage()); + $view->config->addTranslation('label', Piwik::translate('VisitTime_DayOfWeek')); + + if ($view->isViewDataTableId(Graph::ID)) { + $view->config->max_graph_elements = false; + $view->config->show_all_ticks = true; } } @@ -220,4 +236,18 @@ class VisitTime extends \Piwik\Plugin } return $dateRange; } + + /** + * @param ViewDataTable $view + */ + private function setBasicConfigViewProperties(ViewDataTable $view) + { + $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'asc'; + $view->config->show_search = false; + $view->config->show_limit_control = false; + $view->config->show_exclude_low_population = false; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + } } \ No newline at end of file diff --git a/plugins/VisitorGenerator b/plugins/VisitorGenerator index 1634842ace2842e54f95a91e71c078bc10e32673..924b69d524edea4a326216fe6de7a8df7e9a9ddc 160000 --- a/plugins/VisitorGenerator +++ b/plugins/VisitorGenerator @@ -1 +1 @@ -Subproject commit 1634842ace2842e54f95a91e71c078bc10e32673 +Subproject commit 924b69d524edea4a326216fe6de7a8df7e9a9ddc diff --git a/plugins/VisitorInterest/VisitorInterest.php b/plugins/VisitorInterest/VisitorInterest.php index 4225f5cfc3d34d81f5f14522069a5c6feb8ef822..ccfe90c03a3894d3430e94f9df405f1dddcb8080 100644 --- a/plugins/VisitorInterest/VisitorInterest.php +++ b/plugins/VisitorInterest/VisitorInterest.php @@ -16,6 +16,9 @@ use Piwik\FrontController; use Piwik\Menu\MenuMain; use Piwik\Metrics; use Piwik\Piwik; +use Piwik\Plugin\ViewDataTable; +use Piwik\Plugins\CoreVisualizations\Visualizations\Cloud; +use Piwik\Plugins\CoreVisualizations\Visualizations\Graph; use Piwik\WidgetsList; /** @@ -30,12 +33,13 @@ class VisitorInterest extends \Piwik\Plugin public function getListHooksRegistered() { $hooks = array( - 'ArchiveProcessor.Day.compute' => 'archiveDay', - 'ArchiveProcessor.Period.compute' => 'archivePeriod', - 'WidgetsList.addWidgets' => 'addWidgets', - 'Menu.Reporting.addItems' => 'addMenu', - 'API.getReportMetadata' => 'getReportMetadata', - 'Visualization.getReportDisplayProperties' => 'getReportDisplayProperties', + 'ArchiveProcessor.Day.compute' => 'archiveDay', + 'ArchiveProcessor.Period.compute' => 'archivePeriod', + 'WidgetsList.addWidgets' => 'addWidgets', + 'Menu.Reporting.addItems' => 'addMenu', + 'API.getReportMetadata' => 'getReportMetadata', + 'ViewDataTable.configure' => 'configureViewDataTable', + 'Visualization.getDefaultViewTypeForReports' => 'getDefaultViewTypeForReports' ); return $hooks; } @@ -151,97 +155,105 @@ class VisitorInterest extends \Piwik\Plugin $out .= '</div>'; } - public function getReportDisplayProperties(&$properties) + public function getDefaultViewTypeForReports(&$defaultViewTypes) { - $properties['VisitorInterest.getNumberOfVisitsPerVisitDuration'] = - $this->getDisplayPropertiesForGetNumberOfVisitsPerVisitDuration(); - $properties['VisitorInterest.getNumberOfVisitsPerPage'] = - $this->getDisplayPropertiesForGetNumberOfVisitsPerPage(); - $properties['VisitorInterest.getNumberOfVisitsByVisitCount'] = - $this->getDisplayPropertiesForGetNumberOfVisitsByVisitCount(); - $properties['VisitorInterest.getNumberOfVisitsByDaysSinceLast'] = - $this->getDisplayPropertiesForGetNumberOfVisitsByDaysSinceLast(); + $defaultViewTypes['VisitorInterest.getNumberOfVisitsPerVisitDuration'] = Cloud::ID; + $defaultViewTypes['VisitorInterest.getNumberOfVisitsPerPage'] = Cloud::ID; } - private function getDisplayPropertiesForGetNumberOfVisitsPerVisitDuration() + public function configureViewDataTable(ViewDataTable $view) { - return array( - 'default_view_type' => 'cloud', - 'filter_sort_column' => 'label', - 'filter_sort_order' => 'asc', - 'translations' => array('label' => Piwik::translate('VisitorInterest_ColumnVisitDuration')), - 'enable_sort' => false, - 'show_exclude_low_population' => false, - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'show_search' => false, - 'show_table_all_columns' => false, - 'visualization_properties' => array( - 'graph' => array( - 'max_graph_elements' => 10 - ) - ) - ); + switch ($view->requestConfig->apiMethodToRequestDataTable) { + case 'VisitorInterest.getNumberOfVisitsPerVisitDuration': + $this->configureViewForGetNumberOfVisitsPerVisitDuration($view); + break; + case 'VisitorInterest.getNumberOfVisitsPerPage': + $this->configureViewForGetNumberOfVisitsPerPage($view); + break; + case 'VisitorInterest.getNumberOfVisitsByVisitCount': + $this->configureViewForGetNumberOfVisitsByVisitCount($view); + break; + case 'VisitorInterest.getNumberOfVisitsByDaysSinceLast': + $this->configureViewForGetNumberOfVisitsByDaysSinceLast($view); + break; + } } - private function getDisplayPropertiesForGetNumberOfVisitsPerPage() + private function configureViewForGetNumberOfVisitsPerVisitDuration(ViewDataTable $view) { - return array( - 'default_view_type' => 'cloud', - 'filter_sort_column' => 'label', - 'filter_sort_order' => 'asc', - 'translations' => array('label' => Piwik::translate('VisitorInterest_ColumnPagesPerVisit')), - 'enable_sort' => false, - 'show_exclude_low_population' => false, - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'show_search' => false, - 'show_table_all_columns' => false, - 'visualization_properties' => array( - 'graph' => array( - 'max_graph_elements' => 10 - ) - ) - ); + $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'asc'; + + $view->config->addTranslation('label', Piwik::translate('VisitorInterest_ColumnVisitDuration')); + $view->config->enable_sort = false; + $view->config->show_exclude_low_population = false; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_limit_control = false; + $view->config->show_search = false; + $view->config->show_table_all_columns = false; + + if ($view->isViewDataTableId(Graph::ID)) { + $view->config->max_graph_elements = 10; + } } - private function getDisplayPropertiesForGetNumberOfVisitsByVisitCount() + private function configureViewForGetNumberOfVisitsPerPage(ViewDataTable $view) { - return array( - 'columns_to_display' => array('label', 'nb_visits', 'nb_visits_percentage'), - 'filter_sort_column' => 'label', - 'filter_sort_order' => 'asc', - 'translations' => array('label' => Piwik::translate('VisitorInterest_VisitNum'), - 'nb_visits_percentage' => Metrics::getPercentVisitColumn()), - 'show_exclude_low_population' => false, - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'filter_limit' => 15, - 'show_search' => false, - 'enable_sort' => false, - 'show_table_all_columns' => false, - 'show_all_views_icons' => false, - ); + $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'asc'; + + $view->config->addTranslation('label', Piwik::translate('VisitorInterest_ColumnVisitDuration')); + $view->config->enable_sort = false; + $view->config->show_exclude_low_population = false; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_limit_control = false; + $view->config->show_search = false; + $view->config->show_table_all_columns = false; + + if ($view->isViewDataTableId(Graph::ID)) { + $view->config->max_graph_elements = 10; + } } - private function getDisplayPropertiesForGetNumberOfVisitsByDaysSinceLast() + private function configureViewForGetNumberOfVisitsByVisitCount(ViewDataTable $view) { - return array( - 'filter_sort_column' => 'label', - 'filter_sort_order' => 'asc', - 'translations' => array('label' => Piwik::translate('General_DaysSinceLastVisit')), - 'show_exclude_low_population' => false, - 'show_offset_information' => false, - 'show_pagination_control' => false, - 'show_limit_control' => false, - 'show_all_views_icons' => false, - 'filter_limit' => 15, - 'show_search' => false, - 'enable_sort' => false, - 'show_table_all_columns' => false + $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'asc'; + $view->requestConfig->filter_limit = 15; + + $view->config->addTranslations(array( + 'label' => Piwik::translate('VisitorInterest_VisitNum'), + 'nb_visits_percentage' => Metrics::getPercentVisitColumn()) ); + + $view->config->columns_to_display = array('label', 'nb_visits', 'nb_visits_percentage'); + $view->config->show_exclude_low_population = false; + + $view->config->enable_sort = false; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_limit_control = false; + $view->config->show_search = false; + $view->config->show_table_all_columns = false; + $view->config->show_all_views_icons = false; + } + + private function configureViewForGetNumberOfVisitsByDaysSinceLast(ViewDataTable $view) + { + $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'asc'; + $view->requestConfig->filter_limit = 15; + + $view->config->show_search = false; + $view->config->enable_sort = false; + $view->config->show_offset_information = false; + $view->config->show_pagination_control = false; + $view->config->show_limit_control = false; + $view->config->show_all_views_icons = false; + $view->config->show_table_all_columns = false; + $view->config->show_exclude_low_population = false; + $view->config->addTranslation('label', Piwik::translate('General_DaysSinceLastVisit')); } } \ No newline at end of file diff --git a/plugins/VisitsSummary/Controller.php b/plugins/VisitsSummary/Controller.php index ca9aaa7df985005eacd14b4972bd2dc64212f669..27c249f7a909cc955421172af62c2af0078607e8 100644 --- a/plugins/VisitsSummary/Controller.php +++ b/plugins/VisitsSummary/Controller.php @@ -91,6 +91,7 @@ class Controller extends \Piwik\Plugin\Controller $selectableColumns[] = 'nb_searches'; $selectableColumns[] = 'nb_keywords'; } + $view = $this->getLastUnitGraphAcrossPlugins($this->pluginName, __FUNCTION__, $columns, $selectableColumns, $documentation); diff --git a/tests/PHPUnit/UI b/tests/PHPUnit/UI index f54bb82611655eb8dd9deff89c32b37f5846793b..a4c99cd1676bb7fea4fb1fb11997c08449bb7cfa 160000 --- a/tests/PHPUnit/UI +++ b/tests/PHPUnit/UI @@ -1 +1 @@ -Subproject commit f54bb82611655eb8dd9deff89c32b37f5846793b +Subproject commit a4c99cd1676bb7fea4fb1fb11997c08449bb7cfa