diff --git a/core/API/Request.php b/core/API/Request.php index 0fc4d313d00..68cd3fff1d4 100644 --- a/core/API/Request.php +++ b/core/API/Request.php @@ -366,7 +366,15 @@ public static function shouldLoadExpanded() // we have to load all the child subtables. return Common::getRequestVar('filter_column_recursive', false) !== false && Common::getRequestVar('filter_pattern_recursive', false) !== false - && Common::getRequestVar('flat', false) === false; + && !self::shouldLoadFlatten(); + } + + /** + * @return bool + */ + public static function shouldLoadFlatten() + { + return Common::getRequestVar('flat', false) == 1; } /** diff --git a/core/Archive.php b/core/Archive.php index db1ca62ded6..3f13396599e 100644 --- a/core/Archive.php +++ b/core/Archive.php @@ -192,9 +192,10 @@ protected function __construct(Parameters $params, $forceIndexedBySite = false, * or date range (ie, 'YYYY-MM-DD,YYYY-MM-DD'). * @param bool|false|string $segment Segment definition or false if no segment should be used. {@link Piwik\Segment} * @param bool|false|string $_restrictSitesToLogin Used only when running as a scheduled task. + * @param bool $skipAggregationOfSubTables Whether the archive, when it is processed, should also aggregate all sub-tables * @return Archive */ - public static function build($idSites, $period, $strDate, $segment = false, $_restrictSitesToLogin = false) + public static function build($idSites, $period, $strDate, $segment = false, $_restrictSitesToLogin = false, $skipAggregationOfSubTables = false) { $websiteIds = Site::getIdSitesFromIdSitesString($idSites, $_restrictSitesToLogin); @@ -209,7 +210,7 @@ public static function build($idSites, $period, $strDate, $segment = false, $_re $segment = new Segment($segment, $websiteIds); $idSiteIsAll = $idSites == self::REQUEST_ALL_WEBSITES_FLAG; $isMultipleDate = Period::isMultiplePeriod($strDate, $period); - return Archive::factory($segment, $allPeriods, $websiteIds, $idSiteIsAll, $isMultipleDate); + return Archive::factory($segment, $allPeriods, $websiteIds, $idSiteIsAll, $isMultipleDate, $skipAggregationOfSubTables); } /** @@ -231,9 +232,11 @@ public static function build($idSites, $period, $strDate, $segment = false, $_re * @param bool $isMultipleDate Whether multiple dates are being queried or not. If true, then * the result of querying functions will be indexed by period, * regardless of whether `count($periods) == 1`. + * @param bool $skipAggregationOfSubTables Whether the archive should skip aggregation of all sub-tables + * * @return Archive */ - public static function factory(Segment $segment, array $periods, array $idSites, $idSiteIsAll = false, $isMultipleDate = false) + public static function factory(Segment $segment, array $periods, array $idSites, $idSiteIsAll = false, $isMultipleDate = false, $skipAggregationOfSubTables = false) { $forceIndexedBySite = false; $forceIndexedByDate = false; @@ -244,7 +247,7 @@ public static function factory(Segment $segment, array $periods, array $idSites, $forceIndexedByDate = true; } - $params = new Parameters($idSites, $periods, $segment); + $params = new Parameters($idSites, $periods, $segment, $skipAggregationOfSubTables); return new Archive($params, $forceIndexedBySite, $forceIndexedByDate); } @@ -432,16 +435,21 @@ public function getParams() * @param string $segment @see {@link build()} * @param bool $expanded If true, loads all subtables. See {@link getDataTableExpanded()} * @param int|null $idSubtable See {@link getDataTableExpanded()} + * @param bool $skipAggregationOfSubTables Whether or not we should skip the aggregation of all sub-tables and only aggregate parent DataTable. * @param int|null $depth See {@link getDataTableExpanded()} * @return DataTable|DataTable\Map See {@link getDataTable()} and * {@link getDataTableExpanded()} for more * information */ public static function getDataTableFromArchive($name, $idSite, $period, $date, $segment, $expanded, - $idSubtable = null, $depth = null) + $idSubtable = null, $skipAggregationOfSubTables = false, $depth = null) { Piwik::checkUserHasViewAccess($idSite); - $archive = Archive::build($idSite, $period, $date, $segment); + + if($skipAggregationOfSubTables && ($expanded || $idSubtable)) { + throw new \Exception("Not expected to skipAggregationOfSubTables when expanded=1 or idSubtable is set."); + } + $archive = Archive::build($idSite, $period, $date, $segment, $_restrictSitesToLogin = false, $skipAggregationOfSubTables); if ($idSubtable === false) { $idSubtable = null; } @@ -620,7 +628,7 @@ private function cacheArchiveIdsAfterLaunching($archiveGroups, $plugins) private function cacheArchiveIdsWithoutLaunching($plugins) { $idarchivesByReport = ArchiveSelector::getArchiveIds( - $this->params->getIdSites(), $this->params->getPeriods(), $this->params->getSegment(), $plugins); + $this->params->getIdSites(), $this->params->getPeriods(), $this->params->getSegment(), $plugins, $this->params->isSkipAggregationOfSubTables()); // initialize archive ID cache for each report foreach ($plugins as $plugin) { @@ -644,7 +652,13 @@ private function cacheArchiveIdsWithoutLaunching($plugins) */ private function getDoneStringForPlugin($plugin) { - return Rules::getDoneStringFlagFor($this->params->getIdSites(), $this->params->getSegment(), $this->getPeriodLabel(), $plugin); + return Rules::getDoneStringFlagFor( + $this->params->getIdSites(), + $this->params->getSegment(), + $this->getPeriodLabel(), + $plugin, + $this->params->isSkipAggregationOfSubTables() + ); } private function getPeriodLabel() @@ -776,7 +790,7 @@ private static function getPluginForReport($report) */ private function prepareArchive(array $archiveGroups, Site $site, Period $period) { - $parameters = new ArchiveProcessor\Parameters($site, $period, $this->params->getSegment()); + $parameters = new ArchiveProcessor\Parameters($site, $period, $this->params->getSegment(), $this->params->isSkipAggregationOfSubTables()); $archiveLoader = new ArchiveProcessor\Loader($parameters); $periodString = $period->getRangeString(); diff --git a/core/Archive/Parameters.php b/core/Archive/Parameters.php index 0e2654c0f74..1f700819eee 100644 --- a/core/Archive/Parameters.php +++ b/core/Archive/Parameters.php @@ -36,16 +36,22 @@ class Parameters */ private $segment; + /** + * @var bool + */ + private $skipAggregationOfSubTables; + public function getSegment() { return $this->segment; } - public function __construct($idSites, $periods, Segment $segment) + public function __construct($idSites, $periods, Segment $segment, $skipAggregationOfSubTables) { $this->idSites = $idSites; $this->periods = $periods; $this->segment = $segment; + $this->skipAggregationOfSubTables = $skipAggregationOfSubTables; } public function getPeriods() @@ -58,5 +64,10 @@ public function getIdSites() return $this->idSites; } + public function isSkipAggregationOfSubTables() + { + return $this->skipAggregationOfSubTables; + } + } diff --git a/core/ArchiveProcessor.php b/core/ArchiveProcessor.php index f578673d014..20c4c2df80b 100644 --- a/core/ArchiveProcessor.php +++ b/core/ArchiveProcessor.php @@ -199,8 +199,14 @@ public function aggregateDataTableRecords($recordNames, $table = $this->aggregateDataTableRecord($recordName, $columnsAggregationOperation, $columnsToRenameAfterAggregation); - $nameToCount[$recordName]['level0'] = $table->getRowsCount(); - $nameToCount[$recordName]['recursive'] = $table->getRowsCountRecursive(); + $rowsCount = $table->getRowsCount(); + $nameToCount[$recordName]['level0'] = $rowsCount; + + $rowsCountRecursive = $rowsCount; + if($this->isAggregateSubTables()) { + $rowsCountRecursive = $table->getRowsCountRecursive(); + } + $nameToCount[$recordName]['recursive'] = $rowsCountRecursive; $blob = $table->getSerialized($maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable, $columnToSortByBeforeTruncation); Common::destroy($table); @@ -322,7 +328,15 @@ public function insertBlobRecord($name, $values) */ protected function aggregateDataTableRecord($name, $columnsAggregationOperation = null, $columnsToRenameAfterAggregation = null) { - $dataTable = $this->getArchive()->getDataTableExpanded($name, $idSubTable = null, $depth = null, $addMetadataSubtableId = false); + if($this->isAggregateSubTables()) { + // By default we shall aggregate all sub-tables. + $dataTable = $this->getArchive()->getDataTableExpanded($name, $idSubTable = null, $depth = null, $addMetadataSubtableId = false); + } else { + // In some cases (eg. Actions plugin when period=range), + // for better performance we will only aggregate the parent table + $dataTable = $this->getArchive()->getDataTable($name, $idSubTable = null); + } + $dataTable = $this->getAggregatedDataTableMap($dataTable, $columnsAggregationOperation); $this->renameColumnsAfterAggregation($dataTable, $columnsToRenameAfterAggregation); return $dataTable; @@ -402,7 +416,7 @@ protected function getAggregatedDataTableMap($data, $columnsAggregationOperation // as $date => $tableToSum $this->aggregatedDataTableMapsAsOne($data, $table); } else { - $table->addDataTable($data); + $table->addDataTable($data, $this->isAggregateSubTables()); } return $table; } @@ -418,7 +432,7 @@ protected function aggregatedDataTableMapsAsOne(Map $map, DataTable $aggregated) if($tableToAggregate instanceof Map) { $this->aggregatedDataTableMapsAsOne($tableToAggregate, $aggregated); } else { - $aggregated->addDataTable($tableToAggregate); + $aggregated->addDataTable($tableToAggregate, $this->isAggregateSubTables()); } } } @@ -430,7 +444,7 @@ protected function renameColumnsAfterAggregation(DataTable $table, $columnsToRen $columnsToRenameAfterAggregation = self::$columnsToRenameAfterAggregation; } foreach ($columnsToRenameAfterAggregation as $oldName => $newName) { - $table->renameColumn($oldName, $newName); + $table->renameColumn($oldName, $newName, $this->isAggregateSubTables()); } } @@ -464,4 +478,12 @@ protected function getAggregatedNumericMetrics($columns, $operationToApply) } return $metrics; } + + /** + * @return bool + */ + protected function isAggregateSubTables() + { + return !$this->getParams()->isSkipAggregationOfSubTables(); + } } diff --git a/core/ArchiveProcessor/Loader.php b/core/ArchiveProcessor/Loader.php index b3ac4cd3f49..03a054a617a 100644 --- a/core/ArchiveProcessor/Loader.php +++ b/core/ArchiveProcessor/Loader.php @@ -163,12 +163,8 @@ protected function loadExistingArchiveIdFromDb() if ($this->isArchivingForcedToTrigger()) { return $noArchiveFound; } - $site = $this->params->getSite(); - $period = $this->params->getPeriod(); - $segment = $this->params->getSegment(); - $requestedPlugin = $this->params->getRequestedPlugin(); - $idAndVisits = ArchiveSelector::getArchiveIdAndVisits($site, $period, $segment, $minDatetimeArchiveProcessedUTC, $requestedPlugin); + $idAndVisits = ArchiveSelector::getArchiveIdAndVisits($this->params, $minDatetimeArchiveProcessedUTC); if (!$idAndVisits) { return $noArchiveFound; } diff --git a/core/ArchiveProcessor/Parameters.php b/core/ArchiveProcessor/Parameters.php index 1aac335994a..9d9a9088221 100644 --- a/core/ArchiveProcessor/Parameters.php +++ b/core/ArchiveProcessor/Parameters.php @@ -48,11 +48,12 @@ class Parameters * * @ignore */ - public function __construct(Site $site, Period $period, Segment $segment) + public function __construct(Site $site, Period $period, Segment $segment, $skipAggregationOfSubTables = false) { $this->site = $site; $this->period = $period; $this->segment = $segment; + $this->skipAggregationOfSubTables = $skipAggregationOfSubTables; } /** @@ -168,6 +169,11 @@ public function isSingleSite() return count($this->getIdSites()) == 1; } + public function isSkipAggregationOfSubTables() + { + return $this->skipAggregationOfSubTables; + } + public function logStatusDebug($isTemporary) { $temporary = 'definitive archive'; diff --git a/core/ArchiveProcessor/Rules.php b/core/ArchiveProcessor/Rules.php index 9aef10302d8..05b37a93af4 100644 --- a/core/ArchiveProcessor/Rules.php +++ b/core/ArchiveProcessor/Rules.php @@ -50,10 +50,10 @@ class Rules * @param string $plugin * @return string */ - public static function getDoneStringFlagFor(array $idSites, $segment, $periodLabel, $plugin) + public static function getDoneStringFlagFor(array $idSites, $segment, $periodLabel, $plugin, $isSkipAggregationOfSubTables) { if (!self::shouldProcessReportsAllPlugins($idSites, $segment, $periodLabel)) { - return self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin); + return self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin, $isSkipAggregationOfSubTables); } return self::getDoneFlagArchiveContainsAllPlugins($segment); } @@ -98,9 +98,10 @@ private static function getSegmentsToProcess($idSites) return $segmentsToProcess; } - private static function getDoneFlagArchiveContainsOnePlugin(Segment $segment, $plugin) + private static function getDoneFlagArchiveContainsOnePlugin(Segment $segment, $plugin, $isSkipAggregationOfSubTables = false) { - return 'done' . $segment->getHash() . '.' . $plugin; + $partial = self::isFlagArchivePartial($plugin, $isSkipAggregationOfSubTables); + return 'done' . $segment->getHash() . '.' . $plugin . $partial ; } private static function getDoneFlagArchiveContainsAllPlugins(Segment $segment) @@ -108,18 +109,36 @@ private static function getDoneFlagArchiveContainsAllPlugins(Segment $segment) return 'done' . $segment->getHash(); } + /** + * @param $plugin + * @param $isSkipAggregationOfSubTables + * @return string + */ + private static function isFlagArchivePartial($plugin, $isSkipAggregationOfSubTables) + { + $partialArchive = ''; + if ($plugin != "VisitsSummary" // VisitsSummary is always called when segmenting and should not have its own .partial archive + && $isSkipAggregationOfSubTables + ) { + $partialArchive = '.partial'; + } + return $partialArchive; + } + /** * @param array $plugins * @param $segment * @return array */ - public static function getDoneFlags(array $plugins, $segment) + public static function getDoneFlags(array $plugins, Segment $segment, $isSkipAggregationOfSubTables) { $doneFlags = array(); $doneAllPlugins = self::getDoneFlagArchiveContainsAllPlugins($segment); $doneFlags[$doneAllPlugins] = $doneAllPlugins; + + $plugins = array_unique($plugins); foreach ($plugins as $plugin) { - $doneOnePlugin = self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin); + $doneOnePlugin = self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin, $isSkipAggregationOfSubTables); $doneFlags[$plugin] = $doneOnePlugin; } return $doneFlags; diff --git a/core/DataAccess/ArchiveSelector.php b/core/DataAccess/ArchiveSelector.php index eb994ac7561..4ba9b21b012 100644 --- a/core/DataAccess/ArchiveSelector.php +++ b/core/DataAccess/ArchiveSelector.php @@ -42,13 +42,13 @@ class ArchiveSelector const NB_VISITS_CONVERTED_RECORD_LOOKED_UP = "nb_visits_converted"; - static public function getArchiveIdAndVisits(Site $site, Period $period, Segment $segment, $minDatetimeArchiveProcessedUTC, $requestedPlugin) + static public function getArchiveIdAndVisits(ArchiveProcessor\Parameters $params, $minDatetimeArchiveProcessedUTC) { - $dateStart = $period->getDateStart(); - $bindSQL = array($site->getId(), + $dateStart = $params->getPeriod()->getDateStart(); + $bindSQL = array($params->getSite()->getId(), $dateStart->toString('Y-m-d'), - $period->getDateEnd()->toString('Y-m-d'), - $period->getId(), + $params->getPeriod()->getDateEnd()->toString('Y-m-d'), + $params->getPeriod()->getId(), ); $timeStampWhere = ''; @@ -57,9 +57,12 @@ static public function getArchiveIdAndVisits(Site $site, Period $period, Segment $bindSQL[] = Date::factory($minDatetimeArchiveProcessedUTC)->getDatetime(); } - $pluginOrVisitsSummary = array("VisitsSummary", $requestedPlugin); - $pluginOrVisitsSummary = array_unique($pluginOrVisitsSummary); - $sqlWhereArchiveName = self::getNameCondition($pluginOrVisitsSummary, $segment); + $requestedPlugin = $params->getRequestedPlugin(); + $segment = $params->getSegment(); + $isSkipAggregationOfSubTables = $params->isSkipAggregationOfSubTables(); + + $plugins = array("VisitsSummary", $requestedPlugin); + $sqlWhereArchiveName = self::getNameCondition($plugins, $segment, $isSkipAggregationOfSubTables); $sqlQuery = " SELECT idarchive, value, name, date1 as startDate FROM " . ArchiveTableCreator::getNumericTable($dateStart) . "`` @@ -77,8 +80,8 @@ static public function getArchiveIdAndVisits(Site $site, Period $period, Segment return false; } - $idArchive = self::getMostRecentIdArchiveFromResults($segment, $requestedPlugin, $results); - $idArchiveVisitsSummary = self::getMostRecentIdArchiveFromResults($segment, "VisitsSummary", $results); + $idArchive = self::getMostRecentIdArchiveFromResults($segment, $requestedPlugin, $isSkipAggregationOfSubTables, $results); + $idArchiveVisitsSummary = self::getMostRecentIdArchiveFromResults($segment, "VisitsSummary", $isSkipAggregationOfSubTables, $results); list($visits, $visitsConverted) = self::getVisitsMetricsFromResults($idArchive, $idArchiveVisitsSummary, $results); @@ -116,10 +119,10 @@ protected static function getVisitsMetricsFromResults($idArchive, $idArchiveVisi return array($visits, $visitsConverted); } - protected static function getMostRecentIdArchiveFromResults(Segment $segment, $requestedPlugin, $results) + protected static function getMostRecentIdArchiveFromResults(Segment $segment, $requestedPlugin, $isSkipAggregationOfSubTables, $results) { $idArchive = false; - $namesRequestedPlugin = Rules::getDoneFlags(array($requestedPlugin), $segment); + $namesRequestedPlugin = Rules::getDoneFlags(array($requestedPlugin), $segment, $isSkipAggregationOfSubTables); foreach ($results as $result) { if ($idArchive === false && in_array($result['name'], $namesRequestedPlugin) @@ -138,6 +141,7 @@ protected static function getMostRecentIdArchiveFromResults(Segment $segment, $r * @param array $periods * @param Segment $segment * @param array $plugins List of plugin names for which data is being requested. + * @param bool $isSkipAggregationOfSubTables Whether we are selecting an archive that may be partial (no sub-tables) * @return array Archive IDs are grouped by archive name and period range, ie, * array( * 'VisitsSummary.done' => array( @@ -145,12 +149,12 @@ protected static function getMostRecentIdArchiveFromResults(Segment $segment, $r * ) * ) */ - static public function getArchiveIds($siteIds, $periods, $segment, $plugins) + static public function getArchiveIds($siteIds, $periods, $segment, $plugins, $isSkipAggregationOfSubTables = false) { $getArchiveIdsSql = "SELECT idsite, name, date1, date2, MAX(idarchive) as idarchive FROM %s WHERE %s - AND " . self::getNameCondition($plugins, $segment) . " + AND " . self::getNameCondition($plugins, $segment, $isSkipAggregationOfSubTables) . " AND idsite IN (" . implode(',', $siteIds) . ") GROUP BY idsite, date1, date2"; @@ -270,20 +274,21 @@ static public function getArchiveData($archiveIds, $recordNames, $archiveDataTyp * * @param array $plugins * @param Segment $segment + * @param bool $isSkipAggregationOfSubTables * @return string */ - static private function getNameCondition(array $plugins, $segment) + static private function getNameCondition(array $plugins, Segment $segment, $isSkipAggregationOfSubTables) { // the flags used to tell how the archiving process for a specific archive was completed, // if it was completed - $doneFlags = Rules::getDoneFlags($plugins, $segment); + $doneFlags = Rules::getDoneFlags($plugins, $segment, $isSkipAggregationOfSubTables); $allDoneFlags = "'" . implode("','", $doneFlags) . "'"; // create the SQL to find archives that are DONE - return "(name IN ($allDoneFlags)) AND " . + return "((name IN ($allDoneFlags)) AND " . " (value = '" . ArchiveWriter::DONE_OK . "' OR " . - " value = '" . ArchiveWriter::DONE_OK_TEMPORARY . "')"; + " value = '" . ArchiveWriter::DONE_OK_TEMPORARY . "'))"; } static public function purgeOutdatedArchives(Date $dateStart) diff --git a/core/DataAccess/ArchiveWriter.php b/core/DataAccess/ArchiveWriter.php index bd11053089a..5650a6a828c 100644 --- a/core/DataAccess/ArchiveWriter.php +++ b/core/DataAccess/ArchiveWriter.php @@ -66,7 +66,7 @@ public function __construct(ArchiveProcessor\Parameters $params, $isArchiveTempo $this->segment = $params->getSegment(); $this->period = $params->getPeriod(); $idSites = array($this->idSite); - $this->doneFlag = Rules::getDoneStringFlagFor($idSites, $this->segment, $this->period->getLabel(), $params->getRequestedPlugin()); + $this->doneFlag = Rules::getDoneStringFlagFor($idSites, $this->segment, $this->period->getLabel(), $params->getRequestedPlugin(), $params->isSkipAggregationOfSubTables()); $this->isArchiveTemporary = $isArchiveTemporary; $this->dateStart = $this->period->getDateStart(); diff --git a/core/DataTable.php b/core/DataTable.php index 9edcaec3732..0f8809821d1 100644 --- a/core/DataTable.php +++ b/core/DataTable.php @@ -469,7 +469,7 @@ public function applyQueuedFilters() * * @param \Piwik\DataTable $tableToSum */ - public function addDataTable(DataTable $tableToSum) + public function addDataTable(DataTable $tableToSum, $doAggregateSubTables = true) { if($tableToSum instanceof Simple) { if($tableToSum->getRowsCount() > 1) { @@ -479,7 +479,7 @@ public function addDataTable(DataTable $tableToSum) $this->aggregateRowFromSimpleTable($row); } else { foreach ($tableToSum->getRows() as $row) { - $this->aggregateRowWithLabel($row); + $this->aggregateRowWithLabel($row, $doAggregateSubTables); } } } @@ -891,12 +891,15 @@ public function __sleep() * @param string $oldName Old column name. * @param string $newName New column name. */ - public function renameColumn($oldName, $newName) + public function renameColumn($oldName, $newName, $doRenameColumnsOfSubTables = true) { foreach ($this->getRows() as $row) { $row->renameColumn($oldName, $newName); - if (($idSubDataTable = $row->getIdSubDataTable()) !== null) { - Manager::getInstance()->getTable($idSubDataTable)->renameColumn($oldName, $newName); + + if($doRenameColumnsOfSubTables) { + if (($idSubDataTable = $row->getIdSubDataTable()) !== null) { + Manager::getInstance()->getTable($idSubDataTable)->renameColumn($oldName, $newName); + } } } if (!is_null($this->summaryRow)) { @@ -1582,7 +1585,7 @@ public static function fromSerializedArray($data) * @param $row * @throws \Exception */ - protected function aggregateRowWithLabel(Row $row) + protected function aggregateRowWithLabel(Row $row, $doAggregateSubTables = true) { $labelToLookFor = $row->getColumn('label'); if ($labelToLookFor === false) { @@ -1598,15 +1601,17 @@ protected function aggregateRowWithLabel(Row $row) } else { $rowFound->sumRow($row, $copyMeta = true, $this->getMetadata(self::COLUMN_AGGREGATION_OPS_METADATA_NAME)); - // if the row to add has a subtable whereas the current row doesn't - // we simply add it (cloning the subtable) - // if the row has the subtable already - // then we have to recursively sum the subtables - if (($idSubTable = $row->getIdSubDataTable()) !== null) { - $subTable = Manager::getInstance()->getTable($idSubTable); - $subTable->metadata[self::COLUMN_AGGREGATION_OPS_METADATA_NAME] - = $this->getMetadata(self::COLUMN_AGGREGATION_OPS_METADATA_NAME); - $rowFound->sumSubtable($subTable); + if($doAggregateSubTables) { + // if the row to add has a subtable whereas the current row doesn't + // we simply add it (cloning the subtable) + // if the row has the subtable already + // then we have to recursively sum the subtables + if (($idSubTable = $row->getIdSubDataTable()) !== null) { + $subTable = Manager::getInstance()->getTable($idSubTable); + $subTable->metadata[self::COLUMN_AGGREGATION_OPS_METADATA_NAME] + = $this->getMetadata(self::COLUMN_AGGREGATION_OPS_METADATA_NAME); + $rowFound->sumSubtable($subTable); + } } } } diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index 44deebf1ce1..1d25793433e 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -669,6 +669,7 @@ private function reloadPlugins() $this->pluginsToLoad = array_unique($this->pluginsToLoad); + $pluginsToPostPendingEventsTo = array(); foreach ($this->pluginsToLoad as $pluginName) { if (!$this->isPluginLoaded($pluginName) && !$this->isPluginThirdPartyAndBogus($pluginName) @@ -678,9 +679,14 @@ private function reloadPlugins() continue; } - EventDispatcher::getInstance()->postPendingEventsTo($newPlugin); + $pluginsToPostPendingEventsTo[] = $newPlugin; } } + + // post pending events after all plugins are successfully loaded + foreach ($pluginsToPostPendingEventsTo as $plugin) { + EventDispatcher::getInstance()->postPendingEventsTo($plugin); + } } public function getIgnoredBogusPlugins() diff --git a/core/View.php b/core/View.php index 8505aafe3fb..4afea486616 100644 --- a/core/View.php +++ b/core/View.php @@ -134,9 +134,14 @@ public function __construct($templateFile) $this->initializeTwig(); $this->piwik_version = Version::VERSION; - $this->piwikUrl = SettingsPiwik::getPiwikUrl(); $this->userLogin = Piwik::getCurrentUserLogin(); $this->isSuperUser = Access::getInstance()->hasSuperUserAccess(); // TODO: redundancy w/ userIsSuperUser + + try { + $this->piwikUrl = SettingsPiwik::getPiwikUrl(); + } catch (Exception $ex) { + // pass (occurs when DB cannot be connected to, perhaps piwik URL cache should be stored in config file...) + } } /** @@ -337,8 +342,8 @@ public function assign($var, $value = null) */ static public function clearCompiledTemplates() { - $view = new View(null); - $view->twig->clearTemplateCache(); + $twig = new Twig(); + $twig->getTwigEnvironment()->clearTemplateCache(); } /** diff --git a/libs/PiwikTracker/PiwikTracker.php b/libs/PiwikTracker/PiwikTracker.php index ab907788992..ec7cdcb4372 100644 --- a/libs/PiwikTracker/PiwikTracker.php +++ b/libs/PiwikTracker/PiwikTracker.php @@ -148,6 +148,8 @@ class PiwikTracker const CVAR_INDEX_ECOMMERCE_ITEM_NAME = 4; const CVAR_INDEX_ECOMMERCE_ITEM_CATEGORY = 5; + const DEFAULT_COOKIE_PATH = '/'; + /** * Builds a PiwikTracker object, used to track visits, pages and Goal conversions * for a specific website, by using the Piwik Tracking API. @@ -200,7 +202,7 @@ function __construct($idSite, $apiUrl = '') $this->setNewVisitorId(); $this->configCookiesDisabled = false; - $this->configCookiePath = '/'; + $this->configCookiePath = self::DEFAULT_COOKIE_PATH; $this->configCookieDomain = ''; $this->currentTs = time(); diff --git a/plugins/Actions/API.php b/plugins/Actions/API.php index ba96ce198be..14efde7db2c 100644 --- a/plugins/Actions/API.php +++ b/plugins/Actions/API.php @@ -9,6 +9,7 @@ namespace Piwik\Plugins\Actions; use Exception; +use Piwik\API\Request; use Piwik\Archive; use Piwik\Common; @@ -119,8 +120,7 @@ public function get($idSite, $period, $date, $segment = false, $columns = false) public function getPageUrls($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false, $depth = false) { - $dataTable = Archive::getDataTableFromArchive( - 'Actions_actions_url', $idSite, $period, $date, $segment, $expanded, $idSubtable, $depth); + $dataTable = $this->getDataTableFromArchive('Actions_actions_url', $idSite, $period, $date, $segment, $expanded, $idSubtable, $depth); $this->filterPageDatatable($dataTable); $this->filterActionsDataTable($dataTable, $expanded); return $dataTable; @@ -207,7 +207,7 @@ public function getPageUrl($pageUrl, $idSite, $period, $date, $segment = false) public function getPageTitles($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false) { - $dataTable = Archive::getDataTableFromArchive('Actions_actions', $idSite, $period, $date, $segment, $expanded, $idSubtable); + $dataTable = $this->getDataTableFromArchive('Actions_actions', $idSite, $period, $date, $segment, $expanded, $idSubtable); $this->filterPageDatatable($dataTable); $this->filterActionsDataTable($dataTable, $expanded); return $dataTable; @@ -248,7 +248,7 @@ public function getPageTitle($pageName, $idSite, $period, $date, $segment = fals public function getDownloads($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false) { - $dataTable = Archive::getDataTableFromArchive('Actions_downloads', $idSite, $period, $date, $segment, $expanded, $idSubtable); + $dataTable = $this->getDataTableFromArchive('Actions_downloads', $idSite, $period, $date, $segment, $expanded, $idSubtable); $this->filterActionsDataTable($dataTable, $expanded); return $dataTable; } @@ -263,7 +263,7 @@ public function getDownload($downloadUrl, $idSite, $period, $date, $segment = fa public function getOutlinks($idSite, $period, $date, $segment = false, $expanded = false, $idSubtable = false) { - $dataTable = Archive::getDataTableFromArchive('Actions_outlink', $idSite, $period, $date, $segment, $expanded, $idSubtable); + $dataTable = $this->getDataTableFromArchive('Actions_outlink', $idSite, $period, $date, $segment, $expanded, $idSubtable); $this->filterActionsDataTable($dataTable, $expanded); return $dataTable; } @@ -299,7 +299,7 @@ protected function addPagesPerSearchColumn($dataTable, $columnToRead = 'nb_hits' protected function getSiteSearchKeywordsRaw($idSite, $period, $date, $segment) { - $dataTable = Archive::getDataTableFromArchive('Actions_sitesearch', $idSite, $period, $date, $segment, $expanded = false); + $dataTable = $this->getDataTableFromArchive('Actions_sitesearch', $idSite, $period, $date, $segment, $expanded = false); return $dataTable; } @@ -396,7 +396,7 @@ protected function getFilterPageDatatableSearch($callBackParameters, $search, $a if ($table === false) { // fetch the data table - $table = call_user_func_array(array('Piwik\Archive', 'getDataTableFromArchive'), $callBackParameters); + $table = call_user_func_array(array($this, 'getDataTableFromArchive'), $callBackParameters); if ($table instanceof DataTable\Map) { // search an array of tables, e.g. when using date=last30 @@ -460,7 +460,7 @@ protected function doFilterPageDatatableSearch($callBackParameters, $table, $sea // match found on this level and more levels remaining: go deeper $idSubTable = $row->getIdSubDataTable(); $callBackParameters[6] = $idSubTable; - $table = call_user_func_array(array('Piwik\Archive', 'getDataTableFromArchive'), $callBackParameters); + $table = call_user_func_array(array($this, 'getDataTableFromArchive'), $callBackParameters); return $this->doFilterPageDatatableSearch($callBackParameters, $table, $searchTree); } @@ -552,4 +552,16 @@ private function filterNonExitActions($dataTable) { $dataTable->filter('ColumnCallbackDeleteRow', array('exit_nb_visits', function ($visits) { return !strlen($visits); })); } + + protected function getDataTableFromArchive($name, $idSite, $period, $date, $segment, $expanded = false, $idSubtable = null, $depth = null) + { + $skipAggregationOfSubTables = false; + if($period == 'range' + && empty($idSubtable) + && empty($expanded) + && !Request::shouldLoadFlatten()) { + $skipAggregationOfSubTables = true; + } + return Archive::getDataTableFromArchive($name, $idSite, $period, $date, $segment, $expanded, $idSubtable, $skipAggregationOfSubTables, $depth); + } } diff --git a/tests/PHPUnit/Fixtures/SomeVisitsCustomVariablesCampaignsNotHeuristics.php b/tests/PHPUnit/Fixtures/SomeVisitsCustomVariablesCampaignsNotHeuristics.php index 71017f77d61..fd587ff2bc4 100644 --- a/tests/PHPUnit/Fixtures/SomeVisitsCustomVariablesCampaignsNotHeuristics.php +++ b/tests/PHPUnit/Fixtures/SomeVisitsCustomVariablesCampaignsNotHeuristics.php @@ -123,22 +123,35 @@ private function trackVisits() self::checkResponse($t4->doTrackPageView('Bonjour le monde')); } + // see updateDomainHash() in piwik.js + private function getFirstPartyCookieDomainHash() + { + $host = \Piwik\Url::getHost(); + $cookiePath = PiwikTracker::DEFAULT_COOKIE_PATH; + return substr(sha1( $host . $cookiePath), 0, 4); + } + /** * Test setting/getting the first party cookie via the PHP Tracking Client * @param $t */ private function testFirstPartyCookies(PiwikTracker $t) { + $domainHash = $this->getFirstPartyCookieDomainHash(); + $idCookieName = '_pk_id_1_' . $domainHash; + $refCookieName = '_pk_ref_1_' . $domainHash; + $customVarCookieName = '_pk_cvar_1_' . $domainHash; + $viewts = '1302307497'; $uuid = 'ca0afe7b6b692ff5'; - $_COOKIE['_pk_id_1_1fff'] = $uuid . '.1302307497.1.' . $viewts . '.1302307497'; - $_COOKIE['_pk_ref_1_1fff'] = '["YEAH","RIGHT!",1302307497,"http://referrer.example.org/page/sub?query=test&test2=test3"]'; - $_COOKIE['_pk_cvar_1_1fff'] = '{"1":["VAR 1 set, var 2 not set","yes"],"3":["var 3 set","yes!!!!"]}'; + $_COOKIE[$idCookieName] = $uuid . '.1302307497.1.' . $viewts . '.1302307497'; + $_COOKIE[$refCookieName] = '["YEAH","RIGHT!",1302307497,"http://referrer.example.org/page/sub?query=test&test2=test3"]'; + $_COOKIE[$customVarCookieName] = '{"1":["VAR 1 set, var 2 not set","yes"],"3":["var 3 set","yes!!!!"]}'; // test loading 'id' cookie self::assertContains("_viewts=" . $viewts, $t->getUrlTrackPageView()); self::assertEquals($uuid, $t->getVisitorId()); - self::assertEquals($t->getAttributionInfo(), $_COOKIE['_pk_ref_1_1fff']); + self::assertEquals($t->getAttributionInfo(), $_COOKIE[$refCookieName]); self::assertEquals(array("VAR 1 set, var 2 not set", "yes"), $t->getCustomVariable(1)); self::assertFalse($t->getCustomVariable(2)); self::assertEquals(array("var 3 set", "yes!!!!"), $t->getCustomVariable(3)); @@ -147,8 +160,8 @@ private function testFirstPartyCookies(PiwikTracker $t) self::assertFalse($t->getCustomVariable(6)); self::assertFalse($t->getCustomVariable(-1)); - unset($_COOKIE['_pk_id_1_1fff']); - unset($_COOKIE['_pk_ref_1_1fff']); - unset($_COOKIE['_pk_cvar_1_1fff']); + unset($_COOKIE[$idCookieName]); + unset($_COOKIE[$refCookieName]); + unset($_COOKIE[$customVarCookieName]); } } diff --git a/tests/PHPUnit/Fixtures/userAgentParserEnhancedFixtures.yml b/tests/PHPUnit/Fixtures/userAgentParserEnhancedFixtures.yml index 1cb0a328750..28b4d3d6b66 100644 --- a/tests/PHPUnit/Fixtures/userAgentParserEnhancedFixtures.yml +++ b/tests/PHPUnit/Fixtures/userAgentParserEnhancedFixtures.yml @@ -4814,6 +4814,22 @@ model: os_family: Mac browser_family: Unknown +- + user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 1091) AppleWebKit/537.36 (KHTML like Gecko) Chrome/33.0.1750.91 Safari/537.36 OPR/20.0.1387.37 (Edition Next) + os: + name: Mac + short_name: MAC + version: + browser: + name: Opera Next + short_name: ON + version: 20.0 + device: + type: desktop + brand: + model: + os_family: Mac + browser_family: Opera - user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1; en-US) AppleWebKit/9537.73.11 (KHTML, like Gecko) Version/7.0 Safari/537.71 OmniWeb/v624.0' os: @@ -5742,6 +5758,22 @@ model: os_family: Windows browser_family: Unknown +- + user_agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/33.0.1750.91 Safari/537.36 OPR/20.0.1387.37 (Edition Next-Campaign 21) + os: + name: Windows 7 + short_name: WI7 + version: 7 + browser: + name: Opera Next + short_name: ON + version: 20.0 + device: + type: desktop + brand: + model: + os_family: Windows + browser_family: Opera - user_agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 OPR/18.0.1284.49 os: @@ -5934,6 +5966,22 @@ model: os_family: Windows browser_family: Opera +- + user_agent: Opera/9.80 (Windows NT 6.2; U; Edition Next; ru) Presto/2.11 Version/12.50 + os: + name: Windows 8 + short_name: WI8 + version: 8 + browser: + name: Opera Next + short_name: ON + version: 12.50 + device: + type: desktop + brand: + model: + os_family: Windows + browser_family: Opera - user_agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36 OPR/18.0.1284.68 os: @@ -6206,6 +6254,22 @@ model: os_family: Windows browser_family: Internet Explorer +- + user_agent: Opera/9.80 (Windows NT 6.0; Edition Next) Presto/2.12 Version/12.10 + os: + name: Windows Vista + short_name: WVI + version: Vista + browser: + name: Opera Next + short_name: ON + version: 12.10 + device: + type: desktop + brand: + model: + os_family: Windows + browser_family: Opera - user_agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Avant Browser; InfoPath.1) os: @@ -22189,68 +22253,4 @@ brand: WB model: os_family: WebTV - browser_family: Internet Explorer -- - user_agent: Opera/9.80 (Windows NT 6.0; Edition Next) Presto/2.12 Version/12.10 - os: - name: Windows Vista - short_name: WVI - version: Vista - browser: - name: Opera Next - short_name: ON - version: 12.10 - device: - type: desktop - brand: - model: - os_family: Windows - browser_family: Opera -- - user_agent: Opera/9.80 (Windows NT 6.2; U; Edition Next; ru) Presto/2.11 Version/12.50 - os: - name: Windows 8 - short_name: WI8 - version: 8 - browser: - name: Opera Next - short_name: ON - version: 12.50 - device: - type: desktop - brand: - model: - os_family: Windows - browser_family: Opera -- - user_agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 1091) AppleWebKit/537.36 (KHTML like Gecko) Chrome/33.0.1750.91 Safari/537.36 OPR/20.0.1387.37 (Edition Next) - os: - name: Mac - short_name: MAC - version: - browser: - name: Opera Next - short_name: ON - version: 20.0 - device: - type: desktop - brand: - model: - os_family: Mac - browser_family: Opera -- - user_agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/33.0.1750.91 Safari/537.36 OPR/20.0.1387.37 (Edition Next-Campaign 21) - os: - name: Windows 7 - short_name: WI7 - version: 7 - browser: - name: Opera Next - short_name: ON - version: 20.0 - device: - type: desktop - brand: - model: - os_family: Windows - browser_family: Opera \ No newline at end of file + browser_family: Internet Explorer \ No newline at end of file diff --git a/tests/PHPUnit/Integration/OneVisitorOneWebsite_SeveralDaysDateRange_ArchivingTestsTest.php b/tests/PHPUnit/Integration/OneVisitorOneWebsite_SeveralDaysDateRange_ArchivingTestsTest.php index b751a1b4a58..6c8997b935c 100755 --- a/tests/PHPUnit/Integration/OneVisitorOneWebsite_SeveralDaysDateRange_ArchivingTestsTest.php +++ b/tests/PHPUnit/Integration/OneVisitorOneWebsite_SeveralDaysDateRange_ArchivingTestsTest.php @@ -54,18 +54,34 @@ public function getApiForTesting() for ($i = 0; $i <= 1; $i++) { foreach ($segments as $segment) { $result[] = array($apiToCall, array('idSite' => $idSite, 'date' => '2010-12-15,2011-01-15', - 'periods' => array('range'), 'segment' => $segment)); + 'periods' => array('range'), + 'segment' => $segment, + 'otherRequestParameters' => array( + 'flat' => '0', + 'expanded' => '0' + ), + )); } } // Testing Date range in January only // Because of flat=1, this test will archive all sub-tables $result[] = array('Actions.getPageUrls', array('idSite' => $idSite, 'date' => '2011-01-01,2011-02-01', - 'periods' => array('range'), - 'otherRequestParameters' => array( - 'flat' => '1', - ), - 'testSuffix' => '_periodIsRange_flattened_') + 'periods' => array('range'), + 'otherRequestParameters' => array( + 'flat' => '1', + 'expanded' => '0' + ), + 'testSuffix' => '_periodIsRange_flattened_') + ); + // testing the same with expanded=1 should not create new archive records + $result[] = array('Actions.getPageUrls', array('idSite' => $idSite, 'date' => '2011-01-01,2011-02-01', + 'periods' => array('range'), + 'otherRequestParameters' => array( + 'flat' => '0', + 'expanded' => '1' + ), + 'testSuffix' => '_periodIsRange_expanded_') ); return $result; } @@ -88,8 +104,7 @@ public function test_checkArchiveRecords_whenPeriodIsRange() $expectedActionsBlobsWhenFlattened = $expectedActionsBlobs + 3; $tests = array( - // TODO Implement fix, then remove the +3 below - 'archive_blob_2010_12' => ( ($expectedActionsBlobs+3) /*Actions*/ + 'archive_blob_2010_12' => ( $expectedActionsBlobs /*Actions*/ + 8 /* UserSettings */ + 2 /* VisitTime */) * 3, @@ -137,12 +152,31 @@ public function test_checkArchiveRecords_whenPeriodIsRange() $countBlobs = Db::get()->fetchOne($sql); if($expectedRows != $countBlobs) { - var_export(Db::get()->fetchAll("SELECT * FROM " . Common::prefixTable($table). " WHERE period = " . Piwik::$idPeriods['range'] . " ORDER BY idarchive ASC")); + $this->printDebugWhenTestFails($table); } $this->assertEquals($expectedRows, $countBlobs, "$table expected $expectedRows, got $countBlobs"); } } + /** + * @param $table + */ + protected function printDebugWhenTestFails($table) + { + $data = Db::get()->fetchAll("SELECT * FROM " . Common::prefixTable($table) . " WHERE period = " . Piwik::$idPeriods['range'] . " ORDER BY idarchive ASC"); + var_export($data); + + $idArchives = array(); + foreach ($data as $row) { + $idArchives[] = $row['idarchive']; + } + $idArchives = array_unique($idArchives); + foreach ($idArchives as $idArchive) { + $numericTable = str_replace("blob", "numeric", Common::prefixTable($table)); + var_export(Db::get()->fetchAll("SELECT idarchive, name FROM " . $numericTable . " WHERE idarchive = ? AND name LIKE 'done%' LIMIT 1 ", $idArchive)); + } + } + } Test_Piwik_Integration_OneVisitorOneWebsite_SeveralDaysDateRange_ArchivingTests::$fixture diff --git a/tests/PHPUnit/Integration/expected/test_oneVisitor_oneWebsite_severalDays_DateRange__Actions.getPageUrls_range.xml b/tests/PHPUnit/Integration/expected/test_oneVisitor_oneWebsite_severalDays_DateRange__Actions.getPageUrls_range.xml index c9d04097521..62ee4df14dc 100644 --- a/tests/PHPUnit/Integration/expected/test_oneVisitor_oneWebsite_severalDays_DateRange__Actions.getPageUrls_range.xml +++ b/tests/PHPUnit/Integration/expected/test_oneVisitor_oneWebsite_severalDays_DateRange__Actions.getPageUrls_range.xml @@ -43,44 +43,5 @@ 0 0% 100% - - - - 3 - 3 - 0 - 3 - 0 - 0% - 100% - - - - 3 - 3 - 0 - 3 - 0 - 0% - 100% - - - - 3 - 3 - 0 - 3 - 2 - 2 - 0 - 0% - 100% - http://example.org/sub1/sub2/sub3/news - - - - - - \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_oneVisitor_oneWebsite_severalDays_DateRange_periodIsRange_flattened___Actions.getPageUrls_range.xml b/tests/PHPUnit/Integration/expected/test_oneVisitor_oneWebsite_severalDays_DateRange_periodIsRange_flattened___Actions.getPageUrls_range.xml index bd8b87ef40d..1f11de6d952 100644 --- a/tests/PHPUnit/Integration/expected/test_oneVisitor_oneWebsite_severalDays_DateRange_periodIsRange_flattened___Actions.getPageUrls_range.xml +++ b/tests/PHPUnit/Integration/expected/test_oneVisitor_oneWebsite_severalDays_DateRange_periodIsRange_flattened___Actions.getPageUrls_range.xml @@ -34,4 +34,17 @@ 100% http://example.org/news + + + 2 + 2 + 0 + 2 + 2 + 2 + 0 + 0% + 100% + http://example.org/sub1/sub2/sub3/news + \ No newline at end of file diff --git a/tests/PHPUnit/UI b/tests/PHPUnit/UI index f18a9102aa4..f744d26a33b 160000 --- a/tests/PHPUnit/UI +++ b/tests/PHPUnit/UI @@ -1 +1 @@ -Subproject commit f18a9102aa434db63bfdd2c6d47d9ee4fca77581 +Subproject commit f744d26a33b64570a039d65c23c7dfaaff1a245a diff --git a/tests/lib/screenshot-testing/support/app.js b/tests/lib/screenshot-testing/support/app.js index ee9ad303140..8a67e68ed6f 100644 --- a/tests/lib/screenshot-testing/support/app.js +++ b/tests/lib/screenshot-testing/support/app.js @@ -105,7 +105,7 @@ Application.prototype.loadTestModules = function () { // configure suites (auto-add fixture setup/teardown) mocha.suite.suites.forEach(function (suite) { - var fixture = suite.fixture || 'UITestFixture'; + var fixture = typeof suite.fixture === 'undefined' ? 'UITestFixture' : suite.fixture; suite.beforeAll(function (done) { testEnvironment.setupFixture(fixture, done); @@ -115,6 +115,11 @@ Application.prototype.loadTestModules = function () { suite._beforeAll.unshift(suite._beforeAll.pop()); suite.afterAll(function (done) { + if (!fixture) { + done(); + return; + } + testEnvironment.teardownFixture(fixture, done); }); }); diff --git a/tests/lib/screenshot-testing/support/setupDatabase.php b/tests/lib/screenshot-testing/support/setupDatabase.php index e91e4ffd16f..e4efccb0e74 100644 --- a/tests/lib/screenshot-testing/support/setupDatabase.php +++ b/tests/lib/screenshot-testing/support/setupDatabase.php @@ -20,19 +20,21 @@ require_once "PHPUnit/Autoload.php"; require_once dirname(__FILE__) . "/../../../PHPUnit/bootstrap.php"; -if (!class_exists($fixtureClass)) { - $fixtureClass = "Piwik\\Tests\\Fixtures\\$fixtureClass"; -} +if (!empty($fixtureClass)) { + if (!class_exists($fixtureClass)) { + $fixtureClass = "Piwik\\Tests\\Fixtures\\$fixtureClass"; + } -$fixture = new $fixtureClass(); -if (in_array("--persist-fixture-data", $argv)) { - $fixture->persistFixtureData = true; -} -if (in_array("--drop", $argv)) { - $fixture->resetPersistedFixture = true; + $fixture = new $fixtureClass(); + if (in_array("--persist-fixture-data", $argv)) { + $fixture->persistFixtureData = true; + } + if (in_array("--drop", $argv)) { + $fixture->resetPersistedFixture = true; + } + $fixture->printToScreen = true; + $fixture->performSetUp(""); } -$fixture->printToScreen = true; -$fixture->performSetUp(""); // make sure symbolic links exist (phantomjs doesn't support symlink-ing yet) foreach (array('libs', 'plugins', 'tests', 'piwik.js') as $linkName) { diff --git a/tests/lib/screenshot-testing/support/test-environment.js b/tests/lib/screenshot-testing/support/test-environment.js index c371d444e31..7096b2af26b 100644 --- a/tests/lib/screenshot-testing/support/test-environment.js +++ b/tests/lib/screenshot-testing/support/test-environment.js @@ -88,7 +88,7 @@ TestingEnvironment.prototype.setupFixture = function (fixtureClass, done) { console.log(" Setting up fixture " + fixtureClass + "..."); var setupFile = path.join("./support", "setupDatabase.php"), - processArgs = [setupFile, "--server=" + JSON.stringify(config.phpServer), "--fixture=" + fixtureClass]; + processArgs = [setupFile, "--server=" + JSON.stringify(config.phpServer), "--fixture=" + (fixtureClass || "")]; if (options['persist-fixture-data']) { processArgs.push('--persist-fixture-data');