diff --git a/core/API/DataTableManipulator/LabelFilter.php b/core/API/DataTableManipulator/LabelFilter.php index cd8300991bfbb875ebb71747281450d17838fb59..0d4e11772ac9c0d1b0128925a569584a39ca3b41 100644 --- a/core/API/DataTableManipulator/LabelFilter.php +++ b/core/API/DataTableManipulator/LabelFilter.php @@ -147,6 +147,8 @@ class LabelFilter extends DataTableManipulator } $variations[] = $label; + $variations = array_unique($variations); + return $variations; } diff --git a/core/API/DataTablePostProcessor.php b/core/API/DataTablePostProcessor.php index b13fff14395c30c74dc28b297b97f8046b5c1ff0..dfa0434da6fa2f7812d17589711a5cb94ed75b9f 100644 --- a/core/API/DataTablePostProcessor.php +++ b/core/API/DataTablePostProcessor.php @@ -59,6 +59,9 @@ class DataTablePostProcessor */ private $formatter; + private $callbackBeforeGenericFilters; + private $callbackAfterGenericFilters; + /** * Constructor. */ @@ -66,11 +69,31 @@ class DataTablePostProcessor { $this->apiModule = $apiModule; $this->apiMethod = $apiMethod; - $this->request = $request; + $this->setRequest($request); $this->report = Report::factory($apiModule, $apiMethod); $this->apiInconsistencies = new Inconsistencies(); - $this->formatter = new Formatter(); + $this->setFormatter(new Formatter()); + } + + public function setFormatter(Formatter $formatter) + { + $this->formatter = $formatter; + } + + public function setRequest($request) + { + $this->request = $request; + } + + public function setCallbackBeforeGenericFilters($callbackBeforeGenericFilters) + { + $this->callbackBeforeGenericFilters = $callbackBeforeGenericFilters; + } + + public function setCallbackAfterGenericFilters($callbackAfterGenericFilters) + { + $this->callbackAfterGenericFilters = $callbackAfterGenericFilters; } /** @@ -88,19 +111,24 @@ class DataTablePostProcessor $dataTable = $this->applyTotalsCalculator($dataTable); $dataTable = $this->applyFlattener($dataTable); - $dataTable = $this->applyGenericFilters($dataTable); + if ($this->callbackBeforeGenericFilters) { + call_user_func($this->callbackBeforeGenericFilters, $dataTable); + } + $dataTable = $this->applyGenericFilters($dataTable); $this->applyComputeProcessedMetrics($dataTable); + if ($this->callbackAfterGenericFilters) { + call_user_func($this->callbackAfterGenericFilters, $dataTable); + } + // we automatically safe decode all datatable labels (against xss) $dataTable->queueFilter('SafeDecodeLabel'); - $dataTable = $this->convertSegmentValueToSegment($dataTable); $dataTable = $this->applyQueuedFilters($dataTable); $dataTable = $this->applyRequestedColumnDeletion($dataTable); $dataTable = $this->applyLabelFilter($dataTable); $dataTable = $this->applyMetricsFormatting($dataTable); - return $dataTable; } diff --git a/core/API/Proxy.php b/core/API/Proxy.php index 0345693b62a35ef2049a1d48c9cb50b56148139e..0f8667d0d87828278a327ee8ea463370f3d2eefe 100644 --- a/core/API/Proxy.php +++ b/core/API/Proxy.php @@ -490,7 +490,7 @@ class Proxy extends Singleton $hideLine = trim($hideLine); $hideLine .= ' '; - $token = trim(strtok($hideLine, " "), "\n"); + $token = trim(strtok($hideLine, " "), "\n"); $hide = false; @@ -528,18 +528,6 @@ class Proxy extends Singleton return true; } - /** - * Returns the number of required parameters (parameters without default values). - * - * @param string $class The class name - * @param string $name The method name - * @return int The number of required parameters - */ - private function getNumberOfRequiredParameters($class, $name) - { - return $this->metadataArray[$class][$name]['numberOfRequiredParameters']; - } - /** * Returns true if the method is found in the API of the given class name. * diff --git a/core/API/Request.php b/core/API/Request.php index 1db400960641c4570cdc2a5225b260ec6eb3d745..2ed5dfc56761ea13eae94c9638c1ead23a705995 100644 --- a/core/API/Request.php +++ b/core/API/Request.php @@ -18,6 +18,7 @@ use Piwik\SettingsServer; use Piwik\Url; use Piwik\UrlHelper; use Piwik\Log; +use Piwik\Plugin\Manager as PluginManager; /** * Dispatches API requests to the appropriate API method. @@ -219,10 +220,9 @@ class Request list($module, $method) = $this->extractModuleAndMethod($moduleMethod); list($module, $method) = self::getRenamedModuleAndAction($module, $method); + + PluginManager::getInstance()->checkIsPluginActivated($module); - if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated($module)) { - throw new PluginDeactivatedException($module); - } $apiClassName = self::getClassNameAPI($module); self::reloadAuthUsingTokenAuth($this->request); diff --git a/core/API/ResponseBuilder.php b/core/API/ResponseBuilder.php index 4ebe50305d1a429b41288e283882cef9ffbba2aa..68e448b0b4dc82030110e20410747cac0d6b4b2f 100644 --- a/core/API/ResponseBuilder.php +++ b/core/API/ResponseBuilder.php @@ -25,6 +25,7 @@ class ResponseBuilder private $apiRenderer = null; private $request = null; private $sendHeader = true; + private $postProcessDataTable = true; private $apiModule = false; private $apiMethod = false; @@ -45,6 +46,11 @@ class ResponseBuilder $this->sendHeader = false; } + public function disableDataTablePostProcessor() + { + $this->postProcessDataTable = false; + } + /** * This method processes the data resulting from the API call. * @@ -164,8 +170,10 @@ class ResponseBuilder private function handleDataTable(DataTableInterface $datatable) { - $postProcessor = new DataTablePostProcessor($this->apiModule, $this->apiMethod, $this->request); - $datatable = $postProcessor->process($datatable); + if ($this->postProcessDataTable) { + $postProcessor = new DataTablePostProcessor($this->apiModule, $this->apiMethod, $this->request); + $datatable = $postProcessor->process($datatable); + } return $this->apiRenderer->renderDataTable($datatable); } diff --git a/core/DataTable/Filter/PivotByDimension.php b/core/DataTable/Filter/PivotByDimension.php index 61e68423e8da3b1b8da027e1d3f18cacb704d805..3eeff39b44e2fe241debc8bab46400908158eb22 100644 --- a/core/DataTable/Filter/PivotByDimension.php +++ b/core/DataTable/Filter/PivotByDimension.php @@ -286,13 +286,12 @@ class PivotByDimension extends BaseFilter return null; } - if ($row->isSubtableLoaded()) { - $subtable = $row->getSubtable(); - } else { + $subtable = $row->getSubtable(); + if (!$subtable) { $subtable = $this->thisReport->fetchSubtable($idSubtable, $this->getRequestParamOverride($table)); } - if ($subtable === null) { // sanity check + if (!$subtable) { // sanity check throw new Exception("Unexpected error: could not load subtable '$idSubtable'."); } diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index 6e0d5ba91a36ea72281e41db6d15db0a0ef20cdb..fb11f0a6640e0fb5357abc403ec34a72b37c28dd 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -21,6 +21,7 @@ use Piwik\Log; use Piwik\Option; use Piwik\Piwik; use Piwik\Plugin; +use Piwik\PluginDeactivatedException; use Piwik\Singleton; use Piwik\Theme; use Piwik\Tracker; @@ -265,6 +266,19 @@ class Manager extends Singleton || ($this->doLoadAlwaysActivatedPlugins && $this->isPluginAlwaysActivated($name)); } + /** + * Checks whether the given plugin is activated, if not triggers an exception. + * + * @param string $pluginName + * @throws PluginDeactivatedException + */ + public function checkIsPluginActivated($pluginName) + { + if (!$this->isPluginActivated($pluginName)) { + throw new PluginDeactivatedException($pluginName); + } + } + /** * Returns `true` if plugin is loaded (in memory). * diff --git a/core/Plugin/Metric.php b/core/Plugin/Metric.php index 6d69350d92b963dfa77874918544df55cb8abba3..4122dfeedf83827652576fe37989e87d2706554c 100644 --- a/core/Plugin/Metric.php +++ b/core/Plugin/Metric.php @@ -124,10 +124,11 @@ abstract class Metric return $value; - } else { - $value = null; + } elseif (!empty($row)) { + if (array_key_exists($columnName, $row)) { - $value = $row[$columnName]; + return $row[$columnName]; + } else { if (empty($mappingNameToId)) { @@ -142,10 +143,9 @@ abstract class Metric } } } - } - return $value; + return null; } /** diff --git a/core/Plugin/ViewDataTable.php b/core/Plugin/ViewDataTable.php index 4f3b854127f2fac99547933a45dad33a87cb265a..a49358e48b27f9d7344ae45a44b834c1b60bd296 100644 --- a/core/Plugin/ViewDataTable.php +++ b/core/Plugin/ViewDataTable.php @@ -316,7 +316,7 @@ abstract class ViewDataTable implements ViewInterface return new VizRequest(); } - protected function loadDataTableFromAPI($fixedRequestParams = array()) + protected function loadDataTableFromAPI() { if (!is_null($this->dataTable)) { // data table is already there @@ -324,7 +324,7 @@ abstract class ViewDataTable implements ViewInterface return $this->dataTable; } - $this->dataTable = $this->request->loadDataTableFromAPI($fixedRequestParams); + $this->dataTable = $this->request->loadDataTableFromAPI(); return $this->dataTable; } diff --git a/core/Plugin/Visualization.php b/core/Plugin/Visualization.php index 15b468e362136953d822a89aeb929e5fab5c4bbf..3d48c24d15d3e9976500407cd82e0e1af3c4879f 100644 --- a/core/Plugin/Visualization.php +++ b/core/Plugin/Visualization.php @@ -10,6 +10,8 @@ namespace Piwik\Plugin; use Piwik\API\DataTablePostProcessor; +use Piwik\API\Proxy; +use Piwik\API\ResponseBuilder; use Piwik\Common; use Piwik\DataTable; use Piwik\Date; @@ -23,6 +25,8 @@ use Piwik\Plugins\API\API as ApiApi; use Piwik\Plugins\PrivacyManager\PrivacyManager; use Piwik\View; use Piwik\ViewDataTable\Manager as ViewDataTableManager; +use Piwik\Plugin\Manager as PluginManager; +use Piwik\API\Request as ApiRequest; /** * The base class for report visualizations that output HTML and use JavaScript. @@ -173,8 +177,7 @@ class Visualization extends ViewDataTable try { $this->beforeLoadDataTable(); - - $this->loadDataTableFromAPI(array('disable_generic_filters' => 1, 'format_metrics' => 0)); + $this->loadDataTableFromAPI(); $this->postDataTableLoadedFromAPI(); $requestPropertiesAfterLoadDataTable = $this->requestConfig->getProperties(); @@ -233,6 +236,35 @@ class Visualization extends ViewDataTable return $view; } + /** + * @internal + */ + protected function loadDataTableFromAPI() + { + if (!is_null($this->dataTable)) { + // data table is already there + // this happens when setDataTable has been used + return $this->dataTable; + } + + // we build the request (URL) to call the API + $request = $this->buildApiRequestArray(); + + $module = $this->requestConfig->getApiModuleToRequest(); + $method = $this->requestConfig->getApiMethodToRequest(); + + PluginManager::getInstance()->checkIsPluginActivated($module); + + $class = ApiRequest::getClassNameAPI($module); + $dataTable = Proxy::getInstance()->call($class, $method, $request); + + $response = new ResponseBuilder($format = 'original', $request); + $response->disableSendHeader(); + $response->disableDataTablePostProcessor(); + + $this->dataTable = $response->getResponse($dataTable, $module, $method); + } + private function getReportMetadata() { $request = $this->request->getRequestArray() + $_GET + $_POST; @@ -255,11 +287,16 @@ class Visualization extends ViewDataTable $this->config->footer_icons = ViewDataTableManager::configureFooterIcons($this); } - if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated('Goals')) { + if (!$this->isPluginActivated('Goals')) { $this->config->show_goals = false; } } + private function isPluginActivated($pluginName) + { + return PluginManager::getInstance()->isPluginActivated($pluginName); + } + /** * Assigns a template variable making it available in the Twig template specified by * {@link TEMPLATE_FILE}. @@ -357,48 +394,39 @@ class Visualization extends ViewDataTable private function applyFilters() { - list($priorityFilters, $otherFilters) = $this->config->getFiltersToRun(); + $postProcessor = $this->makeDataTablePostProcessor(); // must be created after requestConfig is final + $self = $this; - // First, filters that delete rows - foreach ($priorityFilters as $filter) { - $this->dataTable->filter($filter[0], $filter[1]); - } + $postProcessor->setCallbackBeforeGenericFilters(function (DataTable\DataTableInterface $dataTable) use ($self, $postProcessor) { - $this->beforeGenericFiltersAreAppliedToLoadedDataTable(); + // First, filters that delete rows + foreach ($self->config->getPriorityFilters() as $filter) { + $dataTable->filter($filter[0], $filter[1]); + } - if (!in_array($this->requestConfig->filter_sort_column, $this->config->columns_to_display)) { - $hasNbUniqVisitors = in_array('nb_uniq_visitors', $this->config->columns_to_display); - $this->requestConfig->setDefaultSort($this->config->columns_to_display, $hasNbUniqVisitors, $this->dataTable->getColumns()); - } + $self->beforeGenericFiltersAreAppliedToLoadedDataTable(); - $postProcessor = $this->makeDataTablePostProcessor(); // must be created after requestConfig is final + if (!in_array($self->requestConfig->filter_sort_column, $self->config->columns_to_display)) { + $hasNbUniqVisitors = in_array('nb_uniq_visitors', $self->config->columns_to_display); + $columns = $dataTable->getColumns(); + $self->requestConfig->setDefaultSort($self->config->columns_to_display, $hasNbUniqVisitors, $columns); + } - if (!$this->requestConfig->areGenericFiltersDisabled()) { - $this->dataTable = $postProcessor->applyGenericFilters($this->dataTable); - } + $postProcessor->setRequest($self->buildApiRequestArray()); + }); - $postProcessor->applyComputeProcessedMetrics($this->dataTable); + $postProcessor->setCallbackAfterGenericFilters(function (DataTable\DataTableInterface $dataTable) use ($self) { - $this->afterGenericFiltersAreAppliedToLoadedDataTable(); + $self->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]); - } + // queue other filters so they can be applied later if queued filters are disabled + foreach ($self->config->getPresentationFilters() as $filter) { + $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->requestConfig->areQueuedFiltersDisabled()) { - $this->dataTable->applyQueuedFilters(); - } + }); - if ($this->requestConfig->shouldFormatMetrics()) { - $formatter = $this->metricsFormatter; - $report = $this->report; - $this->dataTable->filter(function (DataTable $table) use ($formatter, $report) { - $formatter->formatMetrics($table, $report); - }); - } + $this->dataTable = $postProcessor->process($this->dataTable); } private function removeEmptyColumnsFromDisplay() @@ -456,7 +484,7 @@ class Visualization extends ViewDataTable */ private function hasReportBeenPurged() { - if (!\Piwik\Plugin\Manager::getInstance()->isPluginActivated('PrivacyManager')) { + if (!$this->isPluginActivated('PrivacyManager')) { return false; } @@ -629,15 +657,14 @@ class Visualization extends ViewDataTable private function makeDataTablePostProcessor() { - $requestArray = $this->request->getRequestArray(); - $request = \Piwik\API\Request::getRequestArrayFromString($requestArray); + $request = $this->buildApiRequestArray(); + $module = $this->requestConfig->getApiModuleToRequest(); + $method = $this->requestConfig->getApiMethodToRequest(); - if (false === $this->config->enable_sort) { - $request['filter_sort_column'] = ''; - $request['filter_sort_order'] = ''; - } + $processor = new DataTablePostProcessor($module, $method, $request); + $processor->setFormatter($this->metricsFormatter); - return new DataTablePostProcessor($this->requestConfig->getApiModuleToRequest(), $this->requestConfig->getApiMethodToRequest(), $request); + return $processor; } private function logMessageIfRequestPropertiesHaveChanged(array $requestPropertiesBefore) @@ -685,4 +712,30 @@ class Visualization extends ViewDataTable return $result; } + + /** + * @internal + * + * @return array + */ + public function buildApiRequestArray() + { + $requestArray = $this->request->getRequestArray(); + $request = APIRequest::getRequestArrayFromString($requestArray); + + if (false === $this->config->enable_sort) { + $request['filter_sort_column'] = ''; + $request['filter_sort_order'] = ''; + } + + if (!array_key_exists('format_metrics', $request) || $request['format_metrics'] === 'bc') { + $request['format_metrics'] = '1'; + } + + if (!$this->requestConfig->disable_queued_filters && array_key_exists('disable_queued_filters', $request)) { + unset($request['disable_queued_filters']); + } + + return $request; + } } diff --git a/core/ViewDataTable/Config.php b/core/ViewDataTable/Config.php index 220a253518c15f7554a1e8e8c1f5e2feeabe4219..f4eef3c639a03e7182de699cf7fdc26fba2b1177 100644 --- a/core/ViewDataTable/Config.php +++ b/core/ViewDataTable/Config.php @@ -557,7 +557,7 @@ class Config /** * @ignore */ - public function getFiltersToRun() + private function getFiltersToRun() { $priorityFilters = array(); $presentationFilters = array(); @@ -581,6 +581,20 @@ class Config return array($priorityFilters, $presentationFilters); } + public function getPriorityFilters() + { + $filters = $this->getFiltersToRun(); + + return $filters[0]; + } + + public function getPresentationFilters() + { + $filters = $this->getFiltersToRun(); + + return $filters[1]; + } + /** * Adds a related report to the {@link $related_reports} property. If the report * references the one that is currently being displayed, it will not be added to the related diff --git a/core/ViewDataTable/Request.php b/core/ViewDataTable/Request.php index 352ce25899cac6ef39eb10f8212e62cc4b825b0d..259d4caaa170550b0324c2510515ef05d3347e1e 100644 --- a/core/ViewDataTable/Request.php +++ b/core/ViewDataTable/Request.php @@ -32,15 +32,11 @@ class Request * 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($fixedRequestParams = array()) + public function loadDataTableFromAPI() { // we build the request (URL) to call the API $requestArray = $this->getRequestArray(); - foreach ($fixedRequestParams as $key => $value) { - $requestArray[$key] = $value; - } - // we make the request to the API $request = new ApiRequest($requestArray); @@ -104,6 +100,14 @@ class Request unset($requestArray['filter_limit']); } + if ($this->requestConfig->disable_generic_filters) { + $requestArray['disable_generic_filters'] = '0'; + } + + if ($this->requestConfig->disable_queued_filters) { + $requestArray['disable_queued_filters'] = 0; + } + return $requestArray; } diff --git a/core/ViewDataTable/RequestConfig.php b/core/ViewDataTable/RequestConfig.php index 753ee55b9893d836d5caf872ba3c9552fc84dd39..a6c9b7bed8085e2570e804f0452d0fa2954b046b 100644 --- a/core/ViewDataTable/RequestConfig.php +++ b/core/ViewDataTable/RequestConfig.php @@ -314,35 +314,6 @@ class RequestConfig $this->filter_sort_order = 'desc'; } - /** - * 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 getApiModuleToRequest() { list($module, $method) = explode('.', $this->apiMethodToRequestDataTable); @@ -356,9 +327,4 @@ class RequestConfig return $method; } - - public function shouldFormatMetrics() - { - return Common::getRequestVar('format_metrics', '1', 'string', $this->request_parameters_to_modify) != 0; - } } diff --git a/plugins/CoreHome/DataTableRowAction/RowEvolution.php b/plugins/CoreHome/DataTableRowAction/RowEvolution.php index e1bc8d5d4fae8aabae53815449f71bb1ebaf7629..85fa98bc3edbf64655eeefdae3b6b12b1d7687ab 100644 --- a/plugins/CoreHome/DataTableRowAction/RowEvolution.php +++ b/plugins/CoreHome/DataTableRowAction/RowEvolution.php @@ -198,6 +198,7 @@ class RowEvolution $view->config->columns_to_display = array_keys($metrics ? : $this->graphMetrics); } + $view->requestConfig->request_parameters_to_modify['label'] = ''; $view->config->show_goals = false; $view->config->show_search = false; $view->config->show_all_views_icons = false; diff --git a/plugins/CoreVisualizations/CoreVisualizations.php b/plugins/CoreVisualizations/CoreVisualizations.php index 54aa127c919d12bb7340c4953dde3b263697e2eb..97311475ace4a8f82508e5b03471d2fe6b59f9f9 100644 --- a/plugins/CoreVisualizations/CoreVisualizations.php +++ b/plugins/CoreVisualizations/CoreVisualizations.php @@ -9,6 +9,7 @@ namespace Piwik\Plugins\CoreVisualizations; +use Piwik\Common; use Piwik\ViewDataTable\Manager as ViewDataTableManager; require_once PIWIK_INCLUDE_PATH . '/plugins/CoreVisualizations/JqplotDataGenerator.php'; @@ -28,7 +29,8 @@ class CoreVisualizations extends \Piwik\Plugin 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', 'AssetManager.getJavaScriptFiles' => 'getJsFiles', 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', - 'UsersManager.deleteUser' => 'deleteUser' + 'UsersManager.deleteUser' => 'deleteUser', + 'ViewDataTable.addViewDataTable' => 'addViewDataTable' ); } @@ -37,6 +39,21 @@ class CoreVisualizations extends \Piwik\Plugin ViewDataTableManager::clearUserViewDataTableParameters($userLogin); } + public function addViewDataTable(&$viewDataTable) + { + if (Common::getRequestVar('pivotBy', '')) { + $tableToRemove = 'Visualizations\HtmlTable'; + } else { + $tableToRemove = 'HtmlTable\PivotBy'; + } + + foreach ($viewDataTable as $index => $table) { + if (Common::stringEndsWith($table, $tableToRemove)) { + unset($viewDataTable[$index]); + } + } + } + public function getStylesheetFiles(&$stylesheets) { $stylesheets[] = "plugins/CoreVisualizations/stylesheets/dataTableVisualizations.less"; diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable.php b/plugins/CoreVisualizations/Visualizations/HtmlTable.php index dcd2374df9062b3c54ee744447620df4321021e2..66cb4c26e96a4dd792b7d994c7148eb7511a657f 100644 --- a/plugins/CoreVisualizations/Visualizations/HtmlTable.php +++ b/plugins/CoreVisualizations/Visualizations/HtmlTable.php @@ -70,10 +70,6 @@ class HtmlTable extends Visualization $dataTable = $request->process(); $this->assignTemplateVar('siteSummary', $dataTable); } - - if ($this->requestConfig->pivotBy) { - $this->config->columns_to_display = $this->dataTable->getColumns(); - } } } diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable/PivotBy.php b/plugins/CoreVisualizations/Visualizations/HtmlTable/PivotBy.php new file mode 100644 index 0000000000000000000000000000000000000000..1703988599fe871475aebda5566c999c46c6b1d4 --- /dev/null +++ b/plugins/CoreVisualizations/Visualizations/HtmlTable/PivotBy.php @@ -0,0 +1,36 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; + +use Piwik\DataTable; +use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; +use Piwik\View; + +/** + * DataTable Visualization that derives from HtmlTable and sets show_extra_columns to true. + */ +class PivotBy extends HtmlTable +{ + public function beforeGenericFiltersAreAppliedToLoadedDataTable() + { + $this->config->columns_to_display = $this->dataTable->getColumns(); + + $this->dataTable->applyQueuedFilters(); + + parent::beforeGenericFiltersAreAppliedToLoadedDataTable(); + } + + public function beforeRender() + { + parent::beforeRender(); + + $this->config->columns_to_display = $this->dataTable->getColumns(); + } +} diff --git a/plugins/ExampleUI/Controller.php b/plugins/ExampleUI/Controller.php index 9bfd517aa0f9c73d0c4841f71bcdee0e05820a8b..210093c8b5758dbbd8f2a2cc4bfd5b18ea8c5035 100644 --- a/plugins/ExampleUI/Controller.php +++ b/plugins/ExampleUI/Controller.php @@ -90,6 +90,7 @@ class Controller extends \Piwik\Plugin\Controller $view = $this->getLastUnitGraphAcrossPlugins($this->pluginName, __FUNCTION__, $columns, $selectableColumns = array('server1', 'server2'), 'My documentation', 'ExampleUI.getTemperaturesEvolution'); $view->requestConfig->filter_sort_column = 'label'; + $view->requestConfig->filter_sort_order = 'asc'; if (empty($view->config->columns_to_display) && !empty($defaultColumns)) { $view->config->columns_to_display = $defaultColumns; diff --git a/plugins/Goals/Columns/Metrics/GoalSpecificProcessedMetric.php b/plugins/Goals/Columns/Metrics/GoalSpecificProcessedMetric.php index 1ae1c411491740fd441d2db1d1b6710b4a831561..d32290bfdc8387170bd9904cd057157a816a3c58 100644 --- a/plugins/Goals/Columns/Metrics/GoalSpecificProcessedMetric.php +++ b/plugins/Goals/Columns/Metrics/GoalSpecificProcessedMetric.php @@ -9,9 +9,11 @@ namespace Piwik\Plugins\Goals\Columns\Metrics; use Piwik\Common; use Piwik\DataTable\Row; +use Piwik\Metrics; use Piwik\Piwik; use Piwik\Plugin\ProcessedMetric; use Piwik\Plugins\Goals\API as GoalsAPI; +use Piwik\Tracker\GoalManager; /** * Base class for processed metrics that are calculated using metrics that are @@ -60,6 +62,16 @@ abstract class GoalSpecificProcessedMetric extends ProcessedMetric $alternateKey = 'idgoal=' . $this->idGoal; if (isset($allGoalMetrics[$alternateKey])) { return $allGoalMetrics[$alternateKey]; + } elseif ($this->idGoal === Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) { + $alternateKey = GoalManager::IDGOAL_ORDER; + if (isset($allGoalMetrics[$alternateKey])) { + return $allGoalMetrics[$alternateKey]; + } + } elseif ($this->idGoal === Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART) { + $alternateKey = GoalManager::IDGOAL_CART; + if (isset($allGoalMetrics[$alternateKey])) { + return $allGoalMetrics[$alternateKey]; + } } else { return array(); }