From 41fabcb3488f00f5840dc2c231519488322b1837 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Wed, 17 Sep 2014 20:40:38 -0700 Subject: Adding new PivotByDimension DataTable filter that can pivot a report by (almost) any dimension. The filter can pivot reports by their subtable dimension and can also pivot by other dimensions (by using segments). Notes: - in the UI, only pivoting by subtable is supported - change to CSV DataTable renderer so column names w/ commas & quotes can appear in text - change to XML DataTable renderer so column names w/ invalid XML characters can be rendered (bit of an iffy change, XML format needs an overhaul I think) - includes new config option 'pivot_by_filter_enable_fetch_by_segment' - includes additions to component metadata classes (ie, Report/Dimension) --- config/global.ini.php | 5 + core/API/DocumentationGenerator.php | 3 + core/API/ResponseBuilder.php | 14 +- core/Columns/Dimension.php | 21 +- core/DataTable.php | 8 + core/DataTable/Filter/PivotByDimension.php | 453 +++++++++++++++++++++ core/DataTable/Renderer/Csv.php | 15 + core/DataTable/Renderer/Xml.php | 65 ++- core/EventDispatcher.php | 6 +- core/Metrics.php | 1 + core/Plugin/ComponentFactory.php | 85 +++- core/Plugin/Report.php | 79 ++++ core/Plugin/Segment.php | 10 + core/ViewDataTable/Config.php | 34 +- plugins/CoreConsole/Commands/TestsSetupFixture.php | 3 +- plugins/CoreHome/CoreHome.php | 2 + plugins/CoreHome/javascripts/dataTable.js | 31 +- plugins/CoreHome/lang/en.json | 4 +- plugins/CoreHome/templates/_dataTableFooter.twig | 5 + tests/PHPUnit/Core/Columns/DimensionTest.php | 2 +- .../Core/DataTable/Filter/PivotByDimensionTest.php | 351 ++++++++++++++++ tests/PHPUnit/Core/DataTable/Renderer/CSVTest.php | 27 +- tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php | 54 +++ tests/PHPUnit/Core/Plugin/ComponentFactoryTest.php | 57 +++ tests/PHPUnit/Impl/TestRequestCollection.php | 1 - tests/PHPUnit/Integration/Core/ReportTest.php | 100 ++++- .../PHPUnit/Integration/PivotByQueryParamTest.php | 167 ++++++++ ...ithDataTableMaps__Referrers.getKeywords_day.xml | 49 +++ ...therQueryParams__Referrers.getKeywords_week.xml | 33 ++ ...hColumnLimiting__Referrers.getKeywords_week.xml | 33 ++ ...ksWithCsvOutput__Referrers.getKeywords_week.csv | Bin 0 -> 440 bytes ...WithJsonOutput__Referrers.getKeywords_week.json | 1 + ...oseSubtableIsSelf__Actions.getPageUrls_week.xml | 123 ++++++ ...rrectPivotTable__Referrers.getKeywords_week.xml | 39 ++ ...rchyIsNotLoaded__Referrers.getKeywords_week.xml | 57 +++ ...rrectPivotTable__Referrers.getKeywords_week.xml | 57 +++ tests/PHPUnit/IntegrationTestCase.php | 7 + 37 files changed, 1969 insertions(+), 33 deletions(-) create mode 100644 core/DataTable/Filter/PivotByDimension.php create mode 100644 tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php create mode 100644 tests/PHPUnit/Integration/PivotByQueryParamTest.php create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml diff --git a/config/global.ini.php b/config/global.ini.php index 43b0605b39..2ce4085ab3 100644 --- a/config/global.ini.php +++ b/config/global.ini.php @@ -472,6 +472,11 @@ enable_auto_update = 1 ; If set to 0 it also disables the "sent plugin update emails" feature in general and the related setting in the UI. enable_update_communication = 1 +; This controls whether the pivotBy query parameter can be used with any dimension or just subtable +; dimensions. If set to 1, it will fetch a report with a segment for each row of the table being pivoted. +; At present, this is very inefficient, so it is disabled by default. +pivot_by_filter_enable_fetch_by_segment = 0 + [Tracker] ; Piwik uses first party cookies by default. If set to 1, ; the visit ID cookie will be set on the Piwik server domain as well diff --git a/core/API/DocumentationGenerator.php b/core/API/DocumentationGenerator.php index 5e8b0d1e41..0662ff153e 100644 --- a/core/API/DocumentationGenerator.php +++ b/core/API/DocumentationGenerator.php @@ -190,6 +190,9 @@ class DocumentationGenerator $aParameters['hideColumns'] = false; $aParameters['showColumns'] = false; $aParameters['filter_pattern_recursive'] = false; + $aParameters['pivotBy'] = false; + $aParameters['pivotByColumn'] = false; + $aParameters['pivotByColumnLimit'] = false; $moduleName = Proxy::getInstance()->getModuleNameFromClassName($class); $aParameters = array_merge(array('module' => 'API', 'method' => $moduleName . '.' . $methodName), $aParameters); diff --git a/core/API/ResponseBuilder.php b/core/API/ResponseBuilder.php index f5af551917..17d5d488f7 100644 --- a/core/API/ResponseBuilder.php +++ b/core/API/ResponseBuilder.php @@ -14,6 +14,7 @@ use Piwik\API\DataTableManipulator\LabelFilter; use Piwik\API\DataTableManipulator\ReportTotalsCalculator; use Piwik\Common; use Piwik\DataTable; +use Piwik\DataTable\Filter\PivotByDimension; use Piwik\DataTable\Renderer; use Piwik\DataTable\DataTableInterface; use Piwik\DataTable\Filter\ColumnDelete; @@ -157,10 +158,21 @@ class ResponseBuilder return Renderer::formatValueXml($message); } - protected function handleDataTable($datatable) + protected function handleDataTable(DataTableInterface $datatable) { $label = $this->getLabelFromRequest($this->request); + // handle pivot by dimension filter + $pivotBy = Common::getRequestVar('pivotBy', false, 'string', $this->request); + if (!empty($pivotBy)) { + $reportId = $this->apiModule . '.' . $this->apiMethod; + $pivotByColumn = Common::getRequestVar('pivotByColumn', false, 'string', $this->request); + $pivotByColumnLimit = Common::getRequestVar('pivotByColumnLimit', false, 'int', $this->request); + + $datatable->filter('PivotByDimension', array($reportId, $pivotBy, $pivotByColumn, $pivotByColumnLimit, + PivotByDimension::isSegmentFetchingEnabledInConfig())); + } + // if requested, flatten nested tables if (Common::getRequestVar('flat', '0', 'string', $this->request) == '1') { $flattener = new Flattener($this->apiModule, $this->apiMethod, $this->request); diff --git a/core/Columns/Dimension.php b/core/Columns/Dimension.php index c2b39093e4..a6f8831a71 100644 --- a/core/Columns/Dimension.php +++ b/core/Columns/Dimension.php @@ -195,10 +195,29 @@ abstract class Dimension * @return Dimension|null The created instance or null if there is no Dimension for * $dimensionId or if the plugin that contains the Dimension is * not loaded. + * @api */ public static function factory($dimensionId) { list($module, $dimension) = explode('.', $dimensionId); return ComponentFactory::factory($module, $dimension, __CLASS__); } -} + + /** + * Returns the name of the plugin that contains this Dimension. + * + * @return string + * @throws Exception if the Dimension is not located within a Plugin module. + * @api + */ + public function getModule() + { + $id = $this->getId(); + if (empty($id)) { + throw new Exception("Invalid dimension ID: '$id'."); + } + + $parts = explode('.', $id); + return reset($parts); + } +} \ No newline at end of file diff --git a/core/DataTable.php b/core/DataTable.php index 3049dbf966..5895e51f2a 100644 --- a/core/DataTable.php +++ b/core/DataTable.php @@ -1634,6 +1634,14 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess $thisRow->sumRow($row, $copyMeta = true, $this->getMetadata(self::COLUMN_AGGREGATION_OPS_METADATA_NAME)); } + /** + * Unsets all queued filters. + */ + public function clearQueuedFilters() + { + $this->queuedFilters = array(); + } + /** * @return \ArrayIterator|Row[] */ diff --git a/core/DataTable/Filter/PivotByDimension.php b/core/DataTable/Filter/PivotByDimension.php new file mode 100644 index 0000000000..1d0a7267f8 --- /dev/null +++ b/core/DataTable/Filter/PivotByDimension.php @@ -0,0 +1,453 @@ +pivotColumn = $pivotColumn; + $this->pivotByColumnLimit = $pivotByColumnLimit ?: self::DEFAULT_COLUMN_LIMIT; + $this->isFetchingBySegmentEnabled = $isFetchingBySegmentEnabled; + + $namesToId = Metrics::getMappingFromIdToName(); + $this->metricIndexValue = isset($namesToId[$this->pivotColumn]) ? $namesToId[$this->pivotColumn] : null; + + $this->setPivotByDimension($pivotByDimension); + $this->setThisReportMetadata($report); + + $this->checkSupportedPivot(); + } + + /** + * Pivots to table. + * + * @param DataTable $table The table to manipulate. + */ + public function filter($table) + { + // set of all column names in the pivoted table mapped with the sum of all column + // values. used later in truncating and ordering the pivoted table's columns. + $columnSet = array(); + + // if no pivot column was set, use the first one found in the row + if (empty($this->pivotColumn)) { + $this->pivotColumn = $this->getNameOfFirstNonLabelColumnInTable($table); + } + + Log::debug("PivotByDimension::%s: pivoting table with pivot column = %s", __FUNCTION__, $this->pivotColumn); + + foreach ($table->getRows() as $row) { + $row->setColumns(array('label' => $row->getColumn('label'))); + + $associatedTable = $this->getIntersectedTable($table, $row); + if (!empty($associatedTable)) { + foreach ($associatedTable->getRows() as $columnRow) { + $pivotTableColumn = $columnRow->getColumn('label'); + + $columnValue = $this->getColumnValue($columnRow, $this->pivotColumn); + + if (isset($columnSet[$pivotTableColumn])) { + $columnSet[$pivotTableColumn] += $columnValue; + } else { + $columnSet[$pivotTableColumn] = $columnValue; + } + + $row->setColumn($pivotTableColumn, $columnValue); + } + + Common::destroy($associatedTable); + unset($associatedTable); + } + } + + Log::debug("PivotByDimension::%s: pivoted columns set: %s", __FUNCTION__, $columnSet); + + // limit columns + if ($this->pivotByColumnLimit > 0) { + arsort($columnSet); + $columnSet = array_slice($columnSet, 0, $this->pivotByColumnLimit, $preserveKeys = true); + } + + // sort columns by name (to ensure deterministic ordering) + ksort($columnSet); + + // remove column sums from array so it can be used as a default row + $columnSet = array_map(function () { return false; }, $columnSet); + + // make sure label column is first + $columnSet = array_merge(array('label' => false), $columnSet); + + Log::debug("PivotByDimension::%s: processed pivoted columns: %s", __FUNCTION__, $columnSet); + + // post process pivoted datatable + foreach ($table->getRows() as $row) { + // remove subtables from rows + $row->removeSubtable(); + $row->deleteMetadata('idsubdatatable_in_db'); + + // use default row to ensure column ordering and add missing columns + $orderedColumns = $columnSet; + foreach ($row->getColumns() as $name => $value) { + if (isset($orderedColumns[$name])) { + $orderedColumns[$name] = $value; + } + } + $row->setColumns($orderedColumns); + } + + $table->clearQueuedFilters(); // TODO: shouldn't clear queued filters, but we can't wait for them to be run + // since generic filters are run before them. remove after refactoring + // processed metrics. + } + + /** + * An intersected table is a table that describes visits by a certain dimension for the visits + * represented by a row in another table. This method fetches intersected tables either via + * subtable or by using a segment. Read the class docs for more info. + */ + private function getIntersectedTable(DataTable $table, Row $row) + { + if ($this->isPivotDimensionSubtable()) { + return $this->loadSubtable($table, $row); + } + + if ($this->isFetchingBySegmentEnabled) { + $segmentValue = $row->getColumn('label'); + return $this->fetchIntersectedWithThisBySegment($table, $segmentValue); + } + + // should never occur, unless checkSupportedPivot() fails to catch an unsupported pivot + throw new Exception("Unexpected error, cannot fetch intersected table."); + } + + private function isPivotDimensionSubtable() + { + return !empty($this->subtableDimension) && $this->subtableDimension->getId() == $this->pivotByDimension->getId(); + } + + private function loadSubtable(DataTable $table, Row $row) + { + $idSubtable = $row->getIdSubDataTable(); + if ($idSubtable === null) { + return null; + } + + if ($row->isSubtableLoaded()) { + $subtable = $row->getSubtable(); + } else { + $subtable = $this->thisReport->fetchSubtable($idSubtable, $this->getRequestParamOverride($table)); + } + + if ($subtable === null) { // sanity check + throw new Exception("Unexpected error: could not load subtable '$idSubtable'."); + } + + return $subtable; + } + + private function fetchIntersectedWithThisBySegment(DataTable $table, $segmentValue) + { + $segmentStr = $this->thisReportDimensionSegment->getSegment() . "==" . urlencode($segmentValue); + + Log::debug("PivotByDimension: Fetching intersected with segment '%s'", $segmentStr); + + $params = array('segment' => $segmentStr) + $this->getRequestParamOverride($table); + return $this->pivotDimensionReport->fetch($params); + } + + private function setPivotByDimension($pivotByDimension) + { + $this->pivotByDimension = Dimension::factory($pivotByDimension); + if (empty($this->pivotByDimension)) { + throw new Exception("Invalid dimension '$pivotByDimension'."); + } + + $this->pivotDimensionReport = Report::getForDimension($this->pivotByDimension); + } + + private function setThisReportMetadata($report) + { + list($module, $method) = explode('.', $report); + + $this->thisReport = Report::factory($module, $method); + if (empty($this->thisReport)) { + throw new Exception("Unable to find report '$report'."); + } + + $this->subtableDimension = $this->thisReport->getSubtableDimension(); + + $thisReportDimension = $this->thisReport->getDimension(); + if ($thisReportDimension !== null) { + $segments = $thisReportDimension->getSegments(); + $this->thisReportDimensionSegment = reset($segments); + } + } + + private function checkSupportedPivot() + { + $reportId = $this->thisReport->getModule() . '.' . $this->thisReport->getName(); + + if (!$this->isFetchingBySegmentEnabled) { + // if fetching by segment is disabled, then there must be a subtable for the current report and + // subtable's dimension must be the pivot dimension + + if (empty($this->subtableDimension)) { + throw new Exception("Unsupported pivot: report '$reportId' has no subtable dimension."); + } + + if ($this->subtableDimension->getId() !== $this->pivotByDimension->getId()) { + throw new Exception("Unsupported pivot: the subtable dimension for '$reportId' does not match the " + . "requested pivotBy dimension. [subtable dimension = {$this->subtableDimension->getId()}, " + . "pivot by dimension = {$this->pivotByDimension->getId()}]"); + } + } else { + $canFetchBySubtable = !empty($this->subtableDimension) + && $this->subtableDimension->getId() === $this->pivotByDimension->getId(); + if ($canFetchBySubtable) { + return; + } + + // if fetching by segment is enabled, and we cannot fetch by subtable, then there has to be a report + // for the pivot dimension (so we can fetch the report), and there has to be a segment for this report's + // dimension (so we can use it when fetching) + + if (empty($this->pivotDimensionReport)) { + throw new Exception("Unsupported pivot: No report for pivot dimension '{$this->pivotByDimension->getId()}'" + . " (report required for fetching intersected tables by segment)."); + } + + if (empty($this->thisReportDimensionSegment)) { + throw new Exception("Unsupported pivot: No segment for dimension of report '$reportId'." + . " (segment required for fetching intersected tables by segment)."); + } + } + } + + /** + * @param $columnRow + * @param $pivotColumn + * @return false|mixed + */ + private function getColumnValue(Row $columnRow, $pivotColumn) + { + $value = $columnRow->getColumn($pivotColumn); + if (empty($value) + && !empty($this->metricIndexValue) + ) { + $value = $columnRow->getColumn($this->metricIndexValue); + } + return $value; + } + + private function getNameOfFirstNonLabelColumnInTable(DataTable $table) + { + foreach ($table->getRows() as $row) { + foreach ($row->getColumns() as $columnName => $ignore) { + if ($columnName != 'label') { + return $columnName; + } + } + } + } + + private function getRequestParamOverride(DataTable $table) + { + $params = array( + 'pivotBy' => '', + 'column' => '', + 'flat' => 0, + 'totals' => 0, + 'disable_queued_filters' => 1, + 'disable_generic_filters' => 1, + 'showColumns' => '', + 'hideColumns' => '' + ); + + $site = $table->getMetadata('site'); + if (!empty($site)) { + $params['idSite'] = $site->getId(); + } + + $period = $table->getMetadata('period'); + if (!empty($period)) { + $params['date'] = $period->getDateStart()->toString(); + $params['period'] = $period->getLabel(); + } + + return $params; + } + + /** + * Returns true if pivoting by subtable is supported for a report. Will return true if the report + * has a subtable dimension and if the subtable dimension is different than the report's dimension. + * + * @param Report $report + * @return bool + */ + public static function isPivotingReportBySubtableSupported(Report $report) + { + $subtableDimension = $report->getSubtableDimension(); + return !empty($subtableDimension) && $subtableDimension->getId() !== $report->getDimension()->getId(); + } + + /** + * Returns true if fetching intersected tables by segment is enabled in the INI config, false if otherwise. + * + * @return bool + */ + public static function isSegmentFetchingEnabledInConfig() + { + return Config::getInstance()->General['pivot_by_filter_enable_fetch_by_segment']; + } +} \ No newline at end of file diff --git a/core/DataTable/Renderer/Csv.php b/core/DataTable/Renderer/Csv.php index 064dbd6db1..25961ce8a9 100644 --- a/core/DataTable/Renderer/Csv.php +++ b/core/DataTable/Renderer/Csv.php @@ -278,6 +278,11 @@ class Csv extends Renderer if ($this->translateColumnNames) { $columnMetrics = $this->translateColumnNames($columnMetrics); } + + foreach ($columnMetrics as &$value) { + $value = $this->formatValue($value); + } + return implode($this->separator, $columnMetrics); } @@ -387,4 +392,14 @@ class Csv extends Renderer return $name; } } + + private function escapeCsvValue($value) + { + if (strpos($value, ',') !== false + || strpos($value, '"') !== false + ) { + return '"' . addslashes($value) . '"'; + } + return $value; + } } diff --git a/core/DataTable/Renderer/Xml.php b/core/DataTable/Renderer/Xml.php index 9eb7db914b..93c800fafa 100644 --- a/core/DataTable/Renderer/Xml.php +++ b/core/DataTable/Renderer/Xml.php @@ -154,8 +154,7 @@ class Xml extends Renderer foreach ($array as $key => $value) { // based on the type of array & the key, determine how this node will look if ($isAssociativeArray) { - $keyIsInvalidXmlElement = is_numeric($key) || is_numeric($key[0]); - if ($keyIsInvalidXmlElement) { + if (!self::isValidXmlTagName($key)) { $prefix = ""; $suffix = ""; $emptyNode = ""; @@ -338,6 +337,8 @@ class Xml extends Renderer */ protected function renderDataTable($array, $prefixLine = "") { + $columnsHaveInvalidChars = $this->areTableLabelsInvalidXmlTagNames(reset($array)); + $out = ''; foreach ($array as $rowId => $row) { if (!is_array($row)) { @@ -373,10 +374,13 @@ class Xml extends Renderer } else { $value = self::formatValueXml($value); } + + list($tagStart, $tagEnd) = $this->getTagStartAndEndFor($name, $columnsHaveInvalidChars); + if (strlen($value) == 0) { - $out .= $prefixLine . "\t\t<$name />\n"; + $out .= $prefixLine . "\t\t<$tagStart />\n"; } else { - $out .= $prefixLine . "\t\t<$name>" . $value . "\n"; + $out .= $prefixLine . "\t\t<$tagStart>" . $value . "\n"; } } $out .= "\t"; @@ -399,15 +403,62 @@ class Xml extends Renderer $array = array('value' => $array); } + $columnsHaveInvalidChars = $this->areTableLabelsInvalidXmlTagNames($array); + $out = ''; foreach ($array as $keyName => $value) { $xmlValue = self::formatValueXml($value); + list($tagStart, $tagEnd) = $this->getTagStartAndEndFor($keyName, $columnsHaveInvalidChars); if (strlen($xmlValue) == 0) { - $out .= $prefixLine . "\t<$keyName />\n"; + $out .= $prefixLine . "\t<$tagStart />\n"; } else { - $out .= $prefixLine . "\t<$keyName>" . $xmlValue . "\n"; + $out .= $prefixLine . "\t<$tagStart>" . $xmlValue . "\n"; } } return $out; } -} + + /** + * Returns true if a string is a valid XML tag name, false if otherwise. + * + * @param string $str + * @return bool + */ + private static function isValidXmlTagName($str) + { + static $validTagRegex = null; + + if ($validTagRegex === null) { + $invalidTagChars = "!\"#$%&'()*+,\\/;<=>?@[\\]\\\\^`{|}~"; + $invalidTagStartChars = $invalidTagChars . "\\-.0123456789"; + $validTagRegex = "/^[^" . $invalidTagStartChars . "][^" . $invalidTagChars . "]*$/"; + } + + $result = preg_match($validTagRegex, $str); + return !empty($result); + } + + private function areTableLabelsInvalidXmlTagNames($rowArray) + { + if (!empty($rowArray)) { + foreach ($rowArray as $name => $value) { + if (!self::isValidXmlTagName($name)) { + return true; + } + } + } + return false; + } + + private function getTagStartAndEndFor($keyName, $columnsHaveInvalidChars) + { + if ($columnsHaveInvalidChars) { + $tagStart = "col name=\"" . self::formatValueXml($keyName) . "\""; + $tagEnd = "col"; + } else { + $tagStart = $tagEnd = $keyName; + } + + return array($tagStart, $tagEnd); + } +} \ No newline at end of file diff --git a/core/EventDispatcher.php b/core/EventDispatcher.php index ce0815c6ba..d9d26b4377 100644 --- a/core/EventDispatcher.php +++ b/core/EventDispatcher.php @@ -201,12 +201,14 @@ class EventDispatcher extends Singleton } /** - * TODO + * Returns the Plugin\Manager instance used by the event dispatcher. + * + * @return Plugin\Manager */ private function getPluginManager() { if ($this->pluginManager === null) { - $this->pluginManager = \Piwik\Plugin\Manager::getInstance(); + $this->pluginManager = Plugin\Manager::getInstance(); } return $this->pluginManager; } diff --git a/core/Metrics.php b/core/Metrics.php index c88bb13294..03b9e2e094 100644 --- a/core/Metrics.php +++ b/core/Metrics.php @@ -181,6 +181,7 @@ class Metrics return $names; } + // TODO: this method is named wrong public static function getMappingFromIdToName() { $idToName = array_flip(self::$mappingFromIdToName); diff --git a/core/Plugin/ComponentFactory.php b/core/Plugin/ComponentFactory.php index 02cb6083e1..68415e9397 100644 --- a/core/Plugin/ComponentFactory.php +++ b/core/Plugin/ComponentFactory.php @@ -37,20 +37,14 @@ class ComponentFactory public static function factory($pluginName, $componentClassSimpleName, $componentTypeClass) { if (empty($pluginName) || empty($componentClassSimpleName)) { + Log::debug("ComponentFactory::%s: empty plugin name or component simple name requested (%s, %s)", + __FUNCTION__, $pluginName, $componentClassSimpleName); + return null; } - $pluginManager = PluginManager::getInstance(); - - try { - if (!$pluginManager->isPluginActivated($pluginName)) { - return null; - } - - $plugin = $pluginManager->getLoadedPlugin($pluginName); - } catch (Exception $e) { - Log::debug($e); - + $plugin = self::getActivatedPlugin(__FUNCTION__, $pluginName); + if (empty($plugin)) { return null; } @@ -63,6 +57,75 @@ class ComponentFactory return new $class(); } } + + Log::debug("ComponentFactory::%s: Could not find requested component (args = ['%s', '%s', '%s']).", + __FUNCTION__, $pluginName, $componentClassSimpleName, $componentTypeClass); + + return null; + } + + /** + * Finds a component instance that satisfies a given predicate. + * + * @param string $componentTypeClass The fully qualified class name of the component type, eg, + * `"Piwik\Plugin\Report"`. + * @param string $pluginName|false The name of the plugin the component is expected to belong to, + * eg, `'UserSettings'`. + * @param callback $predicate + * @return mixed The component that satisfies $predicate or null if not found. + */ + public static function getComponentIf($componentTypeClass, $pluginName, $predicate) + { + $pluginManager = PluginManager::getInstance(); + + // get components to search through + $subnamespace = $componentTypeClass::COMPONENT_SUBNAMESPACE; + if (empty($pluginName)) { + $components = $pluginManager->findMultipleComponents($subnamespace, $componentTypeClass); + } else { + $plugin = self::getActivatedPlugin(__FUNCTION__, $pluginName); + if (empty($plugin)) { + return null; + } + + $components = $plugin->findMultipleComponents($subnamespace, $componentTypeClass); + } + + // find component that satisfieds predicate + foreach ($components as $class) { + $component = new $class(); + if ($predicate($component)) { + return $component; + } + } + + Log::debug("ComponentFactory::%s: Could not find component that satisfies predicate (args = ['%s', '%s', '%s']).", + __FUNCTION__, $componentTypeClass, $pluginName, get_class($predicate)); + return null; } + + /** + * @param string $function + * @param string $pluginName + * @return null|\Piwik\Plugin + */ + private static function getActivatedPlugin($function, $pluginName) + { + $pluginManager = PluginManager::getInstance(); + try { + if (!$pluginManager->isPluginActivated($pluginName)) { + Log::debug("ComponentFactory::%s: component for deactivated plugin ('%s') requested.", + $function, $pluginName); + + return null; + } + + return $pluginManager->getLoadedPlugin($pluginName); + } catch (Exception $e) { + Log::debug($e); + + return null; + } + } } \ No newline at end of file diff --git a/core/Plugin/Report.php b/core/Plugin/Report.php index d9ee86e5c3..a907b0f709 100644 --- a/core/Plugin/Report.php +++ b/core/Plugin/Report.php @@ -9,7 +9,10 @@ namespace Piwik\Plugin; use Piwik\API\Proxy; +use Piwik\API\Request; use Piwik\Cache\LanguageAwareStaticCache; +use Piwik\Columns\Dimension; +use Piwik\DataTable; use Piwik\Menu\MenuReporting; use Piwik\Metrics; use Piwik\Piwik; @@ -575,6 +578,57 @@ class Report return $this->actionToLoadSubTables; } + /** + * Returns the Dimension instance of this report's subtable report. + * + * @return Dimension|null The subtable report's dimension or null if there is subtable report or + * no dimension for the subtable report. + * @api + */ + public function getSubtableDimension() + { + if (empty($this->actionToLoadSubTables)) { + return null; + } + + list($subtableReportModule, $subtableReportAction) = $this->getSubtableApiMethod(); + + $subtableReport = self::factory($subtableReportModule, $subtableReportAction); + if (empty($subtableReport)) { + return null; + } + + return $subtableReport->getDimension(); + } + + /** + * Fetches the report represented by this instance. + * + * @param array $paramOverride Query parameter overrides. + * @return DataTable + * @api + */ + public function fetch($paramOverride = array()) + { + return Request::processRequest($this->module . '.' . $this->action, $paramOverride); + } + + /** + * Fetches a subtable for the report represented by this instance. + * + * @param int $idSubtable The subtable ID. + * @param array $paramOverride Query parameter overrides. + * @return DataTable + * @api + */ + public function fetchSubtable($idSubtable, $paramOverride = array()) + { + $paramOverride = array('idSubtable' => $idSubtable) + $paramOverride; + + list($module, $action) = $this->getSubtableApiMethod(); + return Request::processRequest($module . '.' . $action, $paramOverride); + } + /** * Get an instance of a specific report belonging to the given module and having the given action. * @param string $module @@ -648,4 +702,29 @@ class Report { return 'menu' . ucfirst($this->action); } + + private function getSubtableApiMethod() + { + if (strpos($this->actionToLoadSubTables, '.') !== false) { + return explode('.', $this->actionToLoadSubTables); + } else { + return array($this->module, $this->actionToLoadSubTables); + } + } + + /** + * Finds a top level report that provides stats for a specific Dimension. + * + * @param Dimension $dimension The dimension whose report we're looking for. + * @return Report|null The + * @api + */ + public static function getForDimension(Dimension $dimension) + { + return ComponentFactory::getComponentIf(__CLASS__, $dimension->getModule(), function (Report $report) use ($dimension) { + return !$report->isSubtableReport + && $report->getDimension() + && $report->getDimension()->getId() == $dimension->getId(); + }); + } } diff --git a/core/Plugin/Segment.php b/core/Plugin/Segment.php index cc3392eebc..795d4da157 100644 --- a/core/Plugin/Segment.php +++ b/core/Plugin/Segment.php @@ -186,6 +186,16 @@ class Segment return $this->type; } + /** + * Returns the name of this segment as it should appear in segment expressions. + * + * @return string + */ + public function getSegment() + { + return $this->segment; + } + /** * Set callback which will be executed when user will call for suggested values for segment. * diff --git a/core/ViewDataTable/Config.php b/core/ViewDataTable/Config.php index 093f28b254..0389c213fb 100644 --- a/core/ViewDataTable/Config.php +++ b/core/ViewDataTable/Config.php @@ -9,7 +9,9 @@ namespace Piwik\ViewDataTable; use Piwik\API\Request as ApiRequest; +use Piwik\DataTable\Filter\PivotByDimension; use Piwik\Metrics; +use Piwik\Plugin\Report; use Piwik\Plugins\API\API; /** @@ -83,7 +85,8 @@ class Config * The list of ViewDataTable properties that are 'Client Side Properties'. */ public $clientSideProperties = array( - 'show_limit_control' + 'show_limit_control', + 'pivot_by_dimension' ); /** @@ -93,6 +96,7 @@ class Config 'show_goals', 'show_exclude_low_population', 'show_flatten_table', + 'show_pivot_by_subtable', 'show_table', 'show_table_all_columns', 'show_footer', @@ -184,6 +188,18 @@ class Config */ public $show_flatten_table = true; + /** + * Whether to show the 'Pivot by subtable' option (visible in the popup that displays after clicking + * the 'cog' icon). + */ + public $show_pivot_by_subtable; + + /** + * The ID of the dimension to pivot by when the 'pivot by subtable' option is clicked. Defaults + * to the subtable dimension of the report being displayed. + */ + public $pivot_by_dimension; + /** * Controls whether the footer icon that allows users to switch to the 'normal' DataTable view * is shown. @@ -447,6 +463,7 @@ class Config $this->report_id = $controllerName . '.' . $controllerAction; $this->loadDocumentation(); + $this->setShouldShowPivotBySubtable(); } /** Load documentation from the API */ @@ -635,4 +652,19 @@ class Config $this->addTranslation($key, $translation); } } + + private function setShouldShowPivotBySubtable() + { + $report = Report::factory($this->controllerName, $this->controllerAction); + + if (empty($report)) { + $this->show_pivot_by_subtable = false; + $this->pivot_by_dimension = false; + } else { + $this->show_pivot_by_subtable = PivotByDimension::isPivotingReportBySubtableSupported($report); + + $subtableDimension = $report->getSubtableDimension(); + $this->pivot_by_dimension = $subtableDimension ? $subtableDimension->getId() : false; + } + } } diff --git a/plugins/CoreConsole/Commands/TestsSetupFixture.php b/plugins/CoreConsole/Commands/TestsSetupFixture.php index 1d38f9f3bf..cc5481d7e4 100644 --- a/plugins/CoreConsole/Commands/TestsSetupFixture.php +++ b/plugins/CoreConsole/Commands/TestsSetupFixture.php @@ -134,7 +134,7 @@ class TestsSetupFixture extends ConsoleCommand private function createSqlDump($sqlDumpPath, OutputInterface $output) { - $output->write("Creating SQL dump..."); + $output->writeln("Creating SQL dump..."); $databaseConfig = Config::getInstance()->database; $dbUser = $databaseConfig['username']; @@ -143,6 +143,7 @@ class TestsSetupFixture extends ConsoleCommand $dbName = $databaseConfig['dbname']; $command = "mysqldump --user='$dbUser' --password='$dbPass' --host='$dbHost' '$dbName' > '$sqlDumpPath'"; + $output->writeln("Executing $command..."); passthru($command); $this->writeSuccessMessage($output, array("SQL dump created!")); diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php index 64cead7bcd..61fd18d54b 100644 --- a/plugins/CoreHome/CoreHome.php +++ b/plugins/CoreHome/CoreHome.php @@ -238,5 +238,7 @@ class CoreHome extends \Piwik\Plugin $translationKeys[] = 'General_Default'; $translationKeys[] = 'General_LoadingData'; $translationKeys[] = 'General_ErrorRequest'; + $translationKeys[] = 'CoreHome_UndoPivotBySubtable'; + $translationKeys[] = 'CoreHome_PivotBySubtable'; } } diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 4ba2607c14..11c1f79e2d 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -155,7 +155,8 @@ $.extend(DataTable.prototype, UIControl.prototype, { 'columns', 'flat', 'include_aggregate_rows', - 'totalRows' + 'totalRows', + 'pivotBy' ]; for (var key = 0; key < filters.length; key++) { @@ -1089,6 +1090,9 @@ $.extend(DataTable.prototype, UIControl.prototype, { } else { str += '&expanded=1'; } + if (self.param.pivotBy) { + str += '&pivotBy=' + self.param.pivotBy; + } if (format == 'CSV' || format == 'TSV' || format == 'RSS') { str += '&translateColumnNames=1&language=' + piwik.language; } @@ -1171,10 +1175,14 @@ $.extend(DataTable.prototype, UIControl.prototype, { }; $('div.tableConfiguration', domElem).hover(open, close); - var generateClickCallback = function (paramName, callbackAfterToggle) { + var generateClickCallback = function (paramName, callbackAfterToggle, setParamCallback) { return function () { close(); - self.param[paramName] = (1 - self.param[paramName]) + ''; + if (setParamCallback) { + setParamCallback(); + } else { + self.param[paramName] = (1 - self.param[paramName]) + ''; + } self.param.filter_offset = 0; delete self.param.totalRows; if (callbackAfterToggle) callbackAfterToggle(); @@ -1247,6 +1255,23 @@ $.extend(DataTable.prototype, UIControl.prototype, { } })); + // handle pivot by + $('.dataTablePivotBySubtable', domElem) + .each(function () { + if (self.param.pivotBy) { + $(this).html(getText('CoreHome_UndoPivotBySubtable', true)); + } else { + $(this).html(getText('CoreHome_PivotBySubtable')); + } + }) + .click(generateClickCallback('pivotBy', null, function () { + if (self.param.pivotBy) { + self.param.pivotBy = ''; + } else { + self.param.pivotBy = self.props.pivot_by_dimension; + } + })); + // handle highlighted icon if (iconHighlighted) { icon.addClass('highlighted'); diff --git a/plugins/CoreHome/lang/en.json b/plugins/CoreHome/lang/en.json index c976f2ad3a..71ed8e4d09 100644 --- a/plugins/CoreHome/lang/en.json +++ b/plugins/CoreHome/lang/en.json @@ -59,6 +59,8 @@ "ViewAllPiwikVideoTutorials": "View all Piwik Video Tutorials", "WebAnalyticsReports": "Web Analytics Reports", "YouAreUsingTheLatestVersion": "You are using the latest version of Piwik!", - "ClickRowToExpandOrContract": "Click this row to expand or contract the subtable." + "ClickRowToExpandOrContract": "Click this row to expand or contract the subtable.", + "UndoPivotBySubtable": "This report has been pivoted %s Undo pivot", + "PivotBySubtable": "This report is not pivoted %s Pivot by subtable" } } \ No newline at end of file diff --git a/plugins/CoreHome/templates/_dataTableFooter.twig b/plugins/CoreHome/templates/_dataTableFooter.twig index 4c0a588487..0f673aa2a2 100644 --- a/plugins/CoreHome/templates/_dataTableFooter.twig +++ b/plugins/CoreHome/templates/_dataTableFooter.twig @@ -97,6 +97,11 @@
{% endif %} + {% if properties.show_pivot_by_subtable|default is not empty %} +
  • +
    +
  • + {% endif %} {% if isPluginLoaded('Annotations') and not properties.hide_annotations_view %} diff --git a/tests/PHPUnit/Core/Columns/DimensionTest.php b/tests/PHPUnit/Core/Columns/DimensionTest.php index 477ce7114a..6952b3880f 100644 --- a/tests/PHPUnit/Core/Columns/DimensionTest.php +++ b/tests/PHPUnit/Core/Columns/DimensionTest.php @@ -171,5 +171,5 @@ namespace Piwik\Tests\Core\Columns $dimension = Dimension::factory("ExampleTracker.ExampleDimension"); $this->assertInstanceOf("Piwik\\Plugins\\ExampleTracker\\Columns\\ExampleDimension", $dimension); } - } + } } \ No newline at end of file diff --git a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php new file mode 100644 index 0000000000..e20cdaf682 --- /dev/null +++ b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php @@ -0,0 +1,351 @@ +getMock('stdClass', array('call')); + $proxyMock->expects($this->any())->method('call')->willReturnCallback(function ($className, $methodName, $parameters) use ($self) { + if ($className == "\\Piwik\\Plugins\\UserCountry\\API" + && $methodName == 'getCity' + ) { + return $self->getSegmentTable(); + } else { + throw new Exception("Unknown API request: $className::$methodName."); + } + }); + Proxy::setSingletonInstance($proxyMock); + + $this->segmentTableCount = 0; + } + + public function tearDown() + { + PluginManager::unsetInstance(); + Proxy::unsetInstance(); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Unsupported pivot: report 'ExampleReport.ExampleReportName' has no subtable dimension. + */ + public function testConstructionFailsWhenReportHasNoSubtableAndSegmentFetchingIsDisabled() + { + PluginManager::getInstance()->loadPlugins(array('ExampleReport', 'UserCountry')); + + new PivotByDimension(new DataTable(), "ExampleReport.GetExampleReport", "UserCountry.City", 'nb_visits', $columnLimit = -1, $enableFetchBySegment = false); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Unsupported pivot: the subtable dimension for 'Referrers.Referrers_Keywords' does not match the requested pivotBy dimension. + */ + public function testConstructionFailsWhenDimensionIsNotSubtableAndSegmentFetchingIsDisabled() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry')); + + new PivotByDimension(new DataTable(), "Referrers.getKeywords", "UserCountry.City", "nb_visits", $columnLimit = -1, $enableFetchBySegment = false); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Unsupported pivot: No segment for dimension of report 'UserSettings.UserSettings_WidgetBrowserFamilies' + */ + public function testConstructionFailsWhenDimensionIsNotSubtableAndSegmentFetchingIsEnabledButThereIsNoSegment() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserSettings')); + + new PivotByDimension(new DataTable(), "UserSettings.getBrowserType", "Referrers.Keyword", "nb_visits"); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Invalid dimension 'ExampleTracker.InvalidDimension' + */ + public function testConstructionFailsWhenDimensionDoesNotExist() + { + PluginManager::getInstance()->loadPlugins(array('ExampleReport', 'ExampleTracker')); + + new PivotByDimension(new DataTable(), "ExampleReport.GetExampleReport", "ExampleTracker.InvalidDimension", 'nb_visits'); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Unsupported pivot: No report for pivot dimension 'ExampleTracker.ExampleDimension' + */ + public function testConstructionFailsWhenThereIsNoReportForADimension() + { + PluginManager::getInstance()->loadPlugins(array('ExampleReport', 'ExampleTracker')); + + new PivotByDimension(new DataTable(), "ExampleReport.GetExampleReport", "ExampleTracker.ExampleDimension", "nb_visits"); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Unable to find report 'ExampleReport.InvalidReport' + */ + public function testConstructionFailsWhenSpecifiedReportIsNotValid() + { + PluginManager::getInstance()->loadPlugins(array('ExampleReport', 'Referrers')); + + new PivotByDimension(new DataTable(), "ExampleReport.InvalidReport", "Referrers.Keyword", "nb_visits"); + } + + public function testFilterReturnsEmptyResultWhenTableToFilterIsEmpty() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + + $table = new DataTable(); + + $pivotFilter = new PivotByDimension($table, "Referrers.getKeywords", "Referrers.SearchEngine", 'nb_visits'); + $pivotFilter->filter($table); + + $expectedRows = array(); + $this->assertEquals($expectedRows, $table->getRows()); + } + + public function testFilterCorrectlyCreatesPivotTableUsingSubtableReport() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + + $table = $this->getTableToFilter(true); + + $pivotFilter = new PivotByDimension($table, "Referrers.getKeywords", "Referrers.SearchEngine", 'nb_actions', $columnLimit = -1, $fetchBySegment = false); + $pivotFilter->filter($table); + + $expectedRows = array( + array('label' => 'row 1', 'col 1' => 2, 'col 2' => false, 'col 3' => false, 'col 4' => false), + array('label' => 'row 2', 'col 1' => 4, 'col 2' => 6, 'col 3' => false, 'col 4' => false), + array('label' => 'row 3', 'col 1' => false, 'col 2' => 8, 'col 3' => 31, 'col 4' => 33) + ); + $this->assertTableRowsEquals($expectedRows, $table); + } + + public function testFilterCorrectlyCreatesPivotTableUsingSegment() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + + $table = $this->getTableToFilter(true); + + $pivotFilter = new PivotByDimension($table, "Referrers.getKeywords", "UserCountry.City", 'nb_visits'); + $pivotFilter->filter($table); + + $expectedRows = array( + array('label' => 'row 1', 'col 0' => 2, 'col 1' => false, 'col 2' => false), + array('label' => 'row 2', 'col 0' => 2, 'col 1' => 4, 'col 2' => false), + array('label' => 'row 3', 'col 0' => 2, 'col 1' => 4, 'col 2' => 6) + ); + $this->assertTableRowsEquals($expectedRows, $table); + } + + public function testFilterCorrectlyCreatesPivotTableWhenPivotMetricDoesNotExistInTable() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + + $table = $this->getTableToFilter(true); + + $pivotFilter = new PivotByDimension($table, "Referrers.getKeywords", "Referrers.SearchEngine", 'invalid_metric'); + $pivotFilter->filter($table); + + $expectedRows = array( + array('label' => 'row 1', 'col 1' => false, 'col 2' => false, 'col 3' => false, 'col 4' => false), + array('label' => 'row 2', 'col 1' => false, 'col 2' => false, 'col 3' => false, 'col 4' => false), + array('label' => 'row 3', 'col 1' => false, 'col 2' => false, 'col 3' => false, 'col 4' => false) + ); + $this->assertTableRowsEquals($expectedRows, $table); + } + + public function testFilterCorrectlyCreatesPivotTableWhenSubtablesHaveNoRows() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + + $table = $this->getTableToFilter(false); + + $pivotFilter = new PivotByDimension($table, "CustomVariables.getCustomVariables", "CustomVariables.CustomVariableValue", + 'nb_visits', $fetchBySegment = false); + $pivotFilter->filter($table); + + $expectedRows = array( + array('label' => 'row 1'), + array('label' => 'row 2'), + array('label' => 'row 3') + ); + $this->assertTableRowsEquals($expectedRows, $table); + } + + public function testFilterCorrectlyDefaultsPivotByColumnWhenNoneProvided() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + + $table = $this->getTableToFilter(true); + + $pivotFilter = new PivotByDimension($table, "Referrers.getKeywords", "Referrers.SearchEngine", $column = false, $columnLimit = -1, $fetchBySegment = false); + $pivotFilter->filter($table); + + $expectedRows = array( + array('label' => 'row 1', 'col 1' => 1, 'col 2' => false, 'col 3' => false, 'col 4' => false), + array('label' => 'row 2', 'col 1' => 3, 'col 2' => 5, 'col 3' => false, 'col 4' => false), + array('label' => 'row 3', 'col 1' => false, 'col 2' => 7, 'col 3' => 9, 'col 4' => 32) + ); + $this->assertTableRowsEquals($expectedRows, $table); + } + + public function testFilterCorrectlyLimitsTheColumnNumberWhenColumnLimitProvided() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + + $table = $this->getTableToFilter(true); + + $pivotFilter = new PivotByDimension($table, "Referrers.getKeywords", "Referrers.SearchEngine", $column = 'nb_visits', $columnLimit = 3, $fetchBySegment = false); + $pivotFilter->filter($table); + + $expectedRows = array( + array('label' => 'row 1', 'col 2' => false, 'col 3' => false, 'col 4' => false), + array('label' => 'row 2', 'col 2' => 5, 'col 3' => false, 'col 4' => false), + array('label' => 'row 3', 'col 2' => 7, 'col 3' => 9, 'col 4' => 32) + ); + $this->assertTableRowsEquals($expectedRows, $table); + } + + private function getTableToFilter($addSubtables = false) + { + $row1 = new Row(array(Row::COLUMNS => array( + 'label' => 'row 1', + 'nb_visits' => 10, + 'nb_actions' => 15 + ))); + if ($addSubtables) { + $row1->setSubtable($this->getRow1Subtable()); + } + + $row2 = new Row(array(Row::COLUMNS => array( + 'label' => 'row 2', + 'nb_visits' => 13, + 'nb_actions' => 18 + ))); + if ($addSubtables) { + $row2->setSubtable($this->getRow2Subtable()); + } + + $row3 = new Row(array(Row::COLUMNS => array( + 'label' => 'row 3', + 'nb_visits' => 20, + 'nb_actions' => 25 + ))); + if ($addSubtables) { + $row3->setSubtable($this->getRow3Subtable()); + } + + $table = new DataTable(); + $table->addRowsFromArray(array($row1, $row2, $row3)); + return $table; + } + + private function getRow1Subtable() + { + $table = new DataTable(); + $table->addRowsFromArray(array( + new Row(array(Row::COLUMNS => array( + 'label' => 'col 1', + 'nb_visits' => 1, + 'nb_actions' => 2 + ))) + )); + return $table; + } + + private function getRow2Subtable() + { + $table = new DataTable(); + $table->addRowsFromArray(array( + new Row(array(Row::COLUMNS => array( + 'label' => 'col 1', + 'nb_visits' => 3, + 'nb_actions' => 4 + ))), + new Row(array(Row::COLUMNS => array( + 'label' => 'col 2', + 'nb_visits' => 5, + 'nb_actions' => 6 + ))) + )); + return $table; + } + + private function getRow3Subtable() + { + $table = new DataTable(); + $table->addRowsFromArray(array( + new Row(array(Row::COLUMNS => array( + 'label' => 'col 2', + 'nb_visits' => 7, + 'nb_actions' => 8 + ))), + new Row(array(Row::COLUMNS => array( + 'label' => 'col 3', + 'nb_visits' => 9, + 'nb_actions' => 31 + ))), + new Row(array(Row::COLUMNS => array( + 'label' => 'col 4', + 'nb_visits' => 32, + 'nb_actions' => 33 + ))) + )); + return $table; + } + + private function getSegmentTable() + { + ++$this->segmentTableCount; + + $table = new DataTable(); + for ($i = 0; $i != $this->segmentTableCount; ++$i) { + $row = new Row(array(Row::COLUMNS => array( + 'label' => 'col ' . $i, + 'nb_visits' => ($i + 1) * 2, + 'nb_actions' => ($i + 1) * 3 + ))); + $table->addRow($row); + } + return $table; + } + + private function assertTableRowsEquals($expectedRows, $table) + { + $renderer = new DataTable\Renderer\Php(); + $renderer->setSerialize(false); + $actualRows = $renderer->render($table); + + $this->assertEquals($expectedRows, $actualRows); + } +} \ No newline at end of file diff --git a/tests/PHPUnit/Core/DataTable/Renderer/CSVTest.php b/tests/PHPUnit/Core/DataTable/Renderer/CSVTest.php index 4c5c77a355..64ffcf6a06 100644 --- a/tests/PHPUnit/Core/DataTable/Renderer/CSVTest.php +++ b/tests/PHPUnit/Core/DataTable/Renderer/CSVTest.php @@ -178,6 +178,22 @@ class DataTable_Renderer_CSVTest extends PHPUnit_Framework_TestCase $this->assertEquals($expected, $rendered); } + /** + * @group Core + */ + public function testCSVRendererCorrectlyEscapesHeadersAndValues() + { + $dataTable = $this->_getDataTableSimpleWithCommasInCells(); + $render = new Csv(); + $render->setTable($dataTable); + $render->convertToUnicode = false; + + $expected = '"col,1","col,2" +"val""1","val"",2"'; + $actual = $render->render(); + $this->assertEquals($expected, $actual); + } + /** * DATA OF DATATABLE_ARRAY * ------------------------- @@ -440,4 +456,13 @@ b,d,f,g'; $this->assertEquals($expected, $render->render()); } -} + + private function _getDataTableSimpleWithCommasInCells() + { + $table = new DataTable(); + $table->addRowsFromSimpleArray(array( + array("col,1" => "val\"1", "col,2" => "val\",2") + )); + return $table; + } +} \ No newline at end of file diff --git a/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php b/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php index 40596e0e23..40b58bdc13 100644 --- a/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php +++ b/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php @@ -11,6 +11,9 @@ use Piwik\DataTable\Renderer\Xml; use Piwik\DataTable\Row; use Piwik\DataTable\Simple; +/** + * @group Only + */ class DataTable_Renderer_XMLTest extends PHPUnit_Framework_TestCase { public function setUp() @@ -221,6 +224,39 @@ class DataTable_Renderer_XMLTest extends PHPUnit_Framework_TestCase $this->assertEquals($expected, $render->render()); } + /** + * @group Core + */ + public function testXMLRendererSuccessfullyRendersWhenSimpleDataTableColumnsHaveInvalidXmlCharacters() + { + $dataTable = $this->_getDataTableSimpleWithInvalidChars(); + $render = new Xml(); + $render->setTable($dataTable); + $expected = ' + + 1 + 2 + 2 +'; + $this->assertEquals($expected, $render->render()); + } + + public function testXMLRendererSuccessfullyRendersWhenDataTableColumnsHaveInvalidXmlCharacters() + { + $dataTable = $this->_getDataTableWithInvalidChars(); + $render = new Xml(); + $render->setTable($dataTable); + $expected = ' + + + 1 + 2 + 2 + +'; + $this->assertEquals($expected, $render->render()); + } + /** * DATA OF DATATABLE_ARRAY * ------------------------- @@ -601,4 +637,22 @@ class DataTable_Renderer_XMLTest extends PHPUnit_Framework_TestCase $this->assertEquals($expected, $render->render()); } + + private function _getDataTableSimpleWithInvalidChars() + { + $table = new DataTable\Simple(); + $table->addRowsFromSimpleArray( + array("$%@(%" => 1, "avbs$" => 2, "b/" => 2) + ); + return $table; + } + + private function _getDataTableWithInvalidChars() + { + $table = new DataTable(); + $table->addRowsFromSimpleArray( + array("$%@(%" => 1, "avbs$" => 2, "b/" => 2) + ); + return $table; + } } diff --git a/tests/PHPUnit/Core/Plugin/ComponentFactoryTest.php b/tests/PHPUnit/Core/Plugin/ComponentFactoryTest.php index d41149c8cd..b7b0f30fc3 100644 --- a/tests/PHPUnit/Core/Plugin/ComponentFactoryTest.php +++ b/tests/PHPUnit/Core/Plugin/ComponentFactoryTest.php @@ -11,6 +11,7 @@ use PHPUnit_Framework_TestCase; use Piwik\Config; use Piwik\Plugin\ComponentFactory; use Piwik\Plugin\Manager as PluginManager; +use Piwik\Plugin\Report; /** * @group Core @@ -74,6 +75,62 @@ class ComponentFactoryTest extends PHPUnit_Framework_TestCase $this->assertNull($report); } + public function test_getComponentIf_shouldNotFindAComponentIfComponentExistsButPluginIsNotLoaded() + { + $this->unloadAllPlugins(); + + $report = ComponentFactory::getComponentIf(self::REPORT_CLASS_NAME, 'ExampleReport', function (Report $report) { + return $report->getAction() == 'getExampleReport'; + }); + + $this->assertNull($report); + } + + public function test_getComponentIf_shouldFindAComponent_ThatExists() + { + $this->loadExampleReportPlugin(); + + $report = ComponentFactory::getComponentIf(self::REPORT_CLASS_NAME, 'ExampleReport', function (Report $report) { + return $report->getAction() == 'getExampleReport'; + }); + + $this->assertInstanceOf('Piwik\Plugins\ExampleReport\Reports\GetExampleReport', $report); + } + + public function test_getComponentIf_shouldNotFindAComponent_IfPluginIsActivatedButComponentNotExists() + { + $this->loadExampleReportPlugin(); + + $report = ComponentFactory::getComponentIf(self::REPORT_CLASS_NAME, 'ExampleReport', function (Report $report) { + return false; + }); + + $this->assertNull($report); + } + + public function test_getComponentIf_shouldNotFindAComponent_IfPluginIsLoadedButNotActivated() + { + PluginManager::getInstance()->loadPlugin('ExampleReport'); + + $report = ComponentFactory::getComponentIf(self::REPORT_CLASS_NAME, 'ExampleReport', function (Report $report) { + return $report->getAction() == 'getExampleReport'; + }); + + $this->assertNull($report); + } + + public function test_getComponentIf_shouldSearchThroughAllPlugins_IfNoPluginNameIsSupplied() + { + PluginManager::getInstance()->loadPlugins(array('ExampleReport', 'Referrers')); + + $reports = array(); + ComponentFactory::getComponentIf(self::REPORT_CLASS_NAME, null, function (Report $report) use (&$reports) { + $reports[] = $report; + }); + + $this->assertGreaterThan(1, count($reports)); + } + private function unloadAllPlugins() { PluginManager::getInstance()->loadPlugins(array()); diff --git a/tests/PHPUnit/Impl/TestRequestCollection.php b/tests/PHPUnit/Impl/TestRequestCollection.php index 17ff280eb9..68cae0ff99 100644 --- a/tests/PHPUnit/Impl/TestRequestCollection.php +++ b/tests/PHPUnit/Impl/TestRequestCollection.php @@ -246,7 +246,6 @@ class TestRequestCollection $parametersToSet['serialize'] = 1; $exampleUrl = $apiMetadata->getExampleUrl($class, $methodName, $parametersToSet); - if ($exampleUrl === false) { continue; } diff --git a/tests/PHPUnit/Integration/Core/ReportTest.php b/tests/PHPUnit/Integration/Core/ReportTest.php index c1d0df37f1..f935416675 100644 --- a/tests/PHPUnit/Integration/Core/ReportTest.php +++ b/tests/PHPUnit/Integration/Core/ReportTest.php @@ -6,11 +6,14 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ +use Piwik\API\Proxy; use Piwik\Plugin\Report; use Piwik\Plugins\ExampleReport\Reports\GetExampleReport; use Piwik\Plugins\Actions\Columns\ExitPageUrl; use Piwik\Piwik; use Piwik\Metrics; +use Piwik\Plugins\ExampleTracker\Columns\ExampleDimension; +use Piwik\Plugins\Referrers\Columns\Keyword; use Piwik\WidgetsList; use Piwik\Translate; use Piwik\Menu\MenuReporting; @@ -28,6 +31,7 @@ class GetBasicReport extends Report $this->module = 'TestPlugin'; $this->action = 'getBasicReport'; $this->category = 'Goals_Goals'; + $this->actionToLoadSubTables = 'invalidReport'; } } @@ -101,6 +105,8 @@ class Plugin_ReportTest extends DatabaseTestCase $this->disabledReport = new GetDisabledReport(); $this->basicReport = new GetBasicReport(); $this->advancedReport = new GetAdvancedReport(); + + Proxy::unsetInstance(); } public function tearDown() @@ -338,6 +344,7 @@ class Plugin_ReportTest extends DatabaseTestCase 'bounce_rate' => 'General_ColumnBounceRate', 'conversion_rate' => 'General_ColumnConversionRate', ), + 'actionToLoadSubTables' => 'invalidReport', 'order' => 20 ) ), $reports); @@ -422,6 +429,97 @@ class Plugin_ReportTest extends DatabaseTestCase } } + public function test_getSubtableDimension_ShouldReturnNullIfNoSubtableActionExists() + { + $report = new GetExampleReport(); + $this->assertNull($report->getSubtableDimension()); + } + + public function test_getSubtableDimension_ShouldReturnNullIfSubtableActionIsInvalid() + { + $report = new GetBasicReport(); + $this->assertNull($report->getSubtableDimension()); + } + + public function test_getSubtableDimension_ShouldReturnCorrectDimensionIfSubtableActionIsDefinedAndCorrect() + { + PluginManager::getInstance()->loadPlugins(array('Referrers')); + + $report = Report::factory('Referrers', 'getSearchEngines'); + $subtableDimension = $report->getSubtableDimension(); + + $this->assertNotNull($subtableDimension); + $this->assertInstanceOf("Piwik\\Plugins\\Referrers\\Columns\\Keyword", $subtableDimension); + } + + public function test_fetch_ShouldUseCorrectApiUrl() + { + PluginManager::getInstance()->loadPlugins(array('API', 'ExampleReport')); + + $proxyMock = $this->getMock('stdClass', array('call', '__construct')); + $proxyMock->expects($this->once())->method('call')->with( + '\\Piwik\\Plugins\\ExampleReport\\API', 'getExampleReport', array( + 'idSite' => 1, + 'date' => '2012-01-02', + 'format' => 'original', + 'module' => 'API', + 'method' => 'ExampleReport.getExampleReport' + ) + )->willReturn("result"); + Proxy::setSingletonInstance($proxyMock); + + $report = new GetExampleReport(); + $result = $report->fetch(array('idSite' => 1, 'date' => '2012-01-02')); + $this->assertEquals("result", $result); + } + + public function test_fetchSubtable_ShouldUseCorrectApiUrl() + { + PluginManager::getInstance()->loadPlugins(array('API', 'Referrers')); + + $proxyMock = $this->getMock('stdClass', array('call', '__construct')); + $proxyMock->expects($this->once())->method('call')->with( + '\\Piwik\\Plugins\\Referrers\\API', 'getSearchEnginesFromKeywordId', array( + 'idSubtable' => 23, + 'idSite' => 1, + 'date' => '2012-01-02', + 'format' => 'original', + 'module' => 'API', + 'method' => 'Referrers.getSearchEnginesFromKeywordId' + ) + )->willReturn("result"); + Proxy::setSingletonInstance($proxyMock); + + $report = new \Piwik\Plugins\Referrers\Reports\GetKeywords(); + $result = $report->fetchSubtable(23, array('idSite' => 1, 'date' => '2012-01-02')); + $this->assertEquals("result", $result); + } + + public function test_getForDimension_ShouldReturnCorrectInstanceTypeIfAssociatedReportExists() + { + PluginManager::getInstance()->loadPlugins(array('Referrers')); + + $report = Report::getForDimension(new Keyword()); + $this->assertInstanceOf("Piwik\\Plugins\\Referrers\\Reports\\GetKeywords", $report); + } + + public function test_getForDimension_ShouldReturnNullIfNoReportExistsForDimension() + { + $this->loadExampleReportPlugin(); + $this->loadMorePlugins(); + + $report = Report::getForDimension(new ExampleDimension()); + $this->assertNull($report); + } + + public function test_getForDimension_ShouldReturnNullIfReportPluginNotLoaded() + { + PluginManager::getInstance()->loadPlugins(array()); + + $report = Report::getForDimension(new Keyword()); + $this->assertNull($report); + } + private function loadExampleReportPlugin() { PluginManager::getInstance()->loadPlugins(array('ExampleReport')); @@ -441,6 +539,4 @@ class Plugin_ReportTest extends DatabaseTestCase { Translate::reloadLanguage('en'); } - - } \ No newline at end of file diff --git a/tests/PHPUnit/Integration/PivotByQueryParamTest.php b/tests/PHPUnit/Integration/PivotByQueryParamTest.php new file mode 100644 index 0000000000..a59ff9d1f3 --- /dev/null +++ b/tests/PHPUnit/Integration/PivotByQueryParamTest.php @@ -0,0 +1,167 @@ +General['pivot_by_filter_enable_fetch_by_segment'] = 1; + } + + public function testPivotBySubtableDimensionCreatesCorrectPivotTable() + { + $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'pivotBy' => 'Referrers.SearchEngine', + 'pivotByColumn' => 'nb_visits', + 'pivotByColumnLimit' => -1 + )); + } + + public function testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded() + { + $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'pivotBy' => 'Referrers.SearchEngine', + 'pivotByColumn' => '', // also test default pivot column + 'pivotByColumnLimit' => -1, + 'expanded' => 0 + )); + } + + public function testPivotBySegmentCreatesCorrectPivotTable() + { + $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'pivotBy' => 'UserCountry.City', + 'pivotByColumn' => 'nb_visits', + 'pivotByColumnLimit' => -1 + )); + } + + public function testPivotByParamPlaysNiceWithOtherQueryParams() + { + $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'pivotBy' => 'Referrers.SearchEngine', + 'pivotByColumn' => 'nb_visits', + 'pivotByColumnLimit' => -1, + 'flat' => 1, + 'totals' => 1, + 'disable_queued_filters' => 1, + 'disable_generic_filters' => 1, + 'showColumns' => 'Google,Bing' + )); + } + + public function testPivotByParamPlaysNiceWithQueuedFilters() + { + // TODO: known issue: some segment/report relationships are more complicated; for example, UserCountry.GetCity labels are combinations + // of city, region & country dimensions, so the segment to get an intersected table needs all 3 of those. + + $this->markTestSkipped("Not working right now."); + + $this->assertApiResponseEqualsExpected("UserSettings.getBrowser", array( // should have logo metadata in output + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'pivotBy' => 'UserCountry.City', // testing w/ report that has no subtable report + 'pivotByColumn' => 'nb_visits', + 'pivotByColumnLimit' => -1 + )); + } + + public function testPivotByParamWorksWithReportWhoseSubtableIsSelf() + { + $this->assertApiResponseEqualsExpected("Actions.getPageUrls", array( + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'pivotBy' => 'Actions.PageUrl', + 'pivotByColumn' => 'nb_hits', + 'pivotByColumnLimit' => -1 + )); + } + + public function testPivotByParamWorksWithColumnLimiting() + { + $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'pivotBy' => 'UserCountry.City', + 'pivotByColumn' => 'nb_visits', + 'pivotByColumnLimit' => 2 + )); + } + + public function testPivotByParamWorksWithJsonOutput() + { + $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'format' => 'json', + 'pivotBy' => 'UserCountry.City', + 'pivotByColumn' => 'nb_visits', + 'pivotByColumnLimit' => -1 + )); + } + + public function testPivotByParamWorksWithCsvOutput() + { + $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'format' => 'csv', + 'pivotBy' => 'UserCountry.City', + 'pivotByColumn' => 'nb_visits', + 'pivotByColumnLimit' => -1 + )); + } + + public function testPivotByParamPlaysNiceWithDataTableMaps() + { + $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( + 'idSite' => 'all', + 'date' => '2010-01-01,2010-01-07', + 'period' => 'day', + 'pivotBy' => 'UserCountry.City', + 'pivotByColumn' => 'nb_visits', + 'pivotByColumnLimit' => -1 + )); + } +} + +PivotByQueryParamTest::$fixture = new ManyVisitsWithMockLocationProvider(); \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml new file mode 100644 index 0000000000..a60b9519fb --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml @@ -0,0 +1,49 @@ + + + + + + + + this search term + 2 + 0 + 1 + + + search term 2 + 0 + 0 + 2 + + + search term 3 + 0 + 2 + 0 + + + search term 4 + 0 + 2 + 0 + + + that search term + 2 + 0 + 0 + + + search term 1 + 0 + 0 + 1 + + + + + + + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..777020b15e --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml @@ -0,0 +1,33 @@ + + + + + 0 + 1 + + + + 0 + 0 + + + + 0 + 1 + + + + 1 + 0 + + + + 0 + 1 + + + + 1 + 0 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..70bcfeed7d --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml @@ -0,0 +1,33 @@ + + + + this search term + 0 + 1 + + + search term 2 + 0 + 2 + + + search term 3 + 2 + 0 + + + search term 4 + 2 + 0 + + + that search term + 0 + 0 + + + search term 1 + 0 + 1 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv new file mode 100644 index 0000000000..9b91feb5ee Binary files /dev/null and b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv differ diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json new file mode 100644 index 0000000000..3ffebb1d65 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json @@ -0,0 +1 @@ +[{"label":"this search term","Melbourne, Victoria, Australia":2,"Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":1},{"label":"search term 2","Melbourne, Victoria, Australia":false,"Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":2},{"label":"search term 3","Melbourne, Victoria, Australia":false,"Toronto, Ontario, Canada":2,"Yokohama, Kanagawa, Japan":false},{"label":"search term 4","Melbourne, Victoria, Australia":false,"Toronto, Ontario, Canada":2,"Yokohama, Kanagawa, Japan":false},{"label":"that search term","Melbourne, Victoria, Australia":2,"Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":false},{"label":"search term 1","Melbourne, Victoria, Australia":false,"Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":1}] \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml new file mode 100644 index 0000000000..45bd7630ea --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml @@ -0,0 +1,123 @@ + + + + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + + + 2 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + + + 3 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + + + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..99086f82e8 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml @@ -0,0 +1,39 @@ + + + + this search term + 2 + 0 + 1 + + + search term 2 + 0 + 0 + 2 + + + search term 3 + 0 + 2 + 0 + + + search term 4 + 0 + 2 + 0 + + + that search term + 2 + 0 + 0 + + + search term 1 + 0 + 0 + 1 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..4c9fe03b6f --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml @@ -0,0 +1,57 @@ + + + + this search term + 0 + 1 + 0 + 0 + 1 + 1 + + + search term 2 + 1 + 0 + 1 + 0 + 0 + 0 + + + search term 3 + 0 + 1 + 0 + 0 + 1 + 0 + + + search term 4 + 0 + 0 + 0 + 1 + 0 + 1 + + + that search term + 0 + 0 + 0 + 0 + 1 + 1 + + + search term 1 + 0 + 0 + 0 + 1 + 0 + 0 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..4c9fe03b6f --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml @@ -0,0 +1,57 @@ + + + + this search term + 0 + 1 + 0 + 0 + 1 + 1 + + + search term 2 + 1 + 0 + 1 + 0 + 0 + 0 + + + search term 3 + 0 + 1 + 0 + 0 + 1 + 0 + + + search term 4 + 0 + 0 + 0 + 1 + 0 + 1 + + + that search term + 0 + 0 + 0 + 0 + 1 + 1 + + + search term 1 + 0 + 0 + 0 + 1 + 0 + 0 + + \ No newline at end of file diff --git a/tests/PHPUnit/IntegrationTestCase.php b/tests/PHPUnit/IntegrationTestCase.php index 59160c7c30..ae8a674ed2 100755 --- a/tests/PHPUnit/IntegrationTestCase.php +++ b/tests/PHPUnit/IntegrationTestCase.php @@ -274,11 +274,17 @@ abstract class IntegrationTestCase extends PHPUnit_Framework_TestCase list($processedFilePath, $expectedFilePath) = $this->getProcessedAndExpectedPaths($testName, $apiId, $format = null, $compareAgainst); + $originalGET = $_GET; + $_GET = $requestUrl; + unset($_GET['serialize']); + $processedResponse = TestRequestResponse::loadFromApi($params, $requestUrl); if (empty($compareAgainst)) { $processedResponse->save($processedFilePath); } + $_GET = $originalGET; + try { $expectedResponse = TestRequestResponse::loadFromFile($expectedFilePath, $params, $requestUrl); } catch (Exception $ex) { @@ -395,6 +401,7 @@ abstract class IntegrationTestCase extends PHPUnit_Framework_TestCase 'idSite' => $queryParams['idSite'], 'date' => $queryParams['date'], 'periods' => $queryParams['period'], + 'format' => isset($queryParams['format']) ? $queryParams['format'] : 'xml', 'testSuffix' => '_' . $this->getName(), // TODO: instead of using a test suffix, the whole file name should just be the test method 'otherRequestParameters' => $queryParams )); -- cgit v1.2.3 From bda5356a4695f03e14f820a65077bfdebf23ab52 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Thu, 18 Sep 2014 20:55:59 -0700 Subject: Fixing build. --- tests/PHPUnit/Core/API/ApiRendererTest.php | 3 +-- tests/PHPUnit/Core/API/ResponseBuilderTest.php | 2 +- tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php | 4 +++- tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php | 3 --- tests/PHPUnit/Core/Menu/MenuReportingTest.php | 4 ++++ tests/PHPUnit/Fixture.php | 5 +++++ tests/PHPUnit/Integration/Core/ArchiveProcessingTest.php | 8 ++++++++ tests/PHPUnit/Integration/Core/OptionTest.php | 2 -- tests/PHPUnit/Integration/Core/TravisEnvironmentTest.php | 3 --- 9 files changed, 22 insertions(+), 12 deletions(-) diff --git a/tests/PHPUnit/Core/API/ApiRendererTest.php b/tests/PHPUnit/Core/API/ApiRendererTest.php index a74db0bfe0..42d014ae17 100644 --- a/tests/PHPUnit/Core/API/ApiRendererTest.php +++ b/tests/PHPUnit/Core/API/ApiRendererTest.php @@ -7,7 +7,6 @@ */ use Piwik\API\ApiRenderer; -use Piwik\API\ApiRenderer\Json; /** * @group Core @@ -16,7 +15,7 @@ class ApiRendererTest extends PHPUnit_Framework_TestCase { public function setUp() { - \Piwik\Tests\Fixture::loadAllPlugins(); + \Piwik\Plugin\Manager::getInstance()->loadPlugins(array('API')); } public function test_factory_shouldCreateAnInstance_IfValidFormatGiven() diff --git a/tests/PHPUnit/Core/API/ResponseBuilderTest.php b/tests/PHPUnit/Core/API/ResponseBuilderTest.php index 9b3b7e53e1..9d6d0bc779 100644 --- a/tests/PHPUnit/Core/API/ResponseBuilderTest.php +++ b/tests/PHPUnit/Core/API/ResponseBuilderTest.php @@ -16,7 +16,7 @@ class ResponseBuilderTest extends PHPUnit_Framework_TestCase { public function setUp() { - \Piwik\Tests\Fixture::loadAllPlugins(); + \Piwik\Plugin\Manager::getInstance()->loadPlugins(array('API')); } public function test_getResponseException_shouldFormatExceptionDependingOnFormatAndAddDebugHelp() diff --git a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php index e20cdaf682..790c3cb6fe 100644 --- a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php +++ b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php @@ -8,6 +8,7 @@ namespace Piwik\Tests\Core\DataTable\Filter; use Piwik\API\Proxy; +use Piwik\Config; use Piwik\DataTable; use Piwik\DataTable\Filter\PivotByDimension; use Piwik\DataTable\Row; @@ -17,7 +18,6 @@ use Exception; /** * @group Core - * @group PivotByDimensionTest */ class PivotByDimensionTest extends PHPUnit_Framework_TestCase { @@ -46,6 +46,8 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase Proxy::setSingletonInstance($proxyMock); $this->segmentTableCount = 0; + + Config::getInstance()->setTestEnvironment(); } public function tearDown() diff --git a/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php b/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php index 40b58bdc13..d0b7441ee2 100644 --- a/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php +++ b/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php @@ -11,9 +11,6 @@ use Piwik\DataTable\Renderer\Xml; use Piwik\DataTable\Row; use Piwik\DataTable\Simple; -/** - * @group Only - */ class DataTable_Renderer_XMLTest extends PHPUnit_Framework_TestCase { public function setUp() diff --git a/tests/PHPUnit/Core/Menu/MenuReportingTest.php b/tests/PHPUnit/Core/Menu/MenuReportingTest.php index 09d0347959..b82c4a1aaf 100644 --- a/tests/PHPUnit/Core/Menu/MenuReportingTest.php +++ b/tests/PHPUnit/Core/Menu/MenuReportingTest.php @@ -6,6 +6,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ +use Piwik\Access; use Piwik\Plugin\Report; use Piwik\Piwik; use Piwik\Metrics; @@ -28,11 +29,14 @@ class Menu_ReportingTest extends PHPUnit_Framework_TestCase { PluginManager::getInstance()->unloadPlugins(); $this->menu = MenuReporting::getInstance(); + + Access::setSingletonInstance(new FakeAccess()); } public function tearDown() { MenuReporting::getInstance()->unsetInstance(); + Access::setSingletonInstance(null); parent::tearDown(); } diff --git a/tests/PHPUnit/Fixture.php b/tests/PHPUnit/Fixture.php index 3fd7320094..f625f98001 100644 --- a/tests/PHPUnit/Fixture.php +++ b/tests/PHPUnit/Fixture.php @@ -287,6 +287,11 @@ class Fixture extends PHPUnit_Framework_Assert $_GET = $_REQUEST = array(); Translate::unloadEnglishTranslation(); + + Config::unsetInstance(); + + \Piwik\Config::getInstance()->Plugins; // make sure Plugins exists in a config object for next tests that use Plugin\Manager + // since Plugin\Manager uses getFromGlobalConfig which doesn't init the config object } public static function loadAllPlugins($testEnvironment = null, $testCaseClass = false, $extraPluginsToLoad = array()) diff --git a/tests/PHPUnit/Integration/Core/ArchiveProcessingTest.php b/tests/PHPUnit/Integration/Core/ArchiveProcessingTest.php index 34aa3aeefb..eaa6d6807d 100644 --- a/tests/PHPUnit/Integration/Core/ArchiveProcessingTest.php +++ b/tests/PHPUnit/Integration/Core/ArchiveProcessingTest.php @@ -52,6 +52,14 @@ class Core_ArchiveProcessingTest extends DatabaseTestCase $pseudoMockAccess = new FakeAccess; FakeAccess::$superUser = true; Access::setSingletonInstance($pseudoMockAccess); + + ArchiveTableCreator::$tablesAlreadyInstalled = null; + } + + public function tearDown() + { + Access::setSingletonInstance(null); + ArchiveTableCreator::$tablesAlreadyInstalled = null; } /** diff --git a/tests/PHPUnit/Integration/Core/OptionTest.php b/tests/PHPUnit/Integration/Core/OptionTest.php index e405bae453..c926e1c808 100644 --- a/tests/PHPUnit/Integration/Core/OptionTest.php +++ b/tests/PHPUnit/Integration/Core/OptionTest.php @@ -9,8 +9,6 @@ use Piwik\Common; use Piwik\Db; use Piwik\Option; -require_once "Option.php"; - /** * Class Core_OptionTest * diff --git a/tests/PHPUnit/Integration/Core/TravisEnvironmentTest.php b/tests/PHPUnit/Integration/Core/TravisEnvironmentTest.php index 7b6b233ef4..7549dac8a9 100644 --- a/tests/PHPUnit/Integration/Core/TravisEnvironmentTest.php +++ b/tests/PHPUnit/Integration/Core/TravisEnvironmentTest.php @@ -9,9 +9,6 @@ use Piwik\Translate; */ class Core_TravisEnvironmentTest extends DatabaseTestCase { - /** - * @group Core - */ public function testUsageOfCorrectMysqlAdapter() { $mysqlAdapter = getenv('MYSQL_ADAPTER'); -- cgit v1.2.3 From 5076ef5e6b1dc17260945f80a3ee0d562702f970 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Thu, 18 Sep 2014 21:06:21 -0700 Subject: Fixing build. --- tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php b/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php index d0b7441ee2..f8c2a93072 100644 --- a/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php +++ b/tests/PHPUnit/Core/DataTable/Renderer/XMLTest.php @@ -238,6 +238,9 @@ class DataTable_Renderer_XMLTest extends PHPUnit_Framework_TestCase $this->assertEquals($expected, $render->render()); } + /** + * @group Core + */ public function testXMLRendererSuccessfullyRendersWhenDataTableColumnsHaveInvalidXmlCharacters() { $dataTable = $this->_getDataTableWithInvalidChars(); -- cgit v1.2.3 From eebd6dc7b5ee585fd5fffd2eb85b11a52babb9f7 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Thu, 18 Sep 2014 21:16:17 -0700 Subject: Fix XML rendering regression. --- core/DataTable/Renderer/Xml.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/DataTable/Renderer/Xml.php b/core/DataTable/Renderer/Xml.php index 93c800fafa..7cd10d9367 100644 --- a/core/DataTable/Renderer/Xml.php +++ b/core/DataTable/Renderer/Xml.php @@ -154,16 +154,16 @@ class Xml extends Renderer foreach ($array as $key => $value) { // based on the type of array & the key, determine how this node will look if ($isAssociativeArray) { - if (!self::isValidXmlTagName($key)) { - $prefix = ""; - $suffix = ""; - $emptyNode = ""; - } else if (strpos($key, '=') !== false) { + if (strpos($key, '=') !== false) { list($keyAttributeName, $key) = explode('=', $key, 2); $prefix = ""; $suffix = ""; $emptyNode = ""; + } else if (!self::isValidXmlTagName($key)) { + $prefix = ""; + $suffix = ""; + $emptyNode = ""; } else { $prefix = "<$key>"; $suffix = ""; -- cgit v1.2.3 From 1ad956d65c6eb49c3d6b192d0adac9ce33aa0989 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 19 Sep 2014 10:03:27 -0700 Subject: Add public Report::isSubtableReport() method so it can be used in closure on PHP 5.3. --- core/Plugin/Report.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/Plugin/Report.php b/core/Plugin/Report.php index a907b0f709..6d950babd2 100644 --- a/core/Plugin/Report.php +++ b/core/Plugin/Report.php @@ -601,6 +601,16 @@ class Report return $subtableReport->getDimension(); } + /** + * Returns true if the report is for another report's subtable, false if otherwise. + * + * @return bool + */ + public function isSubtableReport() + { + return $this->isSubtableReport; + } + /** * Fetches the report represented by this instance. * @@ -722,7 +732,7 @@ class Report public static function getForDimension(Dimension $dimension) { return ComponentFactory::getComponentIf(__CLASS__, $dimension->getModule(), function (Report $report) use ($dimension) { - return !$report->isSubtableReport + return !$report->isSubtableReport() && $report->getDimension() && $report->getDimension()->getId() == $dimension->getId(); }); -- cgit v1.2.3 From 71dfe38e139e860ea460e0a98fa09c30d9dcbedb Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 19 Sep 2014 10:42:50 -0700 Subject: Make sure PivotByDimension respects original segment query parameter when fetching intersected tables by segment. --- core/DataTable/Filter/PivotByDimension.php | 6 ++++ .../Core/DataTable/Filter/PivotByDimensionTest.php | 32 ++++++++++++++++++++++ .../PHPUnit/Integration/PivotByQueryParamTest.php | 13 +++++++++ ...ntUsedInRequest__Referrers.getKeywords_week.xml | 11 ++++++++ 4 files changed, 62 insertions(+) create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml diff --git a/core/DataTable/Filter/PivotByDimension.php b/core/DataTable/Filter/PivotByDimension.php index 1d0a7267f8..867e3ec04b 100644 --- a/core/DataTable/Filter/PivotByDimension.php +++ b/core/DataTable/Filter/PivotByDimension.php @@ -300,6 +300,12 @@ class PivotByDimension extends BaseFilter { $segmentStr = $this->thisReportDimensionSegment->getSegment() . "==" . urlencode($segmentValue); + // TODO: segment + report API method query params should be stored in DataTable metadata so we don't have to access it here + $originalSegment = Common::getRequestVar('segment', false); + if (!empty($originalSegment)) { + $segmentStr = $originalSegment . ';' . $segmentStr; + } + Log::debug("PivotByDimension: Fetching intersected with segment '%s'", $segmentStr); $params = array('segment' => $segmentStr) + $this->getRequestParamOverride($table); diff --git a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php index 790c3cb6fe..976c4dee48 100644 --- a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php +++ b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php @@ -29,6 +29,14 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase */ private $segmentTableCount; + /** + * Segment query params used to fetch intersected tables in PivotByDimension filter. Captured by mock + * API\Proxy class. + * + * @var array + */ + public $segmentUsedToGetIntersected = array(); + public function setUp() { $self = $this; @@ -38,6 +46,8 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase if ($className == "\\Piwik\\Plugins\\UserCountry\\API" && $methodName == 'getCity' ) { + $self->segmentUsedToGetIntersected[] = $parameters['segment']; + return $self->getSegmentTable(); } else { throw new Exception("Unknown API request: $className::$methodName."); @@ -161,6 +171,9 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $pivotFilter = new PivotByDimension($table, "Referrers.getKeywords", "UserCountry.City", 'nb_visits'); $pivotFilter->filter($table); + $expectedSegmentParams = array('referrerKeyword==row+1', 'referrerKeyword==row+2', 'referrerKeyword==row+3'); + $this->assertEquals($expectedSegmentParams, $this->segmentUsedToGetIntersected); + $expectedRows = array( array('label' => 'row 1', 'col 0' => 2, 'col 1' => false, 'col 2' => false), array('label' => 'row 2', 'col 0' => 2, 'col 1' => 4, 'col 2' => false), @@ -169,6 +182,25 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $this->assertTableRowsEquals($expectedRows, $table); } + public function testFilterUsesCorrectSegmentWhenPivotingSegmentedReport() + { + PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + + $table = $this->getTableToFilter(true); + + $_GET['segment'] = 'asegment==value'; + + $pivotFilter = new PivotByDimension($table, "Referrers.getKeywords", "UserCountry.City", 'nb_visits'); + $pivotFilter->filter($table); + + $expectedSegmentParams = array( + 'asegment==value;referrerKeyword==row+1', + 'asegment==value;referrerKeyword==row+2', + 'asegment==value;referrerKeyword==row+3' + ); + $this->assertEquals($expectedSegmentParams, $this->segmentUsedToGetIntersected); + } + public function testFilterCorrectlyCreatesPivotTableWhenPivotMetricDoesNotExistInTable() { PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); diff --git a/tests/PHPUnit/Integration/PivotByQueryParamTest.php b/tests/PHPUnit/Integration/PivotByQueryParamTest.php index a59ff9d1f3..2ca32cada2 100644 --- a/tests/PHPUnit/Integration/PivotByQueryParamTest.php +++ b/tests/PHPUnit/Integration/PivotByQueryParamTest.php @@ -67,6 +67,19 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } + public function testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest() + { + $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( + 'idSite' => self::$fixture->idSite, + 'date' => Date::factory(self::$fixture->dateTime)->toString(), + 'period' => 'week', + 'segment' => 'browserCode==FF', + 'pivotBy' => 'UserCountry.City', + 'pivotByColumn' => 'nb_visits', + 'pivotByColumnLimit' => -1 + )); + } + public function testPivotByParamPlaysNiceWithOtherQueryParams() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..f4cc044f57 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml @@ -0,0 +1,11 @@ + + + + that search term + 2 + + + this search term + 2 + + \ No newline at end of file -- cgit v1.2.3 From 1eefab51d457ba7759bd050c816bdf594bb97b6a Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 19 Sep 2014 10:46:34 -0700 Subject: Fix another closure access error in PHP 5.3 for tests. --- tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php index 976c4dee48..4e3bcb63c8 100644 --- a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php +++ b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php @@ -358,7 +358,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase return $table; } - private function getSegmentTable() + public function getSegmentTable() { ++$this->segmentTableCount; -- cgit v1.2.3 From 3d9043017c759ed3777b5368dbcbf0bcf873f9a1 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 19 Sep 2014 10:54:06 -0700 Subject: Cleaning up PivotByDimensionTest a bit. --- .../Core/DataTable/Filter/PivotByDimensionTest.php | 36 ++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php index 4e3bcb63c8..d711d6655c 100644 --- a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php +++ b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php @@ -72,7 +72,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase */ public function testConstructionFailsWhenReportHasNoSubtableAndSegmentFetchingIsDisabled() { - PluginManager::getInstance()->loadPlugins(array('ExampleReport', 'UserCountry')); + $this->loadPlugins('ExampleReport', 'UserCountry'); new PivotByDimension(new DataTable(), "ExampleReport.GetExampleReport", "UserCountry.City", 'nb_visits', $columnLimit = -1, $enableFetchBySegment = false); } @@ -83,7 +83,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase */ public function testConstructionFailsWhenDimensionIsNotSubtableAndSegmentFetchingIsDisabled() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry')); + $this->loadPlugins('Referrers', 'UserCountry'); new PivotByDimension(new DataTable(), "Referrers.getKeywords", "UserCountry.City", "nb_visits", $columnLimit = -1, $enableFetchBySegment = false); } @@ -94,7 +94,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase */ public function testConstructionFailsWhenDimensionIsNotSubtableAndSegmentFetchingIsEnabledButThereIsNoSegment() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserSettings')); + $this->loadPlugins('Referrers', 'UserSettings'); new PivotByDimension(new DataTable(), "UserSettings.getBrowserType", "Referrers.Keyword", "nb_visits"); } @@ -105,7 +105,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase */ public function testConstructionFailsWhenDimensionDoesNotExist() { - PluginManager::getInstance()->loadPlugins(array('ExampleReport', 'ExampleTracker')); + $this->loadPlugins('ExampleReport', 'ExampleTracker'); new PivotByDimension(new DataTable(), "ExampleReport.GetExampleReport", "ExampleTracker.InvalidDimension", 'nb_visits'); } @@ -116,7 +116,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase */ public function testConstructionFailsWhenThereIsNoReportForADimension() { - PluginManager::getInstance()->loadPlugins(array('ExampleReport', 'ExampleTracker')); + $this->loadPlugins('ExampleReport', 'ExampleTracker'); new PivotByDimension(new DataTable(), "ExampleReport.GetExampleReport", "ExampleTracker.ExampleDimension", "nb_visits"); } @@ -127,27 +127,26 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase */ public function testConstructionFailsWhenSpecifiedReportIsNotValid() { - PluginManager::getInstance()->loadPlugins(array('ExampleReport', 'Referrers')); + $this->loadPlugins('ExampleReport', 'Referrers'); new PivotByDimension(new DataTable(), "ExampleReport.InvalidReport", "Referrers.Keyword", "nb_visits"); } public function testFilterReturnsEmptyResultWhenTableToFilterIsEmpty() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); $table = new DataTable(); $pivotFilter = new PivotByDimension($table, "Referrers.getKeywords", "Referrers.SearchEngine", 'nb_visits'); $pivotFilter->filter($table); - $expectedRows = array(); - $this->assertEquals($expectedRows, $table->getRows()); + $this->assertEquals(array(), $table->getRows()); } public function testFilterCorrectlyCreatesPivotTableUsingSubtableReport() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); $table = $this->getTableToFilter(true); @@ -164,7 +163,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase public function testFilterCorrectlyCreatesPivotTableUsingSegment() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); $table = $this->getTableToFilter(true); @@ -184,7 +183,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase public function testFilterUsesCorrectSegmentWhenPivotingSegmentedReport() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); $table = $this->getTableToFilter(true); @@ -203,7 +202,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase public function testFilterCorrectlyCreatesPivotTableWhenPivotMetricDoesNotExistInTable() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); $table = $this->getTableToFilter(true); @@ -220,7 +219,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase public function testFilterCorrectlyCreatesPivotTableWhenSubtablesHaveNoRows() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); $table = $this->getTableToFilter(false); @@ -238,7 +237,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase public function testFilterCorrectlyDefaultsPivotByColumnWhenNoneProvided() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); $table = $this->getTableToFilter(true); @@ -255,7 +254,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase public function testFilterCorrectlyLimitsTheColumnNumberWhenColumnLimitProvided() { - PluginManager::getInstance()->loadPlugins(array('Referrers', 'UserCountry', 'CustomVariables')); + $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); $table = $this->getTableToFilter(true); @@ -382,4 +381,9 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $this->assertEquals($expectedRows, $actualRows); } + + private function loadPlugins() + { + PluginManager::getInstance()->loadPlugins(func_get_args()); + } } \ No newline at end of file -- cgit v1.2.3 From a318e24f45d158e907085912bf9815d30ec3680e Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 19 Sep 2014 11:07:18 -0700 Subject: Refs #6078, allow default column limit to be specified through INI config. --- config/global.ini.php | 6 ++++++ core/DataTable/Filter/PivotByDimension.php | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/config/global.ini.php b/config/global.ini.php index 2ce4085ab3..0c45bf884d 100644 --- a/config/global.ini.php +++ b/config/global.ini.php @@ -477,6 +477,12 @@ enable_update_communication = 1 ; At present, this is very inefficient, so it is disabled by default. pivot_by_filter_enable_fetch_by_segment = 0 +; This controls the default maximum number of columns to display in a pivot table. Since a pivot table displays +; a table's rows as columns, the number of columns can become very large, which will affect webpage layouts. +; Set to -1 to specify no limit. Note: The pivotByColumnLimit query parameter can be used to override this default +; on a per-request basis; +pivot_by_filter_default_column_limit = 7 + [Tracker] ; Piwik uses first party cookies by default. If set to 1, ; the visit ID cookie will be set on the Piwik server domain as well diff --git a/core/DataTable/Filter/PivotByDimension.php b/core/DataTable/Filter/PivotByDimension.php index 867e3ec04b..902c03f1b5 100644 --- a/core/DataTable/Filter/PivotByDimension.php +++ b/core/DataTable/Filter/PivotByDimension.php @@ -55,8 +55,6 @@ use Piwik\Plugin\Segment; */ class PivotByDimension extends BaseFilter { - const DEFAULT_COLUMN_LIMIT = 7; - /** * The pivot-by Dimension. The metadata in this class is used to determine if we can * pivot the report and used to fetch intersected tables. @@ -157,7 +155,7 @@ class PivotByDimension extends BaseFilter $pivotColumn, $pivotByColumnLimit, $isFetchingBySegmentEnabled); $this->pivotColumn = $pivotColumn; - $this->pivotByColumnLimit = $pivotByColumnLimit ?: self::DEFAULT_COLUMN_LIMIT; + $this->pivotByColumnLimit = $pivotByColumnLimit ?: self::getDefaultColumnLimit(); $this->isFetchingBySegmentEnabled = $isFetchingBySegmentEnabled; $namesToId = Metrics::getMappingFromIdToName(); @@ -456,4 +454,15 @@ class PivotByDimension extends BaseFilter { return Config::getInstance()->General['pivot_by_filter_enable_fetch_by_segment']; } + + /** + * Returns the default maximum number of columns to allow in a pivot table from the INI config. + * Uses the **pivot_by_filter_default_column_limit** INI config option. + * + * @return int + */ + public static function getDefaultColumnLimit() + { + return Config::getInstance()->General['pivot_by_filter_default_column_limit']; + } } \ No newline at end of file -- cgit v1.2.3 From eab821030f3d93181de0c81555dda2a89cedac7a Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 19 Sep 2014 13:56:14 -0700 Subject: Refs #6078, add report metadata for Event subtable reports and make sure pivotBy works w/ Events plugins' secondaryDimension query parameter.. --- plugins/Events/Events.php | 4 ++++ plugins/Events/Reports/GetAction.php | 7 +++++- plugins/Events/Reports/GetActionFromCategoryId.php | 28 ++++++++++++++++++++++ plugins/Events/Reports/GetActionFromNameId.php | 28 ++++++++++++++++++++++ plugins/Events/Reports/GetCategory.php | 7 +++++- plugins/Events/Reports/GetCategoryFromActionId.php | 28 ++++++++++++++++++++++ plugins/Events/Reports/GetCategoryFromNameId.php | 28 ++++++++++++++++++++++ plugins/Events/Reports/GetName.php | 7 +++++- plugins/Events/Reports/GetNameFromActionId.php | 28 ++++++++++++++++++++++ plugins/Events/Reports/GetNameFromCategoryId.php | 28 ++++++++++++++++++++++ 10 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 plugins/Events/Reports/GetActionFromCategoryId.php create mode 100644 plugins/Events/Reports/GetActionFromNameId.php create mode 100644 plugins/Events/Reports/GetCategoryFromActionId.php create mode 100644 plugins/Events/Reports/GetCategoryFromNameId.php create mode 100644 plugins/Events/Reports/GetNameFromActionId.php create mode 100644 plugins/Events/Reports/GetNameFromCategoryId.php diff --git a/plugins/Events/Events.php b/plugins/Events/Events.php index af701bdf37..ad4dab646f 100644 --- a/plugins/Events/Events.php +++ b/plugins/Events/Events.php @@ -10,6 +10,7 @@ namespace Piwik\Plugins\Events; use Piwik\Common; use Piwik\Piwik; +use Piwik\Plugin\Report; use Piwik\Plugin\ViewDataTable; class Events extends \Piwik\Plugin @@ -171,6 +172,9 @@ class Events extends \Piwik\Plugin $view->config->addTranslations($this->getMetricTranslations()); $this->addRelatedReports($view, $secondaryDimension); $this->addTooltipEventValue($view); + + $subtableReport = Report::factory('Events', $view->config->subtable_controller_action); + $view->config->pivot_by_dimension = $subtableReport->getDimension()->getId(); } private function addRelatedReports($view, $secondaryDimension) diff --git a/plugins/Events/Reports/GetAction.php b/plugins/Events/Reports/GetAction.php index 04ed51bd21..4fa80bf4e1 100644 --- a/plugins/Events/Reports/GetAction.php +++ b/plugins/Events/Reports/GetAction.php @@ -8,6 +8,7 @@ */ namespace Piwik\Plugins\Events\Reports; +use Piwik\Common; use Piwik\Piwik; use Piwik\Plugins\Events\Columns\EventAction; @@ -20,7 +21,11 @@ class GetAction extends Base $this->name = Piwik::translate('Events_EventActions'); $this->documentation = ''; // TODO $this->metrics = array('nb_events', 'sum_event_value', 'min_event_value', 'max_event_value', 'avg_event_value', 'nb_events_with_value'); - $this->actionToLoadSubTables = 'getNameFromActionId'; + if (Common::getRequestVar('secondaryDimension', false) == 'eventCategory') { + $this->actionToLoadSubTables = 'getCategoryFromNameId'; + } else { + $this->actionToLoadSubTables = 'getNameFromActionId'; + } $this->order = 1; $this->widgetTitle = 'Events_EventActions'; } diff --git a/plugins/Events/Reports/GetActionFromCategoryId.php b/plugins/Events/Reports/GetActionFromCategoryId.php new file mode 100644 index 0000000000..e5de6af9ca --- /dev/null +++ b/plugins/Events/Reports/GetActionFromCategoryId.php @@ -0,0 +1,28 @@ +category = 'Events_Events'; + $this->processedMetrics = false; + $this->dimension = new EventAction(); + $this->name = Piwik::translate('Events_EventActions'); + $this->isSubtableReport = true; + } +} \ No newline at end of file diff --git a/plugins/Events/Reports/GetActionFromNameId.php b/plugins/Events/Reports/GetActionFromNameId.php new file mode 100644 index 0000000000..55bd628459 --- /dev/null +++ b/plugins/Events/Reports/GetActionFromNameId.php @@ -0,0 +1,28 @@ +category = 'Events_Events'; + $this->processedMetrics = false; + $this->dimension = new EventAction(); + $this->name = Piwik::translate('Events_EventActions'); + $this->isSubtableReport = true; + } +} \ No newline at end of file diff --git a/plugins/Events/Reports/GetCategory.php b/plugins/Events/Reports/GetCategory.php index a901e5c32c..9d3817cd71 100644 --- a/plugins/Events/Reports/GetCategory.php +++ b/plugins/Events/Reports/GetCategory.php @@ -8,6 +8,7 @@ */ namespace Piwik\Plugins\Events\Reports; +use Piwik\Common; use Piwik\Piwik; use Piwik\Plugins\Events\Columns\EventCategory; @@ -20,7 +21,11 @@ class GetCategory extends Base $this->name = Piwik::translate('Events_EventCategories'); $this->documentation = ''; // TODO $this->metrics = array('nb_events', 'sum_event_value', 'min_event_value', 'max_event_value', 'avg_event_value', 'nb_events_with_value'); - $this->actionToLoadSubTables = 'getActionFromCategoryId'; + if (Common::getRequestVar('secondaryDimension', false) == 'eventName') { + $this->actionToLoadSubTables = 'getNameFromCategoryId'; + } else { + $this->actionToLoadSubTables = 'getActionFromCategoryId'; + } $this->order = 0; $this->widgetTitle = 'Events_EventCategories'; } diff --git a/plugins/Events/Reports/GetCategoryFromActionId.php b/plugins/Events/Reports/GetCategoryFromActionId.php new file mode 100644 index 0000000000..51f5f6918d --- /dev/null +++ b/plugins/Events/Reports/GetCategoryFromActionId.php @@ -0,0 +1,28 @@ +category = 'Events_Events'; + $this->processedMetrics = false; + $this->dimension = new EventCategory(); + $this->name = Piwik::translate('Events_EventCategories'); + $this->isSubtableReport = true; + } +} \ No newline at end of file diff --git a/plugins/Events/Reports/GetCategoryFromNameId.php b/plugins/Events/Reports/GetCategoryFromNameId.php new file mode 100644 index 0000000000..4806c97d0f --- /dev/null +++ b/plugins/Events/Reports/GetCategoryFromNameId.php @@ -0,0 +1,28 @@ +category = 'Events_Events'; + $this->processedMetrics = false; + $this->dimension = new EventCategory(); + $this->name = Piwik::translate('Events_EventCategories'); + $this->isSubtableReport = true; + } +} \ No newline at end of file diff --git a/plugins/Events/Reports/GetName.php b/plugins/Events/Reports/GetName.php index 886e992085..1f97eb7099 100644 --- a/plugins/Events/Reports/GetName.php +++ b/plugins/Events/Reports/GetName.php @@ -8,6 +8,7 @@ */ namespace Piwik\Plugins\Events\Reports; +use Piwik\Common; use Piwik\Piwik; use Piwik\Plugins\Events\Columns\EventName; @@ -20,7 +21,11 @@ class GetName extends Base $this->name = Piwik::translate('Events_EventNames'); $this->documentation = ''; // TODO $this->metrics = array('nb_events', 'sum_event_value', 'min_event_value', 'max_event_value', 'avg_event_value', 'nb_events_with_value'); - $this->actionToLoadSubTables = 'getActionFromNameId'; + if (Common::getRequestVar('secondaryDimension', false) == 'eventCategory') { + $this->actionToLoadSubTables = 'getCategoryFromNameId'; + } else { + $this->actionToLoadSubTables = 'getActionFromNameId'; + } $this->order = 2; $this->widgetTitle = 'Events_EventNames'; } diff --git a/plugins/Events/Reports/GetNameFromActionId.php b/plugins/Events/Reports/GetNameFromActionId.php new file mode 100644 index 0000000000..7b4899b672 --- /dev/null +++ b/plugins/Events/Reports/GetNameFromActionId.php @@ -0,0 +1,28 @@ +category = 'Events_Events'; + $this->processedMetrics = false; + $this->dimension = new EventName(); + $this->name = Piwik::translate('Events_Names'); + $this->isSubtableReport = true; + } +} \ No newline at end of file diff --git a/plugins/Events/Reports/GetNameFromCategoryId.php b/plugins/Events/Reports/GetNameFromCategoryId.php new file mode 100644 index 0000000000..d1f43f7931 --- /dev/null +++ b/plugins/Events/Reports/GetNameFromCategoryId.php @@ -0,0 +1,28 @@ +category = 'Events_Events'; + $this->processedMetrics = false; + $this->dimension = new EventName(); + $this->name = Piwik::translate('Events_EventNames'); + $this->isSubtableReport = true; + } +} \ No newline at end of file -- cgit v1.2.3 From b5196b8f3d97e031566084720ae6dd5e42f0e115 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 19 Sep 2014 13:56:36 -0700 Subject: Refs #6078, remove pivotBy param when switching between related reports. --- plugins/CoreHome/javascripts/dataTable.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 11c1f79e2d..5bcb96d5a6 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -1643,6 +1643,8 @@ $.extend(DataTable.prototype, UIControl.prototype, { self.param[key] = decodeURIComponent(newParams[key]); } + delete self.param.pivotBy; + // do ajax request self.reloadAjaxDataTable(true, function (newReport) { var newDomElem = self.dataTableLoaded(newReport, self.workingDivId); -- cgit v1.2.3 From cc74e8efef3f821f4f23742ccfee018b2bcbe6d8 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 19 Sep 2014 14:16:01 -0700 Subject: Refs #6078, allow plugins to set what metric gets displayed in pivot tables of specific reports and use in Events to display nb_events. Also do not set columns_to_display in Events plugin if table is pivoted. --- core/ViewDataTable/Config.php | 8 +++++++- plugins/CoreHome/javascripts/dataTable.js | 11 ++++++++++- plugins/Events/Events.php | 7 ++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/core/ViewDataTable/Config.php b/core/ViewDataTable/Config.php index 0389c213fb..a2be3f6c96 100644 --- a/core/ViewDataTable/Config.php +++ b/core/ViewDataTable/Config.php @@ -86,7 +86,8 @@ class Config */ public $clientSideProperties = array( 'show_limit_control', - 'pivot_by_dimension' + 'pivot_by_dimension', + 'pivot_by_column' ); /** @@ -200,6 +201,11 @@ class Config */ public $pivot_by_dimension; + /** + * The column to display in pivot tables. Defaults to the first non-label column if not specified. + */ + public $pivot_by_column = false; + /** * Controls whether the footer icon that allows users to switch to the 'normal' DataTable view * is shown. diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 5bcb96d5a6..1c44546803 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -156,7 +156,8 @@ $.extend(DataTable.prototype, UIControl.prototype, { 'flat', 'include_aggregate_rows', 'totalRows', - 'pivotBy' + 'pivotBy', + 'pivotByColumn' ]; for (var key = 0; key < filters.length; key++) { @@ -1092,6 +1093,9 @@ $.extend(DataTable.prototype, UIControl.prototype, { } if (self.param.pivotBy) { str += '&pivotBy=' + self.param.pivotBy; + if (self.props.pivot_by_column) { + str += '&pivotByColumn=' + self.props.pivot_by_column; + } } if (format == 'CSV' || format == 'TSV' || format == 'RSS') { str += '&translateColumnNames=1&language=' + piwik.language; @@ -1267,8 +1271,12 @@ $.extend(DataTable.prototype, UIControl.prototype, { .click(generateClickCallback('pivotBy', null, function () { if (self.param.pivotBy) { self.param.pivotBy = ''; + self.param.pivotByColumn = ''; } else { self.param.pivotBy = self.props.pivot_by_dimension; + if (self.props.pivot_by_column) { + self.param.pivotByColumn = self.props.pivot_by_column; + } } })); @@ -1644,6 +1652,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { } delete self.param.pivotBy; + delete self.param.pivotByColumn; // do ajax request self.reloadAjaxDataTable(true, function (newReport) { diff --git a/plugins/Events/Events.php b/plugins/Events/Events.php index ad4dab646f..3d335bd229 100644 --- a/plugins/Events/Events.php +++ b/plugins/Events/Events.php @@ -162,7 +162,11 @@ class Events extends \Piwik\Plugin $secondaryDimension = $this->getSecondaryDimensionFromRequest(); $view->config->subtable_controller_action = API::getInstance()->getActionToLoadSubtables($apiMethod, $secondaryDimension); - $view->config->columns_to_display = array('label', 'nb_events', 'sum_event_value'); + + if (Common::getRequestVar('pivotBy', false) === false) { + $view->config->columns_to_display = array('label', 'nb_events', 'sum_event_value'); + } + $view->config->show_flatten_table = true; $view->config->show_table_all_columns = false; $view->requestConfig->filter_sort_column = 'nb_events'; @@ -175,6 +179,7 @@ class Events extends \Piwik\Plugin $subtableReport = Report::factory('Events', $view->config->subtable_controller_action); $view->config->pivot_by_dimension = $subtableReport->getDimension()->getId(); + $view->config->pivot_by_column = 'nb_events'; } private function addRelatedReports($view, $secondaryDimension) -- cgit v1.2.3 From 88e6f0bbdf859e24be18f7cf6ac8f5c9df61fcc7 Mon Sep 17 00:00:00 2001 From: Matthieu Aubry Date: Sat, 20 Sep 2014 21:50:27 +1200 Subject: call clearQueuedFilters() --- core/DataTable.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/DataTable.php b/core/DataTable.php index 5895e51f2a..bc5a57cff6 100644 --- a/core/DataTable.php +++ b/core/DataTable.php @@ -452,7 +452,7 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess foreach ($this->queuedFilters as $filter) { $this->filter($filter['className'], $filter['parameters']); } - $this->queuedFilters = array(); + $this->clearQueuedFilters(); } /** @@ -1670,4 +1670,4 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess { $this->deleteRow($offset); } -} \ No newline at end of file +} -- cgit v1.2.3 From a173c6debcf78c0588317182f5bda70cd1e6922d Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 12:21:17 -0700 Subject: Refs #6078, fix bug where reloading report does not persist pivot and where undoing a saved pivot does nothing. --- core/ViewDataTable/Request.php | 5 ++++- core/ViewDataTable/RequestConfig.php | 33 +++++++++++++++++++++++++++++-- plugins/CoreHome/javascripts/dataTable.js | 4 ++-- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/core/ViewDataTable/Request.php b/core/ViewDataTable/Request.php index 324803aa91..9493889944 100644 --- a/core/ViewDataTable/Request.php +++ b/core/ViewDataTable/Request.php @@ -74,7 +74,10 @@ class Request 'filter_column', 'filter_pattern', 'flat', - 'expanded' + 'expanded', + 'pivotBy', + 'pivotByColumn', + 'pivotByColumnLimit' ); foreach ($toSetEventually as $varToSet) { diff --git a/core/ViewDataTable/RequestConfig.php b/core/ViewDataTable/RequestConfig.php index ad77df8824..102fa68018 100644 --- a/core/ViewDataTable/RequestConfig.php +++ b/core/ViewDataTable/RequestConfig.php @@ -90,7 +90,10 @@ class RequestConfig 'filter_column', 'filter_offset', 'flat', - 'expanded' + 'expanded', + 'pivotBy', + 'pivotByColumn', + 'pivotByColumnLimit' ); /** @@ -108,7 +111,10 @@ class RequestConfig 'disable_generic_filters', 'disable_queued_filters', 'flat', - 'expanded' + 'expanded', + 'pivotBy', + 'pivotByColumn', + 'pivotByColumnLimit' ); /** @@ -232,6 +238,29 @@ class RequestConfig */ public $idSubtable = false; + /** + * Dimension ID to pivot by. See {@link Piwik\DataTable\Filter\PivotByDimension} for more info. + * + * @var string + */ + public $pivotBy = false; + + /** + * The column to display in a pivot table, eg, `'nb_visits'`. See {@link Piwik\DataTable\Filter\PivotByDimension} + * for more info. + * + * @var string + */ + public $pivotByColumn = false; + + /** + * The maximum number of columns to display in a pivot table. See {@link Piwik\DataTable\Filter\PivotByDimension} + * for more info. + * + * @var int + */ + public $pivotByColumnLimit = false; + public function getProperties() { return get_object_vars($this); diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 1c44546803..e316804394 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -1270,8 +1270,8 @@ $.extend(DataTable.prototype, UIControl.prototype, { }) .click(generateClickCallback('pivotBy', null, function () { if (self.param.pivotBy) { - self.param.pivotBy = ''; - self.param.pivotByColumn = ''; + self.param.pivotBy = '0'; // set to '0' so it will be sent in the request and override the saved param + self.param.pivotByColumn = '0'; } else { self.param.pivotBy = self.props.pivot_by_dimension; if (self.props.pivot_by_column) { -- cgit v1.2.3 From 07fce41ea908115d4d2aa152b9d1fb2e387be9ab Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 12:27:34 -0700 Subject: Refs #6078, #5355 only display expand/contract tooltip if row has subtable. --- plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig b/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig index 50d4981bb2..13c153f89c 100644 --- a/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig +++ b/plugins/CoreVisualizations/templates/_dataTableViz_htmlTable.twig @@ -29,7 +29,7 @@ {% if showRow %} + {% if rowHasSubtable %}title="{{ 'CoreHome_ClickRowToExpandOrContract'|translate }}"{% endif %}> {% for column in properties.columns_to_display %} {% include "@CoreHome/_dataTableCell.twig" with properties %} -- cgit v1.2.3 From 7524b71837e7d693bfd34296f7f5a692a0920ae1 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 12:32:18 -0700 Subject: Refs #6078, make sure cog icon is highlighted when table is pivotted. --- plugins/CoreHome/javascripts/dataTable.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index e316804394..cf7f31b56c 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -1262,8 +1262,11 @@ $.extend(DataTable.prototype, UIControl.prototype, { // handle pivot by $('.dataTablePivotBySubtable', domElem) .each(function () { - if (self.param.pivotBy) { + if (self.param.pivotBy + && self.param.pivotBy != '0' + ) { $(this).html(getText('CoreHome_UndoPivotBySubtable', true)); + iconHighlighted = true; } else { $(this).html(getText('CoreHome_PivotBySubtable')); } -- cgit v1.2.3 From 74dad072421f2661c0c096aebb338bbbfef1dc13 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 12:38:12 -0700 Subject: Refs #6078, make pivot option use the pivot by dimension's name. --- core/ViewDataTable/Config.php | 13 +++++++++++-- plugins/CoreHome/javascripts/dataTable.js | 3 ++- plugins/CoreHome/lang/en.json | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/ViewDataTable/Config.php b/core/ViewDataTable/Config.php index a2be3f6c96..e9d6ee54d2 100644 --- a/core/ViewDataTable/Config.php +++ b/core/ViewDataTable/Config.php @@ -87,7 +87,8 @@ class Config public $clientSideProperties = array( 'show_limit_control', 'pivot_by_dimension', - 'pivot_by_column' + 'pivot_by_column', + 'pivot_dimension_name' ); /** @@ -206,6 +207,11 @@ class Config */ public $pivot_by_column = false; + /** + * The human readable name of the pivot dimension. + */ + public $pivot_dimension_name = false; + /** * Controls whether the footer icon that allows users to switch to the 'normal' DataTable view * is shown. @@ -670,7 +676,10 @@ class Config $this->show_pivot_by_subtable = PivotByDimension::isPivotingReportBySubtableSupported($report); $subtableDimension = $report->getSubtableDimension(); - $this->pivot_by_dimension = $subtableDimension ? $subtableDimension->getId() : false; + if (!empty($subtableDimension)) { + $this->pivot_by_dimension = $subtableDimension->getId(); + $this->pivot_dimension_name = $subtableDimension->getName(); + } } } } diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index cf7f31b56c..e49228a6ca 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -1268,7 +1268,8 @@ $.extend(DataTable.prototype, UIControl.prototype, { $(this).html(getText('CoreHome_UndoPivotBySubtable', true)); iconHighlighted = true; } else { - $(this).html(getText('CoreHome_PivotBySubtable')); + var optionLabelText = getText('CoreHome_PivotBySubtable').replace('%s', self.props.pivot_dimension_name); + $(this).html(optionLabelText); } }) .click(generateClickCallback('pivotBy', null, function () { diff --git a/plugins/CoreHome/lang/en.json b/plugins/CoreHome/lang/en.json index 71ed8e4d09..bcaf3af402 100644 --- a/plugins/CoreHome/lang/en.json +++ b/plugins/CoreHome/lang/en.json @@ -61,6 +61,6 @@ "YouAreUsingTheLatestVersion": "You are using the latest version of Piwik!", "ClickRowToExpandOrContract": "Click this row to expand or contract the subtable.", "UndoPivotBySubtable": "This report has been pivoted %s Undo pivot", - "PivotBySubtable": "This report is not pivoted %s Pivot by subtable" + "PivotBySubtable": "This report is not pivoted %s Pivot by %s" } } \ No newline at end of file -- cgit v1.2.3 From fbb33038d9674ac01b0f9b80500b669b68f21637 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 12:47:25 -0700 Subject: Refs #6078, do not pivot table when getting siteSummary data. --- plugins/CoreVisualizations/Visualizations/HtmlTable.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable.php b/plugins/CoreVisualizations/Visualizations/HtmlTable.php index c14eb33863..63cfebe5eb 100644 --- a/plugins/CoreVisualizations/Visualizations/HtmlTable.php +++ b/plugins/CoreVisualizations/Visualizations/HtmlTable.php @@ -64,7 +64,8 @@ class HtmlTable extends Visualization 'filter_offset' => 0, 'period' => $period, 'showColumns' => implode(',', $this->config->columns_to_display), - 'columns' => implode(',', $this->config->columns_to_display) + 'columns' => implode(',', $this->config->columns_to_display), + 'pivotBy' => '' )); $dataTable = $request->process(); -- cgit v1.2.3 From b1968947d69b0da7bfc8c2eea6c8311c3b6be433 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 12:48:36 -0700 Subject: Refs #6078, change default maximum column limit to 10. --- config/global.ini.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/global.ini.php b/config/global.ini.php index 0c45bf884d..98ab17f30b 100644 --- a/config/global.ini.php +++ b/config/global.ini.php @@ -481,7 +481,7 @@ pivot_by_filter_enable_fetch_by_segment = 0 ; a table's rows as columns, the number of columns can become very large, which will affect webpage layouts. ; Set to -1 to specify no limit. Note: The pivotByColumnLimit query parameter can be used to override this default ; on a per-request basis; -pivot_by_filter_default_column_limit = 7 +pivot_by_filter_default_column_limit = 10 [Tracker] ; Piwik uses first party cookies by default. If set to 1, -- cgit v1.2.3 From 8d0205e32a430d4bb028ec14877ff7a7d7b5d22e Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 13:14:13 -0700 Subject: Refs #6078, order pivot table columns by sum, descending and aggregate cut-off columns into 'Others' column. --- core/DataTable/Filter/PivotByDimension.php | 47 +++++--- ...ithDataTableMaps__Referrers.getKeywords_day.xml | 12 +- ...therQueryParams__Referrers.getKeywords_week.xml | 12 +- ...hColumnLimiting__Referrers.getKeywords_week.xml | 12 +- ...ksWithCsvOutput__Referrers.getKeywords_week.csv | Bin 440 -> 440 bytes ...WithJsonOutput__Referrers.getKeywords_week.json | 2 +- ...oseSubtableIsSelf__Actions.getPageUrls_week.xml | 130 ++++++++++----------- ...rrectPivotTable__Referrers.getKeywords_week.xml | 12 +- ...rchyIsNotLoaded__Referrers.getKeywords_week.xml | 48 ++++---- ...rrectPivotTable__Referrers.getKeywords_week.xml | 48 ++++---- 10 files changed, 168 insertions(+), 155 deletions(-) diff --git a/core/DataTable/Filter/PivotByDimension.php b/core/DataTable/Filter/PivotByDimension.php index 902c03f1b5..ba4f0220f6 100644 --- a/core/DataTable/Filter/PivotByDimension.php +++ b/core/DataTable/Filter/PivotByDimension.php @@ -17,6 +17,7 @@ use Piwik\DataTable\BaseFilter; use Piwik\DataTable\Row; use Piwik\Log; use Piwik\Metrics; +use Piwik\Piwik; use Piwik\Plugin\Report; use Piwik\Plugin\Segment; @@ -211,22 +212,10 @@ class PivotByDimension extends BaseFilter Log::debug("PivotByDimension::%s: pivoted columns set: %s", __FUNCTION__, $columnSet); - // limit columns - if ($this->pivotByColumnLimit > 0) { - arsort($columnSet); - $columnSet = array_slice($columnSet, 0, $this->pivotByColumnLimit, $preserveKeys = true); - } - - // sort columns by name (to ensure deterministic ordering) - ksort($columnSet); + $others = Piwik::translate('General_Others'); + $defaultRow = $this->getPivotTableDefaultRowFromColumnSummary($columnSet, $others); - // remove column sums from array so it can be used as a default row - $columnSet = array_map(function () { return false; }, $columnSet); - - // make sure label column is first - $columnSet = array_merge(array('label' => false), $columnSet); - - Log::debug("PivotByDimension::%s: processed pivoted columns: %s", __FUNCTION__, $columnSet); + Log::debug("PivotByDimension::%s: processed pivoted columns: %s", __FUNCTION__, $defaultRow); // post process pivoted datatable foreach ($table->getRows() as $row) { @@ -234,11 +223,13 @@ class PivotByDimension extends BaseFilter $row->removeSubtable(); $row->deleteMetadata('idsubdatatable_in_db'); - // use default row to ensure column ordering and add missing columns - $orderedColumns = $columnSet; + // use default row to ensure column ordering and add missing columns/aggregate cut-off columns + $orderedColumns = $defaultRow; foreach ($row->getColumns() as $name => $value) { if (isset($orderedColumns[$name])) { $orderedColumns[$name] = $value; + } else { + $orderedColumns[$others] += $value; } } $row->setColumns($orderedColumns); @@ -432,6 +423,28 @@ class PivotByDimension extends BaseFilter return $params; } + private function getPivotTableDefaultRowFromColumnSummary($columnSet, $othersRowLabel) + { + // sort columns by sum (to ensure deterministic ordering) + arsort($columnSet); + + // limit columns if necessary (adding aggregate Others column at end) + if ($this->pivotByColumnLimit > 0 + && count($columnSet) > $this->pivotByColumnLimit + ) { + $columnSet = array_slice($columnSet, 0, $this->pivotByColumnLimit - 1, $preserveKeys = true); + $columnSet[$othersRowLabel] = 0; + } + + // remove column sums from array so it can be used as a default row + $columnSet = array_map(function () { return false; }, $columnSet); + + // make sure label column is first + $columnSet = array_merge(array('label' => false), $columnSet); + + return $columnSet; + } + /** * Returns true if pivoting by subtable is supported for a report. Will return true if the report * has a subtable dimension and if the subtable dimension is different than the report's dimension. diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml index a60b9519fb..744fcf397e 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml @@ -6,39 +6,39 @@ this search term - 2 0 1 + 2 search term 2 - 0 0 2 + 0 search term 3 - 0 2 0 + 0 search term 4 - 0 2 0 + 0 that search term - 2 0 0 + 2 search term 1 - 0 0 1 + 0 diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml index 777020b15e..05553ef4f8 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml @@ -2,32 +2,32 @@ - 0 1 + 0 - 0 0 + 0 - 0 1 + 0 - 1 0 + 1 - 0 1 + 0 - 1 0 + 1 \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml index 70bcfeed7d..4635e78f76 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml @@ -3,31 +3,31 @@ this search term 0 - 1 + 3 search term 2 0 - 2 + 2 search term 3 2 - 0 + 0 search term 4 2 - 0 + 0 that search term 0 - 0 + 2 search term 1 0 - 1 + 1 \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv index 9b91feb5ee..0536708ea8 100644 Binary files a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv and b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv differ diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json index 3ffebb1d65..9b82ca037a 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json @@ -1 +1 @@ -[{"label":"this search term","Melbourne, Victoria, Australia":2,"Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":1},{"label":"search term 2","Melbourne, Victoria, Australia":false,"Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":2},{"label":"search term 3","Melbourne, Victoria, Australia":false,"Toronto, Ontario, Canada":2,"Yokohama, Kanagawa, Japan":false},{"label":"search term 4","Melbourne, Victoria, Australia":false,"Toronto, Ontario, Canada":2,"Yokohama, Kanagawa, Japan":false},{"label":"that search term","Melbourne, Victoria, Australia":2,"Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":false},{"label":"search term 1","Melbourne, Victoria, Australia":false,"Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":1}] \ No newline at end of file +[{"label":"this search term","Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":1,"Melbourne, Victoria, Australia":2},{"label":"search term 2","Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":2,"Melbourne, Victoria, Australia":false},{"label":"search term 3","Toronto, Ontario, Canada":2,"Yokohama, Kanagawa, Japan":false,"Melbourne, Victoria, Australia":false},{"label":"search term 4","Toronto, Ontario, Canada":2,"Yokohama, Kanagawa, Japan":false,"Melbourne, Victoria, Australia":false},{"label":"that search term","Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":false,"Melbourne, Victoria, Australia":2},{"label":"search term 1","Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":1,"Melbourne, Victoria, Australia":false}] \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml index 45bd7630ea..5697f732c4 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml @@ -2,122 +2,122 @@ 0 - 1 - 1 - 0 - 0 - 0 - 0 + 1 0 + 0 + 0 + 0 0 0 - 0 - 0 0 - 1 + 0 + 0 + 0 + 0 1 + 1 + 1 0 0 - 0 - 0 0 - 0 - 1 + 0 + 0 + 1 1 - 0 - 0 - 0 - 0 - 0 - 0 + 1 0 + 0 + 0 + 0 0 0 - 0 - 0 0 - 0 + 0 + 0 + 0 + 0 0 + 0 + 0 1 1 - 1 - 1 0 - 0 - 1 + 1 + 1 + 0 2 - 0 - 0 - 1 - 1 - 0 - 0 + 1 0 + 0 + 0 + 1 0 0 - 0 - 0 0 - 0 + 0 + 0 + 1 + 1 0 + 0 + 0 0 0 - 0 - 0 1 - 1 - 1 + 0 + 0 + 0 3 - 0 - 0 - 0 - 0 - 1 - 1 + 1 1 + 1 + 1 + 0 1 0 - 0 - 0 0 - 0 + 0 + 0 + 0 + 0 0 + 0 + 0 0 0 - 0 - 0 0 - 0 - 1 + 0 + 0 + 0 4 - 0 - 0 - 0 - 0 - 0 - 0 + 1 0 + 0 + 0 + 0 0 1 - 1 - 1 1 - 0 + 1 + 1 + 0 + 0 0 + 0 + 0 0 0 - 0 - 0 0 - 0 - 1 + 0 + 0 + 0 \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml index 99086f82e8..c6315c7326 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml @@ -2,38 +2,38 @@ this search term - 2 0 1 + 2 search term 2 - 0 0 2 + 0 search term 3 - 0 2 0 + 0 search term 4 - 0 2 0 + 0 that search term - 2 0 0 + 2 search term 1 - 0 0 1 + 0 \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml index 4c9fe03b6f..1adf9d722a 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml @@ -2,56 +2,56 @@ this search term - 0 - 1 - 0 - 0 1 1 + 1 + 0 + 0 + 0 search term 2 - 1 - 0 - 1 - 0 0 0 + 0 + 0 + 1 + 1 search term 3 - 0 - 1 - 0 - 0 1 0 + 1 + 0 + 0 + 0 search term 4 - 0 - 0 - 0 - 1 0 1 + 0 + 1 + 0 + 0 that search term - 0 - 0 - 0 - 0 1 1 + 0 + 0 + 0 + 0 search term 1 - 0 - 0 - 0 - 1 0 0 + 0 + 1 + 0 + 0 \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml index 4c9fe03b6f..1adf9d722a 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml @@ -2,56 +2,56 @@ this search term - 0 - 1 - 0 - 0 1 1 + 1 + 0 + 0 + 0 search term 2 - 1 - 0 - 1 - 0 0 0 + 0 + 0 + 1 + 1 search term 3 - 0 - 1 - 0 - 0 1 0 + 1 + 0 + 0 + 0 search term 4 - 0 - 0 - 0 - 1 0 1 + 0 + 1 + 0 + 0 that search term - 0 - 0 - 0 - 0 1 1 + 0 + 0 + 0 + 0 search term 1 - 0 - 0 - 0 - 1 0 0 + 0 + 1 + 0 + 0 \ No newline at end of file -- cgit v1.2.3 From 56b798cc1a62e54c9bb10ac7e2ce51e55c192e32 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 13:48:51 -0700 Subject: Refs #6078, make sure visualizations default sort to first non-label column if filter_sort_column is not in columns_to_display and make sure changing pivot status undoes column sort. --- core/Plugin/Visualization.php | 4 ++-- core/ViewDataTable/RequestConfig.php | 12 +++++++++++- plugins/CoreHome/javascripts/dataTable.js | 8 +++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/core/Plugin/Visualization.php b/core/Plugin/Visualization.php index 1c5a7a3bd8..e369dfa05a 100644 --- a/core/Plugin/Visualization.php +++ b/core/Plugin/Visualization.php @@ -286,7 +286,7 @@ class Visualization extends ViewDataTable } if (empty($this->requestConfig->filter_sort_column)) { - $this->requestConfig->setDefaultSort($this->config->columns_to_display, $hasNbUniqVisitors); + $this->requestConfig->setDefaultSort($this->config->columns_to_display, $hasNbUniqVisitors, $columns); } // deal w/ table metadata @@ -312,7 +312,7 @@ class Visualization extends ViewDataTable 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->requestConfig->setDefaultSort($this->config->columns_to_display, $hasNbUniqVisitors, $this->dataTable->getColumns()); } if (!$this->requestConfig->areGenericFiltersDisabled()) { diff --git a/core/ViewDataTable/RequestConfig.php b/core/ViewDataTable/RequestConfig.php index 102fa68018..5ea6b623f4 100644 --- a/core/ViewDataTable/RequestConfig.php +++ b/core/ViewDataTable/RequestConfig.php @@ -292,7 +292,7 @@ class RequestConfig } } - public function setDefaultSort($columnsToDisplay, $hasNbUniqVisitors) + public function setDefaultSort($columnsToDisplay, $hasNbUniqVisitors, $actualColumns) { // default sort order to visits/visitors data if ($hasNbUniqVisitors && in_array('nb_uniq_visitors', $columnsToDisplay)) { @@ -301,6 +301,16 @@ class RequestConfig $this->filter_sort_column = 'nb_visits'; } + // if the default sort column does not exist, sort by the first non-label column + if (!in_array($this->filter_sort_column, $actualColumns)) { + foreach ($actualColumns as $column) { + if ($column != 'label') { + $this->filter_sort_column = $column; + break; + } + } + } + $this->filter_sort_order = 'desc'; } diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index e49228a6ca..54643b578d 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -1273,7 +1273,9 @@ $.extend(DataTable.prototype, UIControl.prototype, { } }) .click(generateClickCallback('pivotBy', null, function () { - if (self.param.pivotBy) { + if (self.param.pivotBy + && self.param.pivotBy != '0' + ) { self.param.pivotBy = '0'; // set to '0' so it will be sent in the request and override the saved param self.param.pivotByColumn = '0'; } else { @@ -1282,6 +1284,10 @@ $.extend(DataTable.prototype, UIControl.prototype, { self.param.pivotByColumn = self.props.pivot_by_column; } } + + // remove sorting so it will default to first column in table + self.param.filter_sort_column = ''; + self.notifyWidgetParametersChange(domElem, {filter_sort_column: ''}); })); // handle highlighted icon -- cgit v1.2.3 From 33cc6c77bc789a6d957272b1fec4a15a7d6ffb2b Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 13:54:06 -0700 Subject: Refs #6078, make sure sorting doesn't break if column has special characters. --- plugins/CoreHome/javascripts/dataTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 54643b578d..3dd81737c4 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -576,7 +576,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { // we change the style of the column currently used as sort column // adding an image and the class columnSorted to the TD - $("th#" + self.param.filter_sort_column + ' #thDIV', domElem).parent() + $("th#" + self.param.filter_sort_column.replace(/([^a-zA-Z_-])/g, "\\$1") + ' #thDIV', domElem).parent() .addClass('columnSorted') .prepend('
    '); } -- cgit v1.2.3 From 96895068207ec39e0c110307a0d2f987970752e5 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 15:34:52 -0700 Subject: Refs #6078, prepend numeral index to each column in pivotted datatable. --- core/API/DocumentationGenerator.php | 2 + core/DataTable/Filter/PivotByDimension.php | 35 +++- .../Core/DataTable/Filter/PivotByDimensionTest.php | 6 +- .../PHPUnit/Integration/PivotByQueryParamTest.php | 3 +- ...ithDataTableMaps__Referrers.getKeywords_day.xml | 36 ++-- ...hColumnLimiting__Referrers.getKeywords_week.xml | 12 +- ...ksWithCsvOutput__Referrers.getKeywords_week.csv | Bin 440 -> 458 bytes ...WithJsonOutput__Referrers.getKeywords_week.json | 2 +- ...oseSubtableIsSelf__Actions.getPageUrls_week.xml | 210 ++++++++++----------- ...ntUsedInRequest__Referrers.getKeywords_week.xml | 4 +- ...rrectPivotTable__Referrers.getKeywords_week.xml | 36 ++-- ...rchyIsNotLoaded__Referrers.getKeywords_week.xml | 72 +++---- 12 files changed, 227 insertions(+), 191 deletions(-) diff --git a/core/API/DocumentationGenerator.php b/core/API/DocumentationGenerator.php index 0662ff153e..668f97bb60 100644 --- a/core/API/DocumentationGenerator.php +++ b/core/API/DocumentationGenerator.php @@ -193,6 +193,8 @@ class DocumentationGenerator $aParameters['pivotBy'] = false; $aParameters['pivotByColumn'] = false; $aParameters['pivotByColumnLimit'] = false; + $aParameters['disable_queued_filters'] = false; + $aParameters['disable_generic_filters'] = false; $moduleName = Proxy::getInstance()->getModuleNameFromClassName($class); $aParameters = array_merge(array('module' => 'API', 'method' => $moduleName . '.' . $methodName), $aParameters); diff --git a/core/DataTable/Filter/PivotByDimension.php b/core/DataTable/Filter/PivotByDimension.php index ba4f0220f6..fd176f8cf5 100644 --- a/core/DataTable/Filter/PivotByDimension.php +++ b/core/DataTable/Filter/PivotByDimension.php @@ -215,7 +215,7 @@ class PivotByDimension extends BaseFilter $others = Piwik::translate('General_Others'); $defaultRow = $this->getPivotTableDefaultRowFromColumnSummary($columnSet, $others); - Log::debug("PivotByDimension::%s: processed pivoted columns: %s", __FUNCTION__, $defaultRow); + Log::debug("PivotByDimension::%s: un-prepended default row: %s", __FUNCTION__, $defaultRow); // post process pivoted datatable foreach ($table->getRows() as $row) { @@ -238,6 +238,18 @@ class PivotByDimension extends BaseFilter $table->clearQueuedFilters(); // TODO: shouldn't clear queued filters, but we can't wait for them to be run // since generic filters are run before them. remove after refactoring // processed metrics. + + // prepend numerals to columns in a queued filter (this way, disable_queued_filters can be used + // to get machine readable data from the API if needed) + $prependedColumnNames = $this->getOrderedColumnsWithPrependedNumerals($defaultRow, $others); + + Log::debug("PivotByDimension::%s: prepended column name mapping: %s", __FUNCTION__, $prependedColumnNames); + + $table->queueFilter(function (DataTable $table) use ($prependedColumnNames) { + foreach ($table->getRows() as $row) { + $row->setColumns(array_combine($prependedColumnNames, $row->getColumns())); + } + }); } /** @@ -445,6 +457,27 @@ class PivotByDimension extends BaseFilter return $columnSet; } + private function getOrderedColumnsWithPrependedNumerals($defaultRow, $othersRowLabel) + { + $result = array(); + + $currentIndex = 1; + foreach ($defaultRow as $columnName => $ignore) { + if ($columnName == $othersRowLabel + || $columnName == 'label' + ) { + $result[] = $columnName; + } else { + $modifiedColumnName = $currentIndex . '. ' . $columnName; + $result[] = $modifiedColumnName; + + ++$currentIndex; + } + } + + return $result; + } + /** * Returns true if pivoting by subtable is supported for a report. Will return true if the report * has a subtable dimension and if the subtable dimension is different than the report's dimension. diff --git a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php index d711d6655c..f1de402f44 100644 --- a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php +++ b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php @@ -262,9 +262,9 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $pivotFilter->filter($table); $expectedRows = array( - array('label' => 'row 1', 'col 2' => false, 'col 3' => false, 'col 4' => false), - array('label' => 'row 2', 'col 2' => 5, 'col 3' => false, 'col 4' => false), - array('label' => 'row 3', 'col 2' => 7, 'col 3' => 9, 'col 4' => 32) + array('label' => 'row 1', 'col 2' => false, 'col 4' => false, 'General_Others' => 1), + array('label' => 'row 2', 'col 2' => 5, 'col 4' => false, 'General_Others' => 3), + array('label' => 'row 3', 'col 2' => 7, 'col 4' => 32, 'General_Others' => 9) ); $this->assertTableRowsEquals($expectedRows, $table); } diff --git a/tests/PHPUnit/Integration/PivotByQueryParamTest.php b/tests/PHPUnit/Integration/PivotByQueryParamTest.php index 2ca32cada2..d798d22bea 100644 --- a/tests/PHPUnit/Integration/PivotByQueryParamTest.php +++ b/tests/PHPUnit/Integration/PivotByQueryParamTest.php @@ -38,7 +38,8 @@ class PivotByQueryParamTest extends IntegrationTestCase 'period' => 'week', 'pivotBy' => 'Referrers.SearchEngine', 'pivotByColumn' => 'nb_visits', - 'pivotByColumnLimit' => -1 + 'pivotByColumnLimit' => -1, + 'disable_queued_filters' => 1 // test that prepending doesn't happen w/ this )); } diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml index 744fcf397e..d98cace554 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml @@ -6,39 +6,39 @@ this search term - 0 - 1 - 2 + 0 + 1 + 2 search term 2 - 0 - 2 - 0 + 0 + 2 + 0 search term 3 - 2 - 0 - 0 + 2 + 0 + 0 search term 4 - 2 - 0 - 0 + 2 + 0 + 0 that search term - 0 - 0 - 2 + 0 + 0 + 2 search term 1 - 0 - 1 - 0 + 0 + 1 + 0 diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml index 4635e78f76..ac43686db0 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml @@ -2,32 +2,32 @@ this search term - 0 + 0 3 search term 2 - 0 + 0 2 search term 3 - 2 + 2 0 search term 4 - 2 + 2 0 that search term - 0 + 0 2 search term 1 - 0 + 0 1 \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv index 0536708ea8..a465a67a14 100644 Binary files a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv and b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv differ diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json index 9b82ca037a..736901c89a 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json @@ -1 +1 @@ -[{"label":"this search term","Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":1,"Melbourne, Victoria, Australia":2},{"label":"search term 2","Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":2,"Melbourne, Victoria, Australia":false},{"label":"search term 3","Toronto, Ontario, Canada":2,"Yokohama, Kanagawa, Japan":false,"Melbourne, Victoria, Australia":false},{"label":"search term 4","Toronto, Ontario, Canada":2,"Yokohama, Kanagawa, Japan":false,"Melbourne, Victoria, Australia":false},{"label":"that search term","Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":false,"Melbourne, Victoria, Australia":2},{"label":"search term 1","Toronto, Ontario, Canada":false,"Yokohama, Kanagawa, Japan":1,"Melbourne, Victoria, Australia":false}] \ No newline at end of file +[{"label":"this search term","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":1,"3. Melbourne, Victoria, Australia":2},{"label":"search term 2","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":2,"3. Melbourne, Victoria, Australia":false},{"label":"search term 3","1. Toronto, Ontario, Canada":2,"2. Yokohama, Kanagawa, Japan":false,"3. Melbourne, Victoria, Australia":false},{"label":"search term 4","1. Toronto, Ontario, Canada":2,"2. Yokohama, Kanagawa, Japan":false,"3. Melbourne, Victoria, Australia":false},{"label":"that search term","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":false,"3. Melbourne, Victoria, Australia":2},{"label":"search term 1","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":1,"3. Melbourne, Victoria, Australia":false}] \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml index 5697f732c4..0b88c2ff59 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml @@ -2,122 +2,122 @@ 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 0 - 1 - 1 - 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 1 + 1 + 0 2 - 1 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 3 - 1 - 1 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 4 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml index f4cc044f57..52686d6610 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml @@ -2,10 +2,10 @@ that search term - 2 + 2 this search term - 2 + 2 \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml index c6315c7326..8112e991f5 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml @@ -2,38 +2,38 @@ this search term - 0 - 1 - 2 + 0 + 1 + 2 search term 2 - 0 - 2 - 0 + 0 + 2 + 0 search term 3 - 2 - 0 - 0 + 2 + 0 + 0 search term 4 - 2 - 0 - 0 + 2 + 0 + 0 that search term - 0 - 0 - 2 + 0 + 0 + 2 search term 1 - 0 - 1 - 0 + 0 + 1 + 0 \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml index 1adf9d722a..6ab5630422 100644 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml @@ -2,56 +2,56 @@ this search term - 1 - 1 - 1 - 0 - 0 - 0 + 1 + 1 + 1 + 0 + 0 + 0 search term 2 - 0 - 0 - 0 - 0 - 1 - 1 + 0 + 0 + 0 + 0 + 1 + 1 search term 3 - 1 - 0 - 1 - 0 - 0 - 0 + 1 + 0 + 1 + 0 + 0 + 0 search term 4 - 0 - 1 - 0 - 1 - 0 - 0 + 0 + 1 + 0 + 1 + 0 + 0 that search term - 1 - 1 - 0 - 0 - 0 - 0 + 1 + 1 + 0 + 0 + 0 + 0 search term 1 - 0 - 0 - 0 - 1 - 0 - 0 + 0 + 0 + 0 + 1 + 0 + 0 \ No newline at end of file -- cgit v1.2.3 From 3101516bd671937e297dabc423576c315a60e135 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 15:38:49 -0700 Subject: Refs #6078,set pivotByColumnLimit explicitly in export link so user can manipulate it. --- plugins/CoreHome/javascripts/dataTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 3dd81737c4..bc222b2617 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -1092,7 +1092,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { str += '&expanded=1'; } if (self.param.pivotBy) { - str += '&pivotBy=' + self.param.pivotBy; + str += '&pivotBy=' + self.param.pivotBy + '&pivotByColumnLimit=20'; if (self.props.pivot_by_column) { str += '&pivotByColumn=' + self.props.pivot_by_column; } -- cgit v1.2.3 From 89ce428063338b24cf229f44c7a716abfeae1674 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 15:52:43 -0700 Subject: Refs #6078, remove dead code & refactor dimension equality checks in PivotByDimension filter. --- core/DataTable/Filter/PivotByDimension.php | 27 +++++++++++++++++++++++---- core/DataTable/Renderer/Csv.php | 10 ---------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/core/DataTable/Filter/PivotByDimension.php b/core/DataTable/Filter/PivotByDimension.php index fd176f8cf5..b3d5a3b5e3 100644 --- a/core/DataTable/Filter/PivotByDimension.php +++ b/core/DataTable/Filter/PivotByDimension.php @@ -274,7 +274,7 @@ class PivotByDimension extends BaseFilter private function isPivotDimensionSubtable() { - return !empty($this->subtableDimension) && $this->subtableDimension->getId() == $this->pivotByDimension->getId(); + return self::areDimensionsEqualAndNotNull($this->subtableDimension, $this->pivotByDimension); } private function loadSubtable(DataTable $table, Row $row) @@ -353,7 +353,7 @@ class PivotByDimension extends BaseFilter throw new Exception("Unsupported pivot: report '$reportId' has no subtable dimension."); } - if ($this->subtableDimension->getId() !== $this->pivotByDimension->getId()) { + if (!$this->isPivotDimensionSubtable()) { throw new Exception("Unsupported pivot: the subtable dimension for '$reportId' does not match the " . "requested pivotBy dimension. [subtable dimension = {$this->subtableDimension->getId()}, " . "pivot by dimension = {$this->pivotByDimension->getId()}]"); @@ -487,8 +487,7 @@ class PivotByDimension extends BaseFilter */ public static function isPivotingReportBySubtableSupported(Report $report) { - $subtableDimension = $report->getSubtableDimension(); - return !empty($subtableDimension) && $subtableDimension->getId() !== $report->getDimension()->getId(); + return self::areDimensionsNotEqualAndNotNull($report->getSubtableDimension(), $report->getDimension()); } /** @@ -511,4 +510,24 @@ class PivotByDimension extends BaseFilter { return Config::getInstance()->General['pivot_by_filter_default_column_limit']; } + + /** + * @param Dimension|null $lhs + * @param Dimension|null $rhs + * @return bool + */ + private static function areDimensionsEqualAndNotNull($lhs, $rhs) + { + return !empty($lhs) && !empty($rhs) && $lhs->getId() == $rhs->getId(); + } + + /** + * @param Dimension|null $lhs + * @param Dimension|null $rhs + * @return bool + */ + private static function areDimensionsNotEqualAndNotNull($lhs, $rhs) + { + return !empty($lhs) && !empty($rhs) && $lhs->getId() != $rhs->getId(); + } } \ No newline at end of file diff --git a/core/DataTable/Renderer/Csv.php b/core/DataTable/Renderer/Csv.php index 25961ce8a9..f75ef8d215 100644 --- a/core/DataTable/Renderer/Csv.php +++ b/core/DataTable/Renderer/Csv.php @@ -392,14 +392,4 @@ class Csv extends Renderer return $name; } } - - private function escapeCsvValue($value) - { - if (strpos($value, ',') !== false - || strpos($value, '"') !== false - ) { - return '"' . addslashes($value) . '"'; - } - return $value; - } } -- cgit v1.2.3 From fcbb47d7934427b7b9e0d8d1f93a96bf699c9ec8 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 16:01:54 -0700 Subject: Refs #6078, make sure pivot option does not display if table is not pivotted and has no subtables (eg, when flattened). --- core/Plugin/Visualization.php | 5 +++++ core/ViewDataTable/Config.php | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/core/Plugin/Visualization.php b/core/Plugin/Visualization.php index e369dfa05a..31d9c58980 100644 --- a/core/Plugin/Visualization.php +++ b/core/Plugin/Visualization.php @@ -297,6 +297,11 @@ class Visualization extends ViewDataTable $this->config->report_last_updated_message = $this->makePrettyArchivedOnText(); } } + + $pivotBy = Common::getRequestVar('pivotBy', false) ?: $this->requestConfig->pivotBy; + if (empty($pivotBy)) { + $this->config->disablePivotBySubtableIfTableHasNoSubtables($this->dataTable); + } } private function applyFilters() diff --git a/core/ViewDataTable/Config.php b/core/ViewDataTable/Config.php index e9d6ee54d2..11ef83a1dc 100644 --- a/core/ViewDataTable/Config.php +++ b/core/ViewDataTable/Config.php @@ -9,6 +9,7 @@ namespace Piwik\ViewDataTable; use Piwik\API\Request as ApiRequest; +use Piwik\DataTable; use Piwik\DataTable\Filter\PivotByDimension; use Piwik\Metrics; use Piwik\Plugin\Report; @@ -682,4 +683,15 @@ class Config } } } + + public function disablePivotBySubtableIfTableHasNoSubtables(DataTable $table) + { + foreach ($table->getRows() as $row) { + if ($row->getIdSubDataTable() !== null) { + return; + } + } + + $this->show_pivot_by_subtable = false; + } } -- cgit v1.2.3 From 3dfe72413261c6bb8fa158df39e54449e13cfd62 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 16:20:24 -0700 Subject: Refs #6078, rename test methods. --- plugins/CoreConsole/Commands/TestsRun.php | 2 +- tests/PHPUnit/Core/API/ApiRendererTest.php | 1 + .../Core/DataTable/Filter/PivotByDimensionTest.php | 28 ++--- .../PHPUnit/Integration/PivotByQueryParamTest.php | 22 ++-- ...ithDataTableMaps__Referrers.getKeywords_day.xml | 49 -------- ...therQueryParams__Referrers.getKeywords_week.xml | 33 ------ ...hColumnLimiting__Referrers.getKeywords_week.xml | 33 ------ ...ksWithCsvOutput__Referrers.getKeywords_week.csv | Bin 458 -> 0 bytes ...WithJsonOutput__Referrers.getKeywords_week.json | 1 - ...oseSubtableIsSelf__Actions.getPageUrls_week.xml | 123 --------------------- ...ntUsedInRequest__Referrers.getKeywords_week.xml | 11 -- ...rrectPivotTable__Referrers.getKeywords_week.xml | 39 ------- ...rchyIsNotLoaded__Referrers.getKeywords_week.xml | 57 ---------- ...rrectPivotTable__Referrers.getKeywords_week.xml | 57 ---------- ...ithDataTableMaps__Referrers.getKeywords_day.xml | 49 ++++++++ ...therQueryParams__Referrers.getKeywords_week.xml | 33 ++++++ ...hColumnLimiting__Referrers.getKeywords_week.xml | 33 ++++++ ...ksWithCsvOutput__Referrers.getKeywords_week.csv | Bin 0 -> 458 bytes ...WithJsonOutput__Referrers.getKeywords_week.json | 1 + ...oseSubtableIsSelf__Actions.getPageUrls_week.xml | 123 +++++++++++++++++++++ ...ntUsedInRequest__Referrers.getKeywords_week.xml | 11 ++ ...rrectPivotTable__Referrers.getKeywords_week.xml | 39 +++++++ ...rchyIsNotLoaded__Referrers.getKeywords_week.xml | 57 ++++++++++ ...rrectPivotTable__Referrers.getKeywords_week.xml | 57 ++++++++++ 24 files changed, 430 insertions(+), 429 deletions(-) delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml delete mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_PlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_PlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithColumnLimiting__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithCsvOutput__Referrers.getKeywords_week.csv create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithJsonOutput__Referrers.getKeywords_week.json create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySegment_CreatesCorrectPivotTable_WhenSegmentUsedInRequest__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySegment_CreatesCorrectPivotTable__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySubtableDimension_CreatesCorrectPivotTable_WhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml create mode 100644 tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySubtableDimension_CreatesCorrectPivotTable__Referrers.getKeywords_week.xml diff --git a/plugins/CoreConsole/Commands/TestsRun.php b/plugins/CoreConsole/Commands/TestsRun.php index 542e803b9e..5f940acb83 100644 --- a/plugins/CoreConsole/Commands/TestsRun.php +++ b/plugins/CoreConsole/Commands/TestsRun.php @@ -87,7 +87,7 @@ class TestsRun extends ConsoleCommand private function executeTestFile($testFile, $options, $command, OutputInterface $output) { - $params = $testFile . " " . $options; + $params = $options . " " . $testFile; $cmd = sprintf("cd %s/tests/PHPUnit && %s %s", PIWIK_DOCUMENT_ROOT, $command, $params); $output->writeln('Executing command: ' . $cmd . ''); passthru($cmd); diff --git a/tests/PHPUnit/Core/API/ApiRendererTest.php b/tests/PHPUnit/Core/API/ApiRendererTest.php index 42d014ae17..ebe1952a90 100644 --- a/tests/PHPUnit/Core/API/ApiRendererTest.php +++ b/tests/PHPUnit/Core/API/ApiRendererTest.php @@ -10,6 +10,7 @@ use Piwik\API\ApiRenderer; /** * @group Core + * @group Only2 */ class ApiRendererTest extends PHPUnit_Framework_TestCase { diff --git a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php index f1de402f44..80162b362f 100644 --- a/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php +++ b/tests/PHPUnit/Core/DataTable/Filter/PivotByDimensionTest.php @@ -70,7 +70,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase * @expectedException Exception * @expectedExceptionMessage Unsupported pivot: report 'ExampleReport.ExampleReportName' has no subtable dimension. */ - public function testConstructionFailsWhenReportHasNoSubtableAndSegmentFetchingIsDisabled() + public function test_construction_ShouldFail_WhenReportHasNoSubtableAndSegmentFetchingIsDisabled() { $this->loadPlugins('ExampleReport', 'UserCountry'); @@ -81,7 +81,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase * @expectedException Exception * @expectedExceptionMessage Unsupported pivot: the subtable dimension for 'Referrers.Referrers_Keywords' does not match the requested pivotBy dimension. */ - public function testConstructionFailsWhenDimensionIsNotSubtableAndSegmentFetchingIsDisabled() + public function test_construction_ShouldFail_WhenDimensionIsNotSubtableAndSegmentFetchingIsDisabled() { $this->loadPlugins('Referrers', 'UserCountry'); @@ -92,7 +92,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase * @expectedException Exception * @expectedExceptionMessage Unsupported pivot: No segment for dimension of report 'UserSettings.UserSettings_WidgetBrowserFamilies' */ - public function testConstructionFailsWhenDimensionIsNotSubtableAndSegmentFetchingIsEnabledButThereIsNoSegment() + public function test_construction_ShouldFail_WhenDimensionIsNotSubtableAndSegmentFetchingIsEnabledButThereIsNoSegment() { $this->loadPlugins('Referrers', 'UserSettings'); @@ -103,7 +103,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase * @expectedException Exception * @expectedExceptionMessage Invalid dimension 'ExampleTracker.InvalidDimension' */ - public function testConstructionFailsWhenDimensionDoesNotExist() + public function test_construction_ShouldFail_WhenDimensionDoesNotExist() { $this->loadPlugins('ExampleReport', 'ExampleTracker'); @@ -114,7 +114,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase * @expectedException Exception * @expectedExceptionMessage Unsupported pivot: No report for pivot dimension 'ExampleTracker.ExampleDimension' */ - public function testConstructionFailsWhenThereIsNoReportForADimension() + public function test_construction_ShouldFail_WhenThereIsNoReportForADimension() { $this->loadPlugins('ExampleReport', 'ExampleTracker'); @@ -125,14 +125,14 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase * @expectedException Exception * @expectedExceptionMessage Unable to find report 'ExampleReport.InvalidReport' */ - public function testConstructionFailsWhenSpecifiedReportIsNotValid() + public function test_construction_ShouldFail_WhenSpecifiedReportIsNotValid() { $this->loadPlugins('ExampleReport', 'Referrers'); new PivotByDimension(new DataTable(), "ExampleReport.InvalidReport", "Referrers.Keyword", "nb_visits"); } - public function testFilterReturnsEmptyResultWhenTableToFilterIsEmpty() + public function test_filter_ReturnsEmptyResult_WhenTableToFilterIsEmpty() { $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); @@ -144,7 +144,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $this->assertEquals(array(), $table->getRows()); } - public function testFilterCorrectlyCreatesPivotTableUsingSubtableReport() + public function test_filter_CorrectlyCreatesPivotTable_WhenUsingSubtableReport() { $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); @@ -161,7 +161,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $this->assertTableRowsEquals($expectedRows, $table); } - public function testFilterCorrectlyCreatesPivotTableUsingSegment() + public function test_filter_CorrectlyCreatesPivotTable_WhenUsingSegment() { $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); @@ -181,7 +181,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $this->assertTableRowsEquals($expectedRows, $table); } - public function testFilterUsesCorrectSegmentWhenPivotingSegmentedReport() + public function test_filter_UsesCorrectSegment_WhenPivotingSegmentedReport() { $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); @@ -200,7 +200,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $this->assertEquals($expectedSegmentParams, $this->segmentUsedToGetIntersected); } - public function testFilterCorrectlyCreatesPivotTableWhenPivotMetricDoesNotExistInTable() + public function test_filter_CorrectlyCreatesPivotTable_WhenPivotMetricDoesNotExistInTable() { $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); @@ -217,7 +217,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $this->assertTableRowsEquals($expectedRows, $table); } - public function testFilterCorrectlyCreatesPivotTableWhenSubtablesHaveNoRows() + public function test_filter_CorrectlyCreatesPivotTable_WhenSubtablesHaveNoRows() { $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); @@ -235,7 +235,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $this->assertTableRowsEquals($expectedRows, $table); } - public function testFilterCorrectlyDefaultsPivotByColumnWhenNoneProvided() + public function test_filter_CorrectlyDefaultsPivotByColumn_WhenNoneProvided() { $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); @@ -252,7 +252,7 @@ class PivotByDimensionTest extends PHPUnit_Framework_TestCase $this->assertTableRowsEquals($expectedRows, $table); } - public function testFilterCorrectlyLimitsTheColumnNumberWhenColumnLimitProvided() + public function test_filter_CorrectlyLimitsTheColumnNumber_WhenColumnLimitProvided() { $this->loadPlugins('Referrers', 'UserCountry', 'CustomVariables'); diff --git a/tests/PHPUnit/Integration/PivotByQueryParamTest.php b/tests/PHPUnit/Integration/PivotByQueryParamTest.php index d798d22bea..6d42fe51ba 100644 --- a/tests/PHPUnit/Integration/PivotByQueryParamTest.php +++ b/tests/PHPUnit/Integration/PivotByQueryParamTest.php @@ -30,7 +30,7 @@ class PivotByQueryParamTest extends IntegrationTestCase Config::getInstance()->General['pivot_by_filter_enable_fetch_by_segment'] = 1; } - public function testPivotBySubtableDimensionCreatesCorrectPivotTable() + public function test_PivotBySubtableDimension_CreatesCorrectPivotTable() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( 'idSite' => self::$fixture->idSite, @@ -43,7 +43,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded() + public function test_PivotBySubtableDimension_CreatesCorrectPivotTable_WhenEntireHirearchyIsNotLoaded() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( 'idSite' => self::$fixture->idSite, @@ -56,7 +56,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotBySegmentCreatesCorrectPivotTable() + public function test_PivotBySegment_CreatesCorrectPivotTable() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( 'idSite' => self::$fixture->idSite, @@ -68,7 +68,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest() + public function test_PivotBySegment_CreatesCorrectPivotTable_WhenSegmentUsedInRequest() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( 'idSite' => self::$fixture->idSite, @@ -81,7 +81,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotByParamPlaysNiceWithOtherQueryParams() + public function test_PivotByParam_PlaysNiceWithOtherQueryParams() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( 'idSite' => self::$fixture->idSite, @@ -98,7 +98,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotByParamPlaysNiceWithQueuedFilters() + public function test_PivotByParam_PlaysNiceWithQueuedFilters() { // TODO: known issue: some segment/report relationships are more complicated; for example, UserCountry.GetCity labels are combinations // of city, region & country dimensions, so the segment to get an intersected table needs all 3 of those. @@ -115,7 +115,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotByParamWorksWithReportWhoseSubtableIsSelf() + public function test_PivotByParam_WorksWithReportWhoseSubtableIsSelf() { $this->assertApiResponseEqualsExpected("Actions.getPageUrls", array( 'idSite' => self::$fixture->idSite, @@ -127,7 +127,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotByParamWorksWithColumnLimiting() + public function test_PivotByParam_WorksWithColumnLimiting() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( 'idSite' => self::$fixture->idSite, @@ -139,7 +139,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotByParamWorksWithJsonOutput() + public function test_PivotByParam_WorksWithJsonOutput() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( 'idSite' => self::$fixture->idSite, @@ -152,7 +152,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotByParamWorksWithCsvOutput() + public function test_PivotByParam_WorksWithCsvOutput() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( 'idSite' => self::$fixture->idSite, @@ -165,7 +165,7 @@ class PivotByQueryParamTest extends IntegrationTestCase )); } - public function testPivotByParamPlaysNiceWithDataTableMaps() + public function test_PivotByParam_PlaysNiceWithDataTableMaps() { $this->assertApiResponseEqualsExpected("Referrers.getKeywords", array( 'idSite' => 'all', diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml deleted file mode 100644 index d98cace554..0000000000 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - this search term - 0 - 1 - 2 - - - search term 2 - 0 - 2 - 0 - - - search term 3 - 2 - 0 - 0 - - - search term 4 - 2 - 0 - 0 - - - that search term - 0 - 0 - 2 - - - search term 1 - 0 - 1 - 0 - - - - - - - - \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml deleted file mode 100644 index 05553ef4f8..0000000000 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamPlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 1 - 0 - - - - 0 - 0 - - - - 1 - 0 - - - - 0 - 1 - - - - 1 - 0 - - - - 0 - 1 - - \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml deleted file mode 100644 index ac43686db0..0000000000 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithColumnLimiting__Referrers.getKeywords_week.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - this search term - 0 - 3 - - - search term 2 - 0 - 2 - - - search term 3 - 2 - 0 - - - search term 4 - 2 - 0 - - - that search term - 0 - 2 - - - search term 1 - 0 - 1 - - \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv deleted file mode 100644 index a465a67a14..0000000000 Binary files a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithCsvOutput__Referrers.getKeywords_week.csv and /dev/null differ diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json deleted file mode 100644 index 736901c89a..0000000000 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithJsonOutput__Referrers.getKeywords_week.json +++ /dev/null @@ -1 +0,0 @@ -[{"label":"this search term","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":1,"3. Melbourne, Victoria, Australia":2},{"label":"search term 2","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":2,"3. Melbourne, Victoria, Australia":false},{"label":"search term 3","1. Toronto, Ontario, Canada":2,"2. Yokohama, Kanagawa, Japan":false,"3. Melbourne, Victoria, Australia":false},{"label":"search term 4","1. Toronto, Ontario, Canada":2,"2. Yokohama, Kanagawa, Japan":false,"3. Melbourne, Victoria, Australia":false},{"label":"that search term","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":false,"3. Melbourne, Victoria, Australia":2},{"label":"search term 1","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":1,"3. Melbourne, Victoria, Australia":false}] \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml deleted file mode 100644 index 0b88c2ff59..0000000000 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotByParamWorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - - - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 0 - 1 - 1 - 0 - - - 2 - 1 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - - - 3 - 1 - 1 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 4 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml deleted file mode 100644 index 52686d6610..0000000000 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTableWhenSegmentUsedInRequest__Referrers.getKeywords_week.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - that search term - 2 - - - this search term - 2 - - \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml deleted file mode 100644 index 8112e991f5..0000000000 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySegmentCreatesCorrectPivotTable__Referrers.getKeywords_week.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - this search term - 0 - 1 - 2 - - - search term 2 - 0 - 2 - 0 - - - search term 3 - 2 - 0 - 0 - - - search term 4 - 2 - 0 - 0 - - - that search term - 0 - 0 - 2 - - - search term 1 - 0 - 1 - 0 - - \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml deleted file mode 100644 index 6ab5630422..0000000000 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTableWhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - this search term - 1 - 1 - 1 - 0 - 0 - 0 - - - search term 2 - 0 - 0 - 0 - 0 - 1 - 1 - - - search term 3 - 1 - 0 - 1 - 0 - 0 - 0 - - - search term 4 - 0 - 1 - 0 - 1 - 0 - 0 - - - that search term - 1 - 1 - 0 - 0 - 0 - 0 - - - search term 1 - 0 - 0 - 0 - 1 - 0 - 0 - - \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml deleted file mode 100644 index 1adf9d722a..0000000000 --- a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_testPivotBySubtableDimensionCreatesCorrectPivotTable__Referrers.getKeywords_week.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - this search term - 1 - 1 - 1 - 0 - 0 - 0 - - - search term 2 - 0 - 0 - 0 - 0 - 1 - 1 - - - search term 3 - 1 - 0 - 1 - 0 - 0 - 0 - - - search term 4 - 0 - 1 - 0 - 1 - 0 - 0 - - - that search term - 1 - 1 - 0 - 0 - 0 - 0 - - - search term 1 - 0 - 0 - 0 - 1 - 0 - 0 - - \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_PlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_PlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml new file mode 100644 index 0000000000..d98cace554 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_PlaysNiceWithDataTableMaps__Referrers.getKeywords_day.xml @@ -0,0 +1,49 @@ + + + + + + + + this search term + 0 + 1 + 2 + + + search term 2 + 0 + 2 + 0 + + + search term 3 + 2 + 0 + 0 + + + search term 4 + 2 + 0 + 0 + + + that search term + 0 + 0 + 2 + + + search term 1 + 0 + 1 + 0 + + + + + + + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_PlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_PlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..05553ef4f8 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_PlaysNiceWithOtherQueryParams__Referrers.getKeywords_week.xml @@ -0,0 +1,33 @@ + + + + + 1 + 0 + + + + 0 + 0 + + + + 1 + 0 + + + + 0 + 1 + + + + 1 + 0 + + + + 0 + 1 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithColumnLimiting__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithColumnLimiting__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..ac43686db0 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithColumnLimiting__Referrers.getKeywords_week.xml @@ -0,0 +1,33 @@ + + + + this search term + 0 + 3 + + + search term 2 + 0 + 2 + + + search term 3 + 2 + 0 + + + search term 4 + 2 + 0 + + + that search term + 0 + 2 + + + search term 1 + 0 + 1 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithCsvOutput__Referrers.getKeywords_week.csv b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithCsvOutput__Referrers.getKeywords_week.csv new file mode 100644 index 0000000000..a465a67a14 Binary files /dev/null and b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithCsvOutput__Referrers.getKeywords_week.csv differ diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithJsonOutput__Referrers.getKeywords_week.json b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithJsonOutput__Referrers.getKeywords_week.json new file mode 100644 index 0000000000..736901c89a --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithJsonOutput__Referrers.getKeywords_week.json @@ -0,0 +1 @@ +[{"label":"this search term","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":1,"3. Melbourne, Victoria, Australia":2},{"label":"search term 2","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":2,"3. Melbourne, Victoria, Australia":false},{"label":"search term 3","1. Toronto, Ontario, Canada":2,"2. Yokohama, Kanagawa, Japan":false,"3. Melbourne, Victoria, Australia":false},{"label":"search term 4","1. Toronto, Ontario, Canada":2,"2. Yokohama, Kanagawa, Japan":false,"3. Melbourne, Victoria, Australia":false},{"label":"that search term","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":false,"3. Melbourne, Victoria, Australia":2},{"label":"search term 1","1. Toronto, Ontario, Canada":false,"2. Yokohama, Kanagawa, Japan":1,"3. Melbourne, Victoria, Australia":false}] \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml new file mode 100644 index 0000000000..0b88c2ff59 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotByParam_WorksWithReportWhoseSubtableIsSelf__Actions.getPageUrls_week.xml @@ -0,0 +1,123 @@ + + + + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + + + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + + + 2 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + + 3 + 1 + 1 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 4 + 1 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySegment_CreatesCorrectPivotTable_WhenSegmentUsedInRequest__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySegment_CreatesCorrectPivotTable_WhenSegmentUsedInRequest__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..52686d6610 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySegment_CreatesCorrectPivotTable_WhenSegmentUsedInRequest__Referrers.getKeywords_week.xml @@ -0,0 +1,11 @@ + + + + that search term + 2 + + + this search term + 2 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySegment_CreatesCorrectPivotTable__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySegment_CreatesCorrectPivotTable__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..8112e991f5 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySegment_CreatesCorrectPivotTable__Referrers.getKeywords_week.xml @@ -0,0 +1,39 @@ + + + + this search term + 0 + 1 + 2 + + + search term 2 + 0 + 2 + 0 + + + search term 3 + 2 + 0 + 0 + + + search term 4 + 2 + 0 + 0 + + + that search term + 0 + 0 + 2 + + + search term 1 + 0 + 1 + 0 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySubtableDimension_CreatesCorrectPivotTable_WhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySubtableDimension_CreatesCorrectPivotTable_WhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..6ab5630422 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySubtableDimension_CreatesCorrectPivotTable_WhenEntireHirearchyIsNotLoaded__Referrers.getKeywords_week.xml @@ -0,0 +1,57 @@ + + + + this search term + 1 + 1 + 1 + 0 + 0 + 0 + + + search term 2 + 0 + 0 + 0 + 0 + 1 + 1 + + + search term 3 + 1 + 0 + 1 + 0 + 0 + 0 + + + search term 4 + 0 + 1 + 0 + 1 + 0 + 0 + + + that search term + 1 + 1 + 0 + 0 + 0 + 0 + + + search term 1 + 0 + 0 + 0 + 1 + 0 + 0 + + \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySubtableDimension_CreatesCorrectPivotTable__Referrers.getKeywords_week.xml b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySubtableDimension_CreatesCorrectPivotTable__Referrers.getKeywords_week.xml new file mode 100644 index 0000000000..1adf9d722a --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_PivotByQueryParamTest_test_PivotBySubtableDimension_CreatesCorrectPivotTable__Referrers.getKeywords_week.xml @@ -0,0 +1,57 @@ + + + + this search term + 1 + 1 + 1 + 0 + 0 + 0 + + + search term 2 + 0 + 0 + 0 + 0 + 1 + 1 + + + search term 3 + 1 + 0 + 1 + 0 + 0 + 0 + + + search term 4 + 0 + 1 + 0 + 1 + 0 + 0 + + + that search term + 1 + 1 + 0 + 0 + 0 + 0 + + + search term 1 + 0 + 0 + 0 + 1 + 0 + 0 + + \ No newline at end of file -- cgit v1.2.3 From 72272d7c652c040e4441a7bf8c34c4316ba0eb06 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 20:25:56 -0700 Subject: Refs #6078, make sure $this->dataTable is instance of DataTable before calling disablePivotBySubtableIfTableHasNoSubtables. --- core/Plugin/Visualization.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/Plugin/Visualization.php b/core/Plugin/Visualization.php index 31d9c58980..e82a8d7f73 100644 --- a/core/Plugin/Visualization.php +++ b/core/Plugin/Visualization.php @@ -299,7 +299,9 @@ class Visualization extends ViewDataTable } $pivotBy = Common::getRequestVar('pivotBy', false) ?: $this->requestConfig->pivotBy; - if (empty($pivotBy)) { + if (empty($pivotBy) + && $this->dataTable instanceof DataTable + ) { $this->config->disablePivotBySubtableIfTableHasNoSubtables($this->dataTable); } } -- cgit v1.2.3 From fbbf12aa0533f26af733c76e4fec49464a056d74 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 21:19:22 -0700 Subject: Refs #6078, fix sorting on pivot table columns when columns use   (use decoded entity in PHP and do not select columns using jquery selector in dataTable.js). --- core/DataTable/Filter/PivotByDimension.php | 5 ++++- core/DataTable/Filter/Sort.php | 1 - plugins/CoreHome/javascripts/dataTable.js | 2 +- plugins/CoreHome/templates/_dataTableHead.twig | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/DataTable/Filter/PivotByDimension.php b/core/DataTable/Filter/PivotByDimension.php index b3d5a3b5e3..225a33f0bb 100644 --- a/core/DataTable/Filter/PivotByDimension.php +++ b/core/DataTable/Filter/PivotByDimension.php @@ -459,6 +459,9 @@ class PivotByDimension extends BaseFilter private function getOrderedColumnsWithPrependedNumerals($defaultRow, $othersRowLabel) { + $nbsp = html_entity_decode(' '); // must use decoded character otherwise sort later will fail + // (sort column will be set to decoded but columns will have  ) + $result = array(); $currentIndex = 1; @@ -468,7 +471,7 @@ class PivotByDimension extends BaseFilter ) { $result[] = $columnName; } else { - $modifiedColumnName = $currentIndex . '. ' . $columnName; + $modifiedColumnName = $currentIndex . '.' . $nbsp . $columnName; $result[] = $modifiedColumnName; ++$currentIndex; diff --git a/core/DataTable/Filter/Sort.php b/core/DataTable/Filter/Sort.php index 6ba2cd1ff0..683e93cffe 100644 --- a/core/DataTable/Filter/Sort.php +++ b/core/DataTable/Filter/Sort.php @@ -248,7 +248,6 @@ class Sort extends BaseFilter $methodToUse = "sortString"; } } - $table->sort(array($this, $methodToUse), $this->columnToSort); } } diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index bc222b2617..6a42e592ae 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -576,7 +576,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { // we change the style of the column currently used as sort column // adding an image and the class columnSorted to the TD - $("th#" + self.param.filter_sort_column.replace(/([^a-zA-Z_-])/g, "\\$1") + ' #thDIV', domElem).parent() + $('.thDIV', domElem).filter(function () { return $(this).text() == self.param.filter_sort_column; }).parent() .addClass('columnSorted') .prepend('
    '); } diff --git a/plugins/CoreHome/templates/_dataTableHead.twig b/plugins/CoreHome/templates/_dataTableHead.twig index 43b87a0e69..47091b3c0f 100644 --- a/plugins/CoreHome/templates/_dataTableHead.twig +++ b/plugins/CoreHome/templates/_dataTableHead.twig @@ -10,7 +10,7 @@ {{ properties.metrics_documentation[column]|raw }} {% endif %} -
    {{ properties.translations[column]|default(column)|raw }}
    +
    {{ properties.translations[column]|default(column)|raw }}
    {% endfor %} -- cgit v1.2.3 From 3d04d1501436a74adf587b97ec9c48450a9fd153 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 20 Sep 2014 21:23:51 -0700 Subject: Refs #6078, fix regression in last commit and only send one request to save viewdatatable params when un-pivoting. --- plugins/CoreHome/javascripts/dataTable.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 6a42e592ae..205ec70023 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -576,7 +576,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { // we change the style of the column currently used as sort column // adding an image and the class columnSorted to the TD - $('.thDIV', domElem).filter(function () { return $(this).text() == self.param.filter_sort_column; }).parent() + $('th', domElem).filter(function () { return $(this).attr('id') == self.param.filter_sort_column; }) .addClass('columnSorted') .prepend('
    '); } @@ -1183,15 +1183,15 @@ $.extend(DataTable.prototype, UIControl.prototype, { return function () { close(); if (setParamCallback) { - setParamCallback(); + var data = setParamCallback(); } else { self.param[paramName] = (1 - self.param[paramName]) + ''; + var data = {}; } self.param.filter_offset = 0; delete self.param.totalRows; if (callbackAfterToggle) callbackAfterToggle(); self.reloadAjaxDataTable(true, callbackSuccess); - var data = {}; data[paramName] = self.param[paramName]; self.notifyWidgetParametersChange(domElem, data); }; @@ -1287,7 +1287,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { // remove sorting so it will default to first column in table self.param.filter_sort_column = ''; - self.notifyWidgetParametersChange(domElem, {filter_sort_column: ''}); + return {filter_sort_column: ''}; })); // handle highlighted icon -- cgit v1.2.3