diff options
author | Thomas Steur <thomas.steur@googlemail.com> | 2014-09-30 09:37:32 +0400 |
---|---|---|
committer | Thomas Steur <thomas.steur@googlemail.com> | 2014-09-30 09:37:32 +0400 |
commit | a00487b0b841c4b15463b591c7f62176c4b84d15 (patch) | |
tree | 6eb893ce356a4740e044c9cdadaf84ffb2095b9d | |
parent | 0edef3332289a7cbe54b58084b967907d1086d29 (diff) |
coding style fixes, some PHPStorm inspection fixes, improved readability of code, few refactorings, all as part of our code cleanup strategy
228 files changed, 2632 insertions, 1541 deletions
diff --git a/core/API/DataTableManipulator.php b/core/API/DataTableManipulator.php index 69dc62063b..30513daaf3 100644 --- a/core/API/DataTableManipulator.php +++ b/core/API/DataTableManipulator.php @@ -141,6 +141,7 @@ abstract class DataTableManipulator /** * Extract the API method for loading subtables from the meta data * + * @throws Exception * @return string */ private function getApiMethodForSubtable() @@ -148,7 +149,7 @@ abstract class DataTableManipulator if (!$this->apiMethodForSubtable) { $meta = API::getInstance()->getMetadata('all', $this->apiModule, $this->apiMethod); - if(empty($meta)) { + if (empty($meta)) { throw new Exception(sprintf( "The DataTable cannot be manipulated: Metadata for report %s.%s could not be found. You can define the metadata in a hook, see example at: http://developer.piwik.org/api-reference/events#apigetreportmetadata", $this->apiModule, $this->apiMethod diff --git a/core/API/DataTableManipulator/Flattener.php b/core/API/DataTableManipulator/Flattener.php index 211af52d2b..cfee16e6ba 100644 --- a/core/API/DataTableManipulator/Flattener.php +++ b/core/API/DataTableManipulator/Flattener.php @@ -127,6 +127,7 @@ class Flattener extends DataTableManipulator * Remove the flat parameter from the subtable request * * @param array $request + * @return array */ protected function manipulateSubtableRequest($request) { diff --git a/core/API/DataTableManipulator/ReportTotalsCalculator.php b/core/API/DataTableManipulator/ReportTotalsCalculator.php index 1dc3bc85d9..1cbfeeb362 100644 --- a/core/API/DataTableManipulator/ReportTotalsCalculator.php +++ b/core/API/DataTableManipulator/ReportTotalsCalculator.php @@ -194,6 +194,7 @@ class ReportTotalsCalculator extends DataTableManipulator * Make sure to get all rows of the first level table. * * @param array $request + * @return array */ protected function manipulateSubtableRequest($request) { diff --git a/core/API/DocumentationGenerator.php b/core/API/DocumentationGenerator.php index 668f97bb60..63ae943433 100644 --- a/core/API/DocumentationGenerator.php +++ b/core/API/DocumentationGenerator.php @@ -47,8 +47,8 @@ class DocumentationGenerator if (!empty($prefixUrls)) { $prefixUrls = 'http://demo.piwik.org/'; } + $str = $toc = ''; - $token_auth = "&token_auth=" . Piwik::getCurrentUserTokenAuth(); $parametersToSet = array( 'idSite' => Common::getRequestVar('idSite', 1, 'int'), 'period' => Common::getRequestVar('period', 'day', 'string'), @@ -57,52 +57,38 @@ class DocumentationGenerator foreach (Proxy::getInstance()->getMetadata() as $class => $info) { $moduleName = Proxy::getInstance()->getModuleNameFromClassName($class); + if (in_array($moduleName, $this->modulesToHide)) { continue; } + $toc .= "<a href='#$moduleName'>$moduleName</a><br/>"; - $str .= "\n<a name='$moduleName' id='$moduleName'></a><h2>Module " . $moduleName . "</h2>"; - $str .= "<div class='apiDescription'> " . $info['__documentation'] . " </div>"; - foreach ($info as $methodName => $infoMethod) { - if ($methodName == '__documentation') { - continue; - } - $params = $this->getParametersString($class, $methodName); - $str .= "\n <div class='apiMethod'>- <b>$moduleName.$methodName </b>" . $params . ""; - $str .= '<small>'; - - if ($outputExampleUrls) { - // we prefix all URLs with $prefixUrls - // used when we include this output in the Piwik official documentation for example - $str .= "<span class=\"example\">"; - $exampleUrl = $this->getExampleUrl($class, $methodName, $parametersToSet); - if ($exampleUrl !== false) { - $lastNUrls = ''; - if (preg_match('/(&period)|(&date)/', $exampleUrl)) { - $exampleUrlRss = $prefixUrls . $this->getExampleUrl($class, $methodName, array('date' => 'last10', 'period' => 'day') + $parametersToSet); - $lastNUrls = ", RSS of the last <a target=_blank href='$exampleUrlRss&format=rss$token_auth&translateColumnNames=1'>10 days</a>"; - } - $exampleUrl = $prefixUrls . $exampleUrl; - $str .= " [ Example in - <a target=_blank href='$exampleUrl&format=xml$token_auth'>XML</a>, - <a target=_blank href='$exampleUrl&format=JSON$token_auth'>Json</a>, - <a target=_blank href='$exampleUrl&format=Tsv$token_auth&translateColumnNames=1'>Tsv (Excel)</a> - $lastNUrls - ]"; - } else { - $str .= " [ No example available ]"; - } - $str .= "</span>"; - } - $str .= '</small>'; - $str .= "</div>\n"; - } - $str .= '<div style="margin:15px;"><a href="#topApiRef">↑ Back to top</a></div>'; + $str .= $this->getInterfaceString($moduleName, $class, $info, $parametersToSet, $outputExampleUrls, $prefixUrls); } $str = "<h2 id='topApiRef' name='topApiRef'>Quick access to APIs</h2> $toc $str"; + + return $str; + } + + private function getInterfaceString($moduleName, $class, $info, $parametersToSet, $outputExampleUrls, $prefixUrls) + { + $str = ''; + + $str .= "\n<a name='$moduleName' id='$moduleName'></a><h2>Module " . $moduleName . "</h2>"; + $str .= "<div class='apiDescription'> " . $info['__documentation'] . " </div>"; + foreach ($info as $methodName => $infoMethod) { + if ($methodName == '__documentation') { + continue; + } + + $str .= $this->getMethodString($moduleName, $class, $parametersToSet, $outputExampleUrls, $prefixUrls, $methodName, $str); + } + + $str .= '<div style="margin:15px;"><a href="#topApiRef">↑ Back to top</a></div>'; + return $str; } @@ -241,4 +227,43 @@ class DocumentationGenerator $sParameters = implode(", ", $asParameters); return "($sParameters)"; } + + private function getMethodString($moduleName, $class, $parametersToSet, $outputExampleUrls, $prefixUrls, $methodName) + { + $str = ''; + $token_auth = "&token_auth=" . Piwik::getCurrentUserTokenAuth(); + + $params = $this->getParametersString($class, $methodName); + $str .= "\n <div class='apiMethod'>- <b>$moduleName.$methodName </b>" . $params . ""; + $str .= '<small>'; + + if ($outputExampleUrls) { + // we prefix all URLs with $prefixUrls + // used when we include this output in the Piwik official documentation for example + $str .= "<span class=\"example\">"; + $exampleUrl = $this->getExampleUrl($class, $methodName, $parametersToSet); + if ($exampleUrl !== false) { + $lastNUrls = ''; + if (preg_match('/(&period)|(&date)/', $exampleUrl)) { + $exampleUrlRss = $prefixUrls . $this->getExampleUrl($class, $methodName, array('date' => 'last10', 'period' => 'day') + $parametersToSet); + $lastNUrls = ", RSS of the last <a target=_blank href='$exampleUrlRss&format=rss$token_auth&translateColumnNames=1'>10 days</a>"; + } + $exampleUrl = $prefixUrls . $exampleUrl; + $str .= " [ Example in + <a target=_blank href='$exampleUrl&format=xml$token_auth'>XML</a>, + <a target=_blank href='$exampleUrl&format=JSON$token_auth'>Json</a>, + <a target=_blank href='$exampleUrl&format=Tsv$token_auth&translateColumnNames=1'>Tsv (Excel)</a> + $lastNUrls + ]"; + } else { + $str .= " [ No example available ]"; + } + $str .= "</span>"; + } + + $str .= '</small>'; + $str .= "</div>\n"; + + return $str; + } } diff --git a/core/API/Proxy.php b/core/API/Proxy.php index d3e1fbad3f..daaa5c9f42 100644 --- a/core/API/Proxy.php +++ b/core/API/Proxy.php @@ -24,7 +24,7 @@ use ReflectionMethod; * * It will also log the performance of API calls (time spent, parameter values, etc.) if logger available * - * @method static \Piwik\API\Proxy getInstance() + * @method static Proxy getInstance() */ class Proxy extends Singleton { diff --git a/core/API/Request.php b/core/API/Request.php index 03b555ad18..64e8e054fa 100644 --- a/core/API/Request.php +++ b/core/API/Request.php @@ -70,7 +70,7 @@ use Piwik\Log; */ class Request { - protected $request = null; + private $request = null; /** * Converts the supplied request string into an array of query paramater name/value diff --git a/core/API/ResponseBuilder.php b/core/API/ResponseBuilder.php index 17d5d488f7..401dccf96c 100644 --- a/core/API/ResponseBuilder.php +++ b/core/API/ResponseBuilder.php @@ -18,7 +18,6 @@ use Piwik\DataTable\Filter\PivotByDimension; use Piwik\DataTable\Renderer; use Piwik\DataTable\DataTableInterface; use Piwik\DataTable\Filter\ColumnDelete; -use Piwik\Piwik; /** */ @@ -158,7 +157,7 @@ class ResponseBuilder return Renderer::formatValueXml($message); } - protected function handleDataTable(DataTableInterface $datatable) + private function handleDataTable(DataTableInterface $datatable) { $label = $this->getLabelFromRequest($this->request); @@ -224,7 +223,7 @@ class ResponseBuilder return $this->apiRenderer->renderDataTable($datatable); } - protected function handleArray($array) + private function handleArray($array) { $firstArray = null; $firstKey = null; diff --git a/core/Access.php b/core/Access.php index 00093e6e4f..d18310cb5b 100644 --- a/core/Access.php +++ b/core/Access.php @@ -33,29 +33,6 @@ use Piwik\Db; */ class Access { - private static $instance = null; - - /** - * Gets the singleton instance. Creates it if necessary. - */ - public static function getInstance() - { - if (self::$instance == null) { - self::$instance = new self; - - Piwik::postEvent('Access.createAccessSingleton', array(&self::$instance)); - } - return self::$instance; - } - - /** - * Sets the singleton instance. For testing purposes. - */ - public static function setSingletonInstance($instance) - { - self::$instance = $instance; - } - /** * Array of idsites available to the current user, indexed by permission level * @see getSitesIdWith*() @@ -100,6 +77,29 @@ class Access */ private $auth = null; + private static $instance = null; + + /** + * Gets the singleton instance. Creates it if necessary. + */ + public static function getInstance() + { + if (self::$instance == null) { + self::$instance = new self; + + Piwik::postEvent('Access.createAccessSingleton', array(&self::$instance)); + } + return self::$instance; + } + + /** + * Sets the singleton instance. For testing purposes. + */ + public static function setSingletonInstance($instance) + { + self::$instance = $instance; + } + /** * Returns the list of the existing Access level. * Useful when a given API method requests a given acccess Level. @@ -146,6 +146,7 @@ class Access if ($this->hasSuperUserAccess()) { return $this->reloadAccessSuperUser(); } + return false; } @@ -155,6 +156,7 @@ class Access if (!$result->wasAuthenticationSuccessful()) { return false; } + $this->login = $result->getIdentity(); $this->token_auth = $result->getTokenAuth(); @@ -162,21 +164,26 @@ class Access if ($result->hasSuperUserAccess()) { return $this->reloadAccessSuperUser(); } + // in case multiple calls to API using different tokens, we ensure we reset it as not SU $this->setSuperUserAccess(false); // we join with site in case there are rows in access for an idsite that doesn't exist anymore // (backward compatibility ; before we deleted the site without deleting rows in _access table) $accessRaw = $this->getRawSitesWithSomeViewAccess($this->login); + foreach ($accessRaw as $access) { $this->idsitesByAccess[$access['access']][] = $access['idsite']; } + return true; } public function getRawSitesWithSomeViewAccess($login) { - return Db::fetchAll(self::getSqlAccessSite("access, t2.idsite"), $login); + $sql = self::getSqlAccessSite("access, t2.idsite"); + + return Db::fetchAll($sql, $login); } /** @@ -187,10 +194,11 @@ class Access */ public static function getSqlAccessSite($select) { - return "SELECT " . $select . " - FROM " . Common::prefixTable('access') . " as t1 - JOIN " . Common::prefixTable('site') . " as t2 USING (idsite) " . - " WHERE login = ?"; + $access = Common::prefixTable('access'); + $siteTable = Common::prefixTable('site'); + + return "SELECT " . $select . " FROM " . $access . " as t1 + JOIN " . $siteTable . " as t2 USING (idsite) WHERE login = ?"; } /** @@ -323,7 +331,9 @@ class Access if ($this->hasSuperUserAccess()) { return; } + $idSitesAccessible = $this->getSitesIdWithAdminAccess(); + if (count($idSitesAccessible) == 0) { throw new NoAccessException(Piwik::translate('General_ExceptionPrivilegeAtLeastOneWebsite', array('admin'))); } @@ -339,7 +349,9 @@ class Access if ($this->hasSuperUserAccess()) { return; } + $idSitesAccessible = $this->getSitesIdWithAtLeastViewAccess(); + if (count($idSitesAccessible) == 0) { throw new NoAccessException(Piwik::translate('General_ExceptionPrivilegeAtLeastOneWebsite', array('view'))); } @@ -357,8 +369,10 @@ class Access if ($this->hasSuperUserAccess()) { return; } + $idSites = $this->getIdSites($idSites); $idSitesAccessible = $this->getSitesIdWithAdminAccess(); + foreach ($idSites as $idsite) { if (!in_array($idsite, $idSitesAccessible)) { throw new NoAccessException(Piwik::translate('General_ExceptionPrivilegeAccessWebsite', array("'admin'", $idsite))); @@ -378,8 +392,10 @@ class Access if ($this->hasSuperUserAccess()) { return; } + $idSites = $this->getIdSites($idSites); $idSitesAccessible = $this->getSitesIdWithAtLeastViewAccess(); + foreach ($idSites as $idsite) { if (!in_array($idsite, $idSitesAccessible)) { throw new NoAccessException(Piwik::translate('General_ExceptionPrivilegeAccessWebsite', array("'view'", $idsite))); @@ -399,9 +415,11 @@ class Access } $idSites = Site::getIdSitesFromIdSitesString($idSites); + if (empty($idSites)) { throw new NoAccessException("The parameter 'idSite=' is missing from the request."); } + return $idSites; } } diff --git a/core/Archive.php b/core/Archive.php index 65b5b91532..7101850c1d 100644 --- a/core/Archive.php +++ b/core/Archive.php @@ -197,18 +197,23 @@ class Archive { $websiteIds = Site::getIdSitesFromIdSitesString($idSites, $_restrictSitesToLogin); - $timezone = count($websiteIds) == 1 ? Site::getTimezoneFor($websiteIds[0]) : false; + $timezone = false; + if (count($websiteIds) == 1) { + $timezone = Site::getTimezoneFor($websiteIds[0]); + } if (Period::isMultiplePeriod($strDate, $period)) { - $oPeriod = PeriodFactory::build($period, $strDate, $timezone); + $oPeriod = PeriodFactory::build($period, $strDate, $timezone); $allPeriods = $oPeriod->getSubperiods(); } else { - $oPeriod = PeriodFactory::makePeriodFromQueryParams($timezone, $period, $strDate); + $oPeriod = PeriodFactory::makePeriodFromQueryParams($timezone, $period, $strDate); $allPeriods = array($oPeriod); } - $segment = new Segment($segment, $websiteIds); - $idSiteIsAll = $idSites == self::REQUEST_ALL_WEBSITES_FLAG; + + $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, $skipAggregationOfSubTables); } @@ -239,9 +244,11 @@ class Archive { $forceIndexedBySite = false; $forceIndexedByDate = false; + if ($idSiteIsAll || count($idSites) > 1) { $forceIndexedBySite = true; } + if (count($periods) > 1 || $isMultipleDate) { $forceIndexedByDate = true; } @@ -265,7 +272,7 @@ class Archive * * @param string|array $names One or more archive names, eg, `'nb_visits'`, `'Referrers_distinctKeywords'`, * etc. - * @return false|numeric|array `false` if there is no data to return, a single numeric value if we're not querying + * @return false|integer|array `false` if there is no data to return, a single numeric value if we're not querying * for multiple sites/periods, or an array if multiple sites, periods or names are * queried for. */ @@ -406,9 +413,11 @@ class Archive private function getRequestedPlugins($archiveNames) { $result = array(); + foreach ($archiveNames as $name) { $result[] = self::getPluginForReport($name); } + return array_unique($result); } @@ -436,6 +445,7 @@ class Archive * @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()} + * @throws \Exception * @return DataTable|DataTable\Map See {@link getDataTable()} and * {@link getDataTableExpanded()} for more * information @@ -445,9 +455,10 @@ class Archive { Piwik::checkUserHasViewAccess($idSite); - if($skipAggregationOfSubTables && ($expanded || $idSubtable)) { + 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; @@ -495,6 +506,7 @@ class Archive $archiveNames, $archiveDataType, $this->params->getIdSites(), $this->params->getPeriods(), $defaultRow = null); $archiveIds = $this->getArchiveIds($archiveNames); + if (empty($archiveIds)) { return $result; } @@ -532,7 +544,7 @@ class Archive // figure out which archives haven't been processed (if an archive has been processed, // then we have the archive IDs in $this->idarchives) - $doneFlags = array(); + $doneFlags = array(); $archiveGroups = array(); foreach ($plugins as $plugin) { $doneFlag = $this->getDoneStringForPlugin($plugin); @@ -541,7 +553,7 @@ class Archive if (!isset($this->idarchives[$doneFlag])) { $archiveGroup = $this->getArchiveGroupOfPlugin($plugin); - if($archiveGroup == self::ARCHIVE_ALL_PLUGINS_FLAG) { + if ($archiveGroup == self::ARCHIVE_ALL_PLUGINS_FLAG) { $archiveGroup = reset($plugins); } $archiveGroups[] = $archiveGroup; @@ -559,19 +571,7 @@ class Archive } } - // order idarchives by the table month they belong to - $idArchivesByMonth = array(); - foreach (array_keys($doneFlags) as $doneFlag) { - if (empty($this->idarchives[$doneFlag])) { - continue; - } - - foreach ($this->idarchives[$doneFlag] as $dateRange => $idarchives) { - foreach ($idarchives as $id) { - $idArchivesByMonth[$dateRange][] = $id; - } - } - } + $idArchivesByMonth = $this->getIdArchivesByMonth($doneFlags); return $idArchivesByMonth; } @@ -800,9 +800,29 @@ class Archive $idArchive = $archiveLoader->prepareArchive($plugin); - if($idArchive) { + if ($idArchive) { $this->idarchives[$doneFlag][$periodString][] = $idArchive; } } } + + private function getIdArchivesByMonth($doneFlags) + { + // order idarchives by the table month they belong to + $idArchivesByMonth = array(); + + foreach (array_keys($doneFlags) as $doneFlag) { + if (empty($this->idarchives[$doneFlag])) { + continue; + } + + foreach ($this->idarchives[$doneFlag] as $dateRange => $idarchives) { + foreach ($idarchives as $id) { + $idArchivesByMonth[$dateRange][] = $id; + } + } + } + + return $idArchivesByMonth; + } } diff --git a/core/Archive/DataCollection.php b/core/Archive/DataCollection.php index 89b435f9dc..efd63cd925 100644 --- a/core/Archive/DataCollection.php +++ b/core/Archive/DataCollection.php @@ -188,6 +188,7 @@ class DataCollection $this->putRowInIndex($result, $indexKeys, $row, $idSite, $period); } } + return $result; } @@ -208,6 +209,7 @@ class DataCollection $this->dataNames, $this->dataType, $this->sitesId, $this->periods, $this->defaultRow); $index = $this->getIndexedArray($resultIndices); + return $dataTableFactory->make($index, $resultIndices); } @@ -249,6 +251,7 @@ class DataCollection $dataTableFactory->useSubtable($idSubTable); $index = $this->getIndexedArray($resultIndices); + return $dataTableFactory->make($index, $resultIndices); } diff --git a/core/Archive/DataTableFactory.php b/core/Archive/DataTableFactory.php index 41806c62f9..71eaa7a8c1 100644 --- a/core/Archive/DataTableFactory.php +++ b/core/Archive/DataTableFactory.php @@ -154,6 +154,7 @@ class DataTableFactory } $this->transformMetadata($dataTable); + return $dataTable; } diff --git a/core/ArchiveProcessor.php b/core/ArchiveProcessor.php index 2df309d69c..71e90cde23 100644 --- a/core/ArchiveProcessor.php +++ b/core/ArchiveProcessor.php @@ -79,12 +79,12 @@ class ArchiveProcessor /** * @var \Piwik\DataAccess\ArchiveWriter */ - protected $archiveWriter; + private $archiveWriter; /** * @var \Piwik\DataAccess\LogAggregator */ - protected $logAggregator; + private $logAggregator; /** * @var Archive @@ -94,14 +94,14 @@ class ArchiveProcessor /** * @var Parameters */ - protected $params; + private $params; /** * @var int */ - protected $numberOfVisits = false; + private $numberOfVisits = false; - protected $numberOfVisitsConverted = false; + private $numberOfVisitsConverted = false; /** * If true, unique visitors are not calculated when we are aggregating data for multiple sites. @@ -125,11 +125,12 @@ class ArchiveProcessor protected function getArchive() { - if(empty($this->archive)) { + if (empty($this->archive)) { $subPeriods = $this->params->getSubPeriods(); - $idSites = $this->params->getIdSites(); + $idSites = $this->params->getIdSites(); $this->archive = Archive::factory($this->params->getSegment(), $subPeriods, $idSites); } + return $this->archive; } @@ -208,6 +209,7 @@ class ArchiveProcessor if (!is_array($recordNames)) { $recordNames = array($recordNames); } + $nameToCount = array(); foreach ($recordNames as $recordName) { $latestUsedTableId = Manager::getInstance()->getMostRecentTableId(); @@ -218,7 +220,7 @@ class ArchiveProcessor $nameToCount[$recordName]['level0'] = $rowsCount; $rowsCountRecursive = $rowsCount; - if($this->isAggregateSubTables()) { + if ($this->isAggregateSubTables()) { $rowsCountRecursive = $table->getRowsCountRecursive(); } $nameToCount[$recordName]['recursive'] = $rowsCountRecursive; @@ -271,7 +273,7 @@ class ArchiveProcessor public function getNumberOfVisits() { - if($this->numberOfVisits === false) { + if ($this->numberOfVisits === false) { throw new Exception("visits should have been set here"); } return $this->numberOfVisits; @@ -343,7 +345,7 @@ class ArchiveProcessor */ protected function aggregateDataTableRecord($name, $columnsAggregationOperation = null, $columnsToRenameAfterAggregation = null) { - if($this->isAggregateSubTables()) { + if ($this->isAggregateSubTables()) { // By default we shall aggregate all sub-tables. $dataTable = $this->getArchive()->getDataTableExpanded($name, $idSubTable = null, $depth = null, $addMetadataSubtableId = false); } else { @@ -440,15 +442,18 @@ class ArchiveProcessor protected function getAggregatedDataTableMap($data, $columnsAggregationOperation) { $table = new DataTable(); + if (!empty($columnsAggregationOperation)) { $table->setMetadata(DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME, $columnsAggregationOperation); } + if ($data instanceof DataTable\Map) { // as $date => $tableToSum $this->aggregatedDataTableMapsAsOne($data, $table); } else { $table->addDataTable($data, $this->isAggregateSubTables()); } + return $table; } @@ -460,7 +465,7 @@ class ArchiveProcessor protected function aggregatedDataTableMapsAsOne(Map $map, DataTable $aggregated) { foreach ($map->getDataTables() as $tableToAggregate) { - if($tableToAggregate instanceof Map) { + if ($tableToAggregate instanceof Map) { $this->aggregatedDataTableMapsAsOne($tableToAggregate, $aggregated); } else { $aggregated->addDataTable($tableToAggregate, $this->isAggregateSubTables()); @@ -477,6 +482,7 @@ class ArchiveProcessor if (is_null($columnsToRenameAfterAggregation)) { $columnsToRenameAfterAggregation = self::$columnsToRenameAfterAggregation; } + foreach ($columnsToRenameAfterAggregation as $oldName => $newName) { $table->renameColumn($oldName, $newName, $this->isAggregateSubTables()); } @@ -487,6 +493,7 @@ class ArchiveProcessor if (!is_array($columns)) { $columns = array($columns); } + $operationForColumn = $this->getOperationForColumns($columns, $operationToApply); $dataTable = $this->getArchive()->getDataTableFromNumeric($columns); @@ -497,7 +504,7 @@ class ArchiveProcessor } $rowMetrics = $results->getFirstRow(); - if($rowMetrics === false) { + if ($rowMetrics === false) { $rowMetrics = new Row; } $this->enrichWithUniqueVisitorsMetric($rowMetrics); @@ -510,6 +517,7 @@ class ArchiveProcessor $metrics[$name] = 0; } } + return $metrics; } diff --git a/core/ArchiveProcessor/Loader.php b/core/ArchiveProcessor/Loader.php index a4ffa4d12e..b684d8fee1 100644 --- a/core/ArchiveProcessor/Loader.php +++ b/core/ArchiveProcessor/Loader.php @@ -10,7 +10,6 @@ namespace Piwik\ArchiveProcessor; use Piwik\Archive; use Piwik\ArchiveProcessor; use Piwik\Config; -use Piwik\DataAccess\ArchivePurger; use Piwik\DataAccess\ArchiveSelector; use Piwik\Date; use Piwik\Period; @@ -82,6 +81,7 @@ class Loader * Prepares the core metrics if needed. * * @param $visits + * @return array */ protected function prepareCoreMetricsArchive($visits, $visitsConverted) { @@ -102,12 +102,14 @@ class Loader $visits = $metrics['nb_visits']; $visitsConverted = $metrics['nb_visits_converted']; } + return array($visits, $visitsConverted); } protected function prepareAllPluginsArchive($visits, $visitsConverted) { $pluginsArchiver = new PluginsArchiver($this->params, $this->isArchiveTemporary()); + if ($this->mustProcessVisitCount($visits) || $this->doesRequestedPluginIncludeVisitsSummary() ) { @@ -115,9 +117,11 @@ class Loader $visits = $metrics['nb_visits']; $visitsConverted = $metrics['nb_visits_converted']; } + if ($this->isThereSomeVisits($visits)) { $pluginsArchiver->callAggregateAllPlugins($visits, $visitsConverted); } + $idArchive = $pluginsArchiver->finalizeArchive(); return array($idArchive, $visits); @@ -136,11 +140,13 @@ class Loader { $period = $this->params->getPeriod()->getLabel(); $debugSetting = 'always_archive_data_period'; // default + if ($period == 'day') { $debugSetting = 'always_archive_data_day'; } elseif ($period == 'range') { $debugSetting = 'always_archive_data_range'; } + return (bool) Config::getInstance()->Debug[$debugSetting]; } @@ -162,9 +168,11 @@ class Loader } $idAndVisits = ArchiveSelector::getArchiveIdAndVisits($this->params, $minDatetimeArchiveProcessedUTC); + if (!$idAndVisits) { return $noArchiveFound; } + return $idAndVisits; } @@ -183,19 +191,27 @@ class Loader // Permanent archive return $endDateTimestamp; } + + $dateStart = $this->params->getDateStart(); + $period = $this->params->getPeriod(); + $segment = $this->params->getSegment(); + $site = $this->params->getSite(); + // Temporary archive - return Rules::getMinTimeProcessedForTemporaryArchive($this->params->getDateStart(), $this->params->getPeriod(), $this->params->getSegment(), $this->params->getSite()); + return Rules::getMinTimeProcessedForTemporaryArchive($dateStart, $period, $segment, $site); } protected static function determineIfArchivePermanent(Date $dateEnd) { $now = time(); $endTimestampUTC = strtotime($dateEnd->getDateEndUTC()); + if ($endTimestampUTC <= $now) { // - if the period we are looking for is finished, we look for a ts_archived that // is greater than the last day of the archive return $endTimestampUTC; } + return false; } @@ -204,6 +220,7 @@ class Loader if (is_null($this->temporaryArchive)) { throw new \Exception("getMinTimeArchiveProcessed() should be called prior to isArchiveTemporary()"); } + return $this->temporaryArchive; } diff --git a/core/ArchiveProcessor/Parameters.php b/core/ArchiveProcessor/Parameters.php index 79cb1c7196..1528d8210c 100644 --- a/core/ArchiveProcessor/Parameters.php +++ b/core/ArchiveProcessor/Parameters.php @@ -91,7 +91,7 @@ class Parameters */ public function getSubPeriods() { - if($this->getPeriod()->getLabel() == 'day') { + if ($this->getPeriod()->getLabel() == 'day') { return array( $this->getPeriod() ); } return $this->getPeriod()->getSubperiods(); diff --git a/core/ArchiveProcessor/PluginsArchiver.php b/core/ArchiveProcessor/PluginsArchiver.php index 10f61287ed..2986d05dd3 100644 --- a/core/ArchiveProcessor/PluginsArchiver.php +++ b/core/ArchiveProcessor/PluginsArchiver.php @@ -56,7 +56,7 @@ class PluginsArchiver */ public function callAggregateCoreMetrics() { - if($this->isSingleSiteDayArchive) { + if ($this->isSingleSiteDayArchive) { $metrics = $this->aggregateDayVisitsMetrics(); } else { $metrics = $this->aggregateMultipleVisitsMetrics(); @@ -92,11 +92,11 @@ class PluginsArchiver /** @var Archiver $archiver */ $archiver = new $archiverClass($this->archiveProcessor); - if(!$archiver->isEnabled()) { + if (!$archiver->isEnabled()) { continue; } - if($this->shouldProcessReportsForPlugin($pluginName)) { - if($this->isSingleSiteDayArchive) { + if ($this->shouldProcessReportsForPlugin($pluginName)) { + if ($this->isSingleSiteDayArchive) { $archiver->aggregateDayReport(); } else { $archiver->aggregateMultipleReports(); diff --git a/core/ArchiveProcessor/Rules.php b/core/ArchiveProcessor/Rules.php index a64a4f81ad..c4a672d3ac 100644 --- a/core/ArchiveProcessor/Rules.php +++ b/core/ArchiveProcessor/Rules.php @@ -222,7 +222,7 @@ class Rules { $uiSettingIsEnabled = Controller::isGeneralSettingsAdminEnabled(); - if($uiSettingIsEnabled) { + if ($uiSettingIsEnabled) { $timeToLive = Option::get(self::OPTION_TODAY_ARCHIVE_TTL); if ($timeToLive !== false) { return $timeToLive; @@ -266,7 +266,7 @@ class Rules { $uiSettingIsEnabled = Controller::isGeneralSettingsAdminEnabled(); - if($uiSettingIsEnabled) { + if ($uiSettingIsEnabled) { $browserArchivingEnabled = Option::get(self::OPTION_BROWSER_TRIGGER_ARCHIVING); if ($browserArchivingEnabled !== false) { return (bool)$browserArchivingEnabled; diff --git a/core/AssetManager.php b/core/AssetManager.php index 1badba4d9e..6759facb2b 100644 --- a/core/AssetManager.php +++ b/core/AssetManager.php @@ -37,7 +37,7 @@ use Piwik\Translate; * the global option 'disable_merged_assets'. See the documentation in the global * config for more information. * - * @method static \Piwik\AssetManager getInstance() + * @method static AssetManager getInstance() */ class AssetManager extends Singleton { @@ -72,7 +72,7 @@ class AssetManager extends Singleton $this->minimalStylesheetFetcher = new StaticUIAssetFetcher(array('plugins/Morpheus/stylesheets/base.less', 'plugins/Morpheus/stylesheets/general/_forms.less'), array(), $this->theme); $theme = Manager::getInstance()->getThemeEnabled(); - if(!empty($theme)) { + if (!empty($theme)) { $this->theme = new Theme(); } } @@ -206,7 +206,7 @@ class AssetManager extends Singleton $pluginName = $plugin->getPluginName(); $pluginIsCore = Manager::getInstance()->isPluginBundledWithCore($pluginName); - if(($pluginIsCore && $core) || (!$pluginIsCore && !$core)) + if (($pluginIsCore && $core) || (!$pluginIsCore && !$core)) $loadedPlugins[] = $pluginName; } @@ -220,12 +220,12 @@ class AssetManager extends Singleton { $assetsToRemove = array($this->getMergedStylesheetAsset()); - if($pluginName) { + if ($pluginName) { - if($this->pluginContainsJScriptAssets($pluginName)) { + if ($this->pluginContainsJScriptAssets($pluginName)) { PiwikConfig::getInstance()->init(); - if(Manager::getInstance()->isPluginBundledWithCore($pluginName)) { + if (Manager::getInstance()->isPluginBundledWithCore($pluginName)) { $assetsToRemove[] = $this->getMergedCoreJSAsset(); @@ -347,13 +347,13 @@ class AssetManager extends Singleton $plugin = Manager::getInstance()->getLoadedPlugin($pluginName); - if($plugin->isTheme()) { + if ($plugin->isTheme()) { $theme = Manager::getInstance()->getTheme($pluginName); $javaScriptFiles = $theme->getJavaScriptFiles(); - if(!empty($javaScriptFiles)) + if (!empty($javaScriptFiles)) $assets = array_merge($assets, $javaScriptFiles); } diff --git a/core/AssetManager/UIAssetCatalog.php b/core/AssetManager/UIAssetCatalog.php index d8a45f8964..826259ecb3 100644 --- a/core/AssetManager/UIAssetCatalog.php +++ b/core/AssetManager/UIAssetCatalog.php @@ -40,7 +40,7 @@ class UIAssetCatalog { $location = $uiAsset->getAbsoluteLocation(); - if(!$this->assetAlreadyInCatalog($location)) { + if (!$this->assetAlreadyInCatalog($location)) { $this->existingAssetLocations[] = $location; $this->uiAssets[] = $uiAsset; } diff --git a/core/AssetManager/UIAssetFetcher.php b/core/AssetManager/UIAssetFetcher.php index 955ced51a7..3bd34c118e 100644 --- a/core/AssetManager/UIAssetFetcher.php +++ b/core/AssetManager/UIAssetFetcher.php @@ -56,7 +56,7 @@ abstract class UIAssetFetcher */ public function getCatalog() { - if($this->catalog == null) + if ($this->catalog == null) $this->createCatalog(); return $this->catalog; diff --git a/core/AssetManager/UIAssetFetcher/JScriptUIAssetFetcher.php b/core/AssetManager/UIAssetFetcher/JScriptUIAssetFetcher.php index a5ab3d096d..5600068e44 100644 --- a/core/AssetManager/UIAssetFetcher/JScriptUIAssetFetcher.php +++ b/core/AssetManager/UIAssetFetcher/JScriptUIAssetFetcher.php @@ -18,7 +18,7 @@ class JScriptUIAssetFetcher extends UIAssetFetcher protected function retrieveFileLocations() { - if(!empty($this->plugins)) { + if (!empty($this->plugins)) { /** * Triggered when gathering the list of all JavaScript files needed by Piwik @@ -53,14 +53,14 @@ class JScriptUIAssetFetcher extends UIAssetFetcher protected function addThemeFiles() { $theme = $this->getTheme(); - if(!$theme) { + if (!$theme) { return; } - if(in_array($theme->getThemeName(), $this->plugins)) { + if (in_array($theme->getThemeName(), $this->plugins)) { $jsInThemes = $this->getTheme()->getJavaScriptFiles(); - if(!empty($jsInThemes)) { + if (!empty($jsInThemes)) { foreach($jsInThemes as $jsFile) { diff --git a/core/AssetManager/UIAssetFetcher/StylesheetUIAssetFetcher.php b/core/AssetManager/UIAssetFetcher/StylesheetUIAssetFetcher.php index 47a78a47ca..47ac94d04b 100644 --- a/core/AssetManager/UIAssetFetcher/StylesheetUIAssetFetcher.php +++ b/core/AssetManager/UIAssetFetcher/StylesheetUIAssetFetcher.php @@ -18,7 +18,6 @@ class StylesheetUIAssetFetcher extends UIAssetFetcher $theme = $this->getTheme(); $themeName = $theme->getThemeName(); - $themeName = $this->getTheme()->getThemeName(); $order = array( 'libs/', 'plugins/CoreHome/stylesheets/color_manager.css', // must be before other Piwik stylesheets @@ -72,7 +71,7 @@ class StylesheetUIAssetFetcher extends UIAssetFetcher protected function addThemeFiles() { $theme = $this->getTheme(); - if(!$theme) { + if (!$theme) { return; } $themeStylesheet = $this->getTheme()->getStylesheet(); diff --git a/core/AssetManager/UIAssetMerger.php b/core/AssetManager/UIAssetMerger.php index 8850de512b..42b5ce0cfe 100644 --- a/core/AssetManager/UIAssetMerger.php +++ b/core/AssetManager/UIAssetMerger.php @@ -48,7 +48,7 @@ abstract class UIAssetMerger public function generateFile() { - if(!$this->shouldGenerate()) + if (!$this->shouldGenerate()) return; $this->mergedContent = $this->getMergedAssets(); @@ -138,8 +138,9 @@ abstract class UIAssetMerger */ private function shouldGenerate() { - if(!$this->mergedAsset->exists()) + if (!$this->mergedAsset->exists()) { return true; + } return !$this->isFileUpToDate(); } @@ -162,19 +163,11 @@ abstract class UIAssetMerger return false; } - /** - * @return boolean - */ - private function isMergedAssetsDisabled() - { - return AssetManager::getInstance()->isMergedAssetsDisabled(); - } - private function adjustPaths() { $theme = $this->assetFetcher->getTheme(); // During installation theme is not yet ready - if($theme) { + if ($theme) { $this->mergedContent = $this->assetFetcher->getTheme()->rewriteAssetsPathToTheme($this->mergedContent); } } @@ -189,7 +182,7 @@ abstract class UIAssetMerger */ protected function getCacheBusterValue() { - if(empty($this->cacheBusterValue)) + if (empty($this->cacheBusterValue)) $this->cacheBusterValue = $this->generateCacheBuster(); return $this->cacheBusterValue; @@ -199,12 +192,4 @@ abstract class UIAssetMerger { $this->mergedContent = $this->getPreamble() . $this->mergedContent; } - - /** - * @return boolean - */ - private function shouldCompareExistingVersion() - { - return $this->isMergedAssetsDisabled(); - } } diff --git a/core/AssetManager/UIAssetMerger/JScriptUIAssetMerger.php b/core/AssetManager/UIAssetMerger/JScriptUIAssetMerger.php index bfb2442279..935018c580 100644 --- a/core/AssetManager/UIAssetMerger/JScriptUIAssetMerger.php +++ b/core/AssetManager/UIAssetMerger/JScriptUIAssetMerger.php @@ -57,7 +57,7 @@ class JScriptUIAssetMerger extends UIAssetMerger { $plugins = $this->getPlugins(); - if(!empty($plugins)) { + if (!empty($plugins)) { /** * Triggered after all the JavaScript files Piwik uses are minified and merged into a diff --git a/core/AssetManager/UIAssetMinifier.php b/core/AssetManager/UIAssetMinifier.php index 5f738092cc..07dd3c769d 100644 --- a/core/AssetManager/UIAssetMinifier.php +++ b/core/AssetManager/UIAssetMinifier.php @@ -36,6 +36,7 @@ class UIAssetMinifier extends Singleton public function isMinifiedJs($content) { $lineCount = substr_count($content, "\n"); + if ($lineCount == 0) { return true; } diff --git a/core/BaseFactory.php b/core/BaseFactory.php index 6f09f952ef..0bc8716eb2 100644 --- a/core/BaseFactory.php +++ b/core/BaseFactory.php @@ -9,7 +9,6 @@ namespace Piwik; use Exception; -use Piwik\Common; /** * Base class for all factory types. diff --git a/core/CacheFile.php b/core/CacheFile.php index 9eb0587595..48a23004bf 100644 --- a/core/CacheFile.php +++ b/core/CacheFile.php @@ -25,11 +25,7 @@ class CacheFile /** * @var string */ - protected $cachePath; - /** - * @var - */ - protected $cachePrefix; + private $cachePath; /** * Minimum enforced TTL in seconds @@ -67,11 +63,12 @@ class CacheFile if (empty($id)) { return false; } + $id = $this->cleanupId($id); $cache_complete = false; - $content = ''; - $expires_on = false; + $content = ''; + $expires_on = false; // We are assuming that most of the time cache will exists $cacheFilePath = $this->cachePath . $id . '.php'; @@ -88,6 +85,7 @@ class CacheFile ) { return false; } + return $content; } @@ -104,6 +102,7 @@ class CacheFile if (!Filesystem::isValidFilename($id)) { throw new Exception("Invalid cache ID request $id"); } + return $id; } @@ -120,25 +119,23 @@ class CacheFile if (empty($id)) { return false; } + if (!is_dir($this->cachePath)) { Filesystem::mkdir($this->cachePath); } + if (!is_writable($this->cachePath)) { return false; } - $id = $this->cleanupId($id); + $id = $this->cleanupId($id); $id = $this->cachePath . $id . '.php'; if (is_object($content)) { throw new \Exception('You cannot use the CacheFile to cache an object, only arrays, strings and numbers.'); } - $cache_literal = "<" . "?php\n"; - $cache_literal .= "$" . "content = " . var_export($content, true) . ";\n"; - $cache_literal .= "$" . "expires_on = " . $this->getExpiresTime() . ";\n"; - $cache_literal .= "$" . "cache_complete = true;\n"; - $cache_literal .= "?" . ">"; + $cache_literal = $this->buildCacheLiteral($content); // Write cache to a temp file, then rename it, overwriting the old cache // On *nix systems this should guarantee atomicity @@ -162,6 +159,7 @@ class CacheFile return true; } + return false; } @@ -176,14 +174,17 @@ class CacheFile if (empty($id)) { return false; } + $id = $this->cleanupId($id); $filename = $this->cachePath . $id . '.php'; + if (file_exists($filename)) { $this->opCacheInvalidate($filename); @unlink($filename); return true; } + return false; } @@ -218,8 +219,19 @@ class CacheFile @opcache_invalidate($filepath, $force = true); } if (function_exists('apc_delete_file')) { - apc_delete_file($filepath); + @apc_delete_file($filepath); } } } + + private function buildCacheLiteral($content) + { + $cache_literal = "<" . "?php\n"; + $cache_literal .= "$" . "content = " . var_export($content, true) . ";\n"; + $cache_literal .= "$" . "expires_on = " . $this->getExpiresTime() . ";\n"; + $cache_literal .= "$" . "cache_complete = true;\n"; + $cache_literal .= "?" . ">"; + + return $cache_literal; + } } diff --git a/core/CliMulti.php b/core/CliMulti.php index 21e0ee0b0d..6de96af5b0 100644 --- a/core/CliMulti.php +++ b/core/CliMulti.php @@ -58,13 +58,15 @@ class CliMulti { public function request(array $piwikUrls) { $chunks = array($piwikUrls); - if($this->concurrentProcessesLimit) { + if ($this->concurrentProcessesLimit) { $chunks = array_chunk( $piwikUrls, $this->concurrentProcessesLimit); } + $results = array(); foreach($chunks as $urlsChunk) { $results = array_merge($results, $this->requestUrls($urlsChunk)); } + return $results; } @@ -89,17 +91,22 @@ class CliMulti { private function start($piwikUrls) { foreach ($piwikUrls as $index => $url) { - $cmdId = $this->generateCommandId($url) . $index; - $output = new Output($cmdId); + $cmdId = $this->generateCommandId($url) . $index; + $this->executeUrlCommand($cmdId, $url); + } + } - if ($this->supportsAsync) { - $this->executeAsyncCli($url, $output, $cmdId); - } else { - $this->executeNotAsyncHttp($url, $output); - } + private function executeUrlCommand($cmdId, $url) + { + $output = new Output($cmdId); - $this->outputs[] = $output; + if ($this->supportsAsync) { + $this->executeAsyncCli($url, $output, $cmdId); + } else { + $this->executeNotAsyncHttp($url, $output); } + + $this->outputs[] = $output; } private function buildCommand($hostname, $query, $outputFile) @@ -192,7 +199,7 @@ class CliMulti { $timeOneWeekAgo = strtotime('-1 week'); $files = _glob(self::getTmpPath() . '/*'); - if(empty($files)) { + if (empty($files)) { return; } diff --git a/core/CliMulti/CliPhp.php b/core/CliMulti/CliPhp.php index df82e05376..1b164835d4 100644 --- a/core/CliMulti/CliPhp.php +++ b/core/CliMulti/CliPhp.php @@ -18,11 +18,11 @@ class CliPhp { if (defined('PHP_BINARY')) { - if($this->isValidPhpType(PHP_BINARY)) { + if ($this->isValidPhpType(PHP_BINARY)) { return PHP_BINARY . ' -q'; } - if($this->isHhvmBinary(PHP_BINARY)) { + if ($this->isHhvmBinary(PHP_BINARY)) { return PHP_BINARY . ' --php'; } } diff --git a/core/CliMulti/Process.php b/core/CliMulti/Process.php index e8dfb662a4..6c5ac165ca 100644 --- a/core/CliMulti/Process.php +++ b/core/CliMulti/Process.php @@ -154,7 +154,7 @@ class Process return false; } - if(!self::isProcFSMounted()) { + if (!self::isProcFSMounted()) { return false; } @@ -169,11 +169,11 @@ class Process { $uname = @shell_exec('uname -a'); - if(empty($uname)) { + if (empty($uname)) { $uname = php_uname(); } - if(strpos($uname, 'synology') !== false) { + if (strpos($uname, 'synology') !== false) { return true; } return false; @@ -208,7 +208,7 @@ class Process */ private static function isProcFSMounted() { - if(is_resource(@fopen('/proc', 'r'))) { + if (is_resource(@fopen('/proc', 'r'))) { return true; } // Testing if /proc is a resource with @fopen fails on systems with open_basedir set. diff --git a/core/Columns/Updater.php b/core/Columns/Updater.php index 2dd6e4040e..1bc53607ca 100644 --- a/core/Columns/Updater.php +++ b/core/Columns/Updater.php @@ -87,17 +87,17 @@ class Updater extends \Piwik\Updates $changingColumns = array(); - foreach (VisitDimension::getAllDimensions() as $dimension) { + foreach (self::getVisitDimensions() as $dimension) { $updates = self::getUpdatesForDimension($dimension, 'log_visit.', $visitColumns, $conversionColumns); $changingColumns = self::mixinUpdates($changingColumns, $updates); } - foreach (ActionDimension::getAllDimensions() as $dimension) { + foreach (self::getActionDimensions() as $dimension) { $updates = self::getUpdatesForDimension($dimension, 'log_link_visit_action.', $actionColumns); $changingColumns = self::mixinUpdates($changingColumns, $updates); } - foreach (ConversionDimension::getAllDimensions() as $dimension) { + foreach (self::getConversionDimensions() as $dimension) { $updates = self::getUpdatesForDimension($dimension, 'log_conversion.', $conversionColumns); $changingColumns = self::mixinUpdates($changingColumns, $updates); } @@ -167,15 +167,15 @@ class Updater extends \Piwik\Updates $actionColumns = DbHelper::getTableColumns(Common::prefixTable('log_link_visit_action')); $conversionColumns = DbHelper::getTableColumns(Common::prefixTable('log_conversion')); - foreach (VisitDimension::getAllDimensions() as $dimension) { + foreach (self::getVisitDimensions() as $dimension) { $versions = self::mixinVersions($dimension, 'log_visit.', $visitColumns, $versions); } - foreach (ActionDimension::getAllDimensions() as $dimension) { + foreach (self::getActionDimensions() as $dimension) { $versions = self::mixinVersions($dimension, 'log_link_visit_action.', $actionColumns, $versions); } - foreach (ConversionDimension::getAllDimensions() as $dimension) { + foreach (self::getConversionDimensions() as $dimension) { $versions = self::mixinVersions($dimension, 'log_conversion.', $conversionColumns, $versions); } @@ -327,4 +327,25 @@ class Updater extends \Piwik\Updates return array(); } + + private static function getVisitDimensions() + { + return VisitDimension::getAllDimensions(); + } + + /** + * @return mixed|Dimension[] + */ + private static function getActionDimensions() + { + return ActionDimension::getAllDimensions(); + } + + /** + * @return mixed|Dimension[] + */ + private static function getConversionDimensions() + { + return ConversionDimension::getAllDimensions(); + } } diff --git a/core/Common.php b/core/Common.php index d9ddf0be25..bf18343bd3 100644 --- a/core/Common.php +++ b/core/Common.php @@ -362,10 +362,13 @@ class Common */ private static function undoMagicQuotes($value) { - return version_compare(PHP_VERSION, '5.4', '<') - && get_magic_quotes_gpc() - ? stripslashes($value) - : $value; + if (version_compare(PHP_VERSION, '5.4', '<') && + get_magic_quotes_gpc()) { + + return stripslashes($value); + } + + return $value; } /** @@ -375,8 +378,7 @@ class Common */ public static function sanitizeLineBreaks($value) { - $value = str_replace(array("\n", "\r", "\0"), '', $value); - return $value; + return str_replace(array("\n", "\r", "\0"), '', $value); } /** @@ -406,6 +408,7 @@ class Common if (is_null($requestArrayToUse)) { $requestArrayToUse = $_GET + $_POST; } + $varDefault = self::sanitizeInputValues($varDefault); if ($varType === 'int') { // settype accepts only integer @@ -469,6 +472,7 @@ class Common } settype($value, $varType); } + return $value; } @@ -496,14 +500,17 @@ class Common public static function hash($str, $raw_output = false) { static $hashAlgorithm = null; + if (is_null($hashAlgorithm)) { $hashAlgorithm = @Config::getInstance()->General['hash_algorithm']; } if ($hashAlgorithm) { $hash = @hash($hashAlgorithm, $str, $raw_output); - if ($hash !== false) + if ($hash !== false) { + return $hash; + } } return md5($str, $raw_output); @@ -520,7 +527,7 @@ class Common public static function getRandomString($length = 16, $alphabet = "abcdefghijklmnoprstuvwxyz0123456789") { $chars = $alphabet; - $str = ''; + $str = ''; list($usec, $sec) = explode(" ", microtime()); $seed = ((float)$sec + (float)$usec) * 100000; @@ -530,6 +537,7 @@ class Common $rand_key = mt_rand(0, strlen($chars) - 1); $str .= substr($chars, $rand_key, 1); } + return str_shuffle($str); } @@ -571,6 +579,7 @@ class Common ) { throw new Exception("visitorId is expected to be a " . Tracker::LENGTH_HEX_ID_STRING . " hex char string"); } + return self::hex2bin($id); } @@ -584,6 +593,7 @@ class Common { require_once PIWIK_INCLUDE_PATH . '/libs/PiwikTracker/PiwikTracker.php'; $userIdHashed = \PiwikTracker::getUserIdHashed($userId); + return self::convertVisitorIdToBin($userIdHashed); } @@ -730,6 +740,7 @@ class Common if ($includeInternalCodes) { return array_merge($countriesList, $extras); } + return $countriesList; } @@ -1054,7 +1065,7 @@ class Common public static function sendHeader($header, $replace = true) { // don't send header in CLI mode - if(!Common::isPhpCliMode() and !headers_sent()) { + if (!Common::isPhpCliMode() and !headers_sent()) { header($header, $replace); } } diff --git a/core/Config.php b/core/Config.php index 9d6326bb2e..572291b259 100644 --- a/core/Config.php +++ b/core/Config.php @@ -36,7 +36,7 @@ use Exception; * Config::getInstance()->MySection = array('myoption' => 1); * Config::getInstance()->forceSave(); * - * @method static \Piwik\Config getInstance() + * @method static Config getInstance() */ class Config extends Singleton { @@ -416,9 +416,9 @@ class Config extends Singleton $section = $this->getFromGlobalConfig($name); $sectionCommon = $this->getFromCommonConfig($name); - if(empty($section) && !empty($sectionCommon)) { + if (empty($section) && !empty($sectionCommon)) { $section = $sectionCommon; - } elseif(!empty($section) && !empty($sectionCommon)) { + } elseif (!empty($section) && !empty($sectionCommon)) { $section = $this->array_merge_recursive_distinct($section, $sectionCommon); } @@ -559,7 +559,7 @@ class Config extends Singleton } // If there is a common.config.ini.php, this will ensure config.ini.php does not duplicate its values - if(!empty($configCommon)) { + if (!empty($configCommon)) { $configGlobal = $this->array_merge_recursive_distinct($configGlobal, $configCommon); } diff --git a/core/Console.php b/core/Console.php index 03f9df438d..1f418fc79a 100644 --- a/core/Console.php +++ b/core/Console.php @@ -40,6 +40,7 @@ class Console extends Application { $this->initPiwikHost($input); $this->initConfig($output); + try { self::initPlugins(); } catch(\Exception $e) { @@ -51,18 +52,23 @@ class Console extends Application $commands = $this->getAvailableCommands(); foreach ($commands as $command) { - if (!class_exists($command)) { - Log::warning(sprintf('Cannot add command %s, class does not exist', $command)); - } elseif (!is_subclass_of($command, 'Piwik\Plugin\ConsoleCommand')) { - Log::warning(sprintf('Cannot add command %s, class does not extend Piwik\Plugin\ConsoleCommand', $command)); - } else { - $this->add(new $command); - } + $this->addCommandIfExists($command); } return parent::doRun($input, $output); } + private function addCommandIfExists($command) + { + if (!class_exists($command)) { + Log::warning(sprintf('Cannot add command %s, class does not exist', $command)); + } elseif (!is_subclass_of($command, 'Piwik\Plugin\ConsoleCommand')) { + Log::warning(sprintf('Cannot add command %s, class does not extend Piwik\Plugin\ConsoleCommand', $command)); + } else { + $this->add(new $command); + } + } + /** * Returns a list of available command classnames. * @@ -128,9 +134,11 @@ class Console extends Application protected function initConfig(OutputInterface $output) { $config = Config::getInstance(); + try { $config->checkLocalConfigFound(); return $config; + } catch (\Exception $e) { $output->writeln($e->getMessage() . "\n"); } @@ -151,6 +159,8 @@ class Console extends Application $extra = new \Piwik\Plugins\EnterpriseAdmin\EnterpriseAdmin(); $extra->addConsoleCommands($commands); } + return $commands; } + } diff --git a/core/Cookie.php b/core/Cookie.php index d081ec944e..7440c5795c 100644 --- a/core/Cookie.php +++ b/core/Cookie.php @@ -200,12 +200,14 @@ class Cookie private function extractSignedContent($content) { $signature = substr($content, -40); + if (substr($content, -43, 3) == self::VALUE_SEPARATOR . '_=' && $signature == sha1(substr($content, 0, -40) . SettingsPiwik::getSalt()) ) { // strip trailing: VALUE_SEPARATOR '_=' signature" return substr($content, 0, -43); } + return false; } @@ -218,6 +220,7 @@ class Cookie protected function loadContentFromCookie() { $cookieStr = $this->extractSignedContent($_COOKIE[$this->name]); + if ($cookieStr === false) { return; } @@ -255,6 +258,7 @@ class Cookie protected function generateContentString() { $cookieStr = ''; + foreach ($this->value as $name => $value) { if (!is_numeric($value)) { $value = base64_encode(safe_serialize($value)); @@ -335,6 +339,7 @@ class Cookie $this->value[$name] = $value; return; } + $this->value[$this->keyStore][$name] = $value; } @@ -347,14 +352,19 @@ class Cookie public function get($name) { $name = self::escapeValue($name); - if ($this->keyStore === false) { - return isset($this->value[$name]) - ? self::escapeValue($this->value[$name]) - : false; + if (false === $this->keyStore) { + if (isset($this->value[$name])) { + self::escapeValue($this->value[$name]); + } + + return false; + } + + if (isset($this->value[$this->keyStore][$name])) { + return self::escapeValue($this->value[$this->keyStore][$name]); } - return isset($this->value[$this->keyStore][$name]) - ? self::escapeValue($this->value[$this->keyStore][$name]) - : false; + + return false; } /** @@ -364,8 +374,9 @@ class Cookie */ public function __toString() { - $str = 'COOKIE ' . $this->name . ', rows count: ' . count($this->value) . ', cookie size = ' . strlen($this->generateContentString()) . " bytes\n"; + $str = 'COOKIE ' . $this->name . ', rows count: ' . count($this->value) . ', cookie size = ' . strlen($this->generateContentString()) . " bytes\n"; $str .= var_export($this->value, $return = true); + return $str; } diff --git a/core/CronArchive.php b/core/CronArchive.php index 442480051b..045e1f7c62 100644 --- a/core/CronArchive.php +++ b/core/CronArchive.php @@ -181,6 +181,13 @@ class CronArchive */ public $concurrentRequestsPerWebsite = false; + private $websitesWithVisitsSinceLastRun = 0; + private $skippedPeriodsArchivesWebsite = 0; + private $skippedDayArchivesWebsites = 0; + private $skipped = 0; + private $processed = 0; + private $archivedPeriodsArchivesWebsite = 0; + /** * Returns the option name of the option that stores the time core:archive was last executed. * @@ -234,10 +241,10 @@ class CronArchive // record archiving start time Option::set(self::OPTION_ARCHIVING_STARTED_TS, time()); - $this->segments = $this->initSegmentsToArchive(); + $this->segments = $this->initSegmentsToArchive(); $this->allWebsites = APISitesManager::getInstance()->getAllSitesId(); - if(!empty($this->shouldArchiveOnlySpecificPeriods)) { + if (!empty($this->shouldArchiveOnlySpecificPeriods)) { $this->log("- Will process the following periods: " . implode(", ", $this->shouldArchiveOnlySpecificPeriods) . " (--force-periods)"); } @@ -279,13 +286,6 @@ class CronArchive $this->runScheduledTasks(); } - private $websitesWithVisitsSinceLastRun = 0; - private $skippedPeriodsArchivesWebsite = 0; - private $skippedDayArchivesWebsites = 0; - private $skipped = 0; - private $processed = 0; - private $archivedPeriodsArchivesWebsite = 0; - /** * Main function, runs archiving on all websites with new activity */ @@ -310,7 +310,7 @@ class CronArchive } $skipWebsiteForced = in_array($idSite, $this->shouldSkipSpecifiedSites); - if($skipWebsiteForced) { + if ($skipWebsiteForced) { $this->log("Skipped website id $idSite, found in --skip-idsites "); $this->skipped++; continue; @@ -380,6 +380,7 @@ class CronArchive // do not logError since errors are already in stderr $this->log("Error: " . $error); } + $summary = count($this->errors) . " total errors during this script execution, please investigate and try and fix these errors."; $this->logFatalError($summary); } @@ -402,9 +403,11 @@ class CronArchive $this->log("Starting Scheduled tasks... "); $tasksOutput = $this->request("?module=API&method=CoreAdminHome.runScheduledTasks&format=csv&convertToUnicode=0&token_auth=" . $this->token_auth); + if ($tasksOutput == \Piwik\DataTable\Renderer\Csv::NO_DATA_AVAILABLE) { $tasksOutput = " No task to run"; } + $this->log($tasksOutput); $this->log("done"); $this->logSection(""); @@ -415,6 +418,7 @@ class CronArchive $timerWebsite = new Timer; $lastTimestampWebsiteProcessedPeriods = $lastTimestampWebsiteProcessedDay = false; + if ($this->archiveAndRespectTTL) { Option::clearCachedOption($this->lastRunKey($idSite, "periods")); $lastTimestampWebsiteProcessedPeriods = Option::get($this->lastRunKey($idSite, "periods")); @@ -433,6 +437,7 @@ class CronArchive if ($this->processPeriodsMaximumEverySeconds > 10 * 60) { $secondsSinceLastExecution += 5 * 60; } + $shouldArchivePeriods = $secondsSinceLastExecution > $this->processPeriodsMaximumEverySeconds; if (empty($lastTimestampWebsiteProcessedPeriods)) { // 2) OR always if script never executed for this website before @@ -455,7 +460,7 @@ class CronArchive } $websiteIdIsForced = in_array($idSite, $this->shouldArchiveSpecifiedSites); - if($websiteIdIsForced) { + if ($websiteIdIsForced) { $shouldArchivePeriods = true; } @@ -492,7 +497,7 @@ class CronArchive } $shouldProceed = $this->processArchiveDays($idSite, $lastTimestampWebsiteProcessedDay, $shouldArchivePeriods, $timerWebsite); - if(!$shouldProceed) { + if (!$shouldProceed) { return false; } @@ -508,7 +513,7 @@ class CronArchive $success = true; foreach (array('week', 'month', 'year') as $period) { - if(!$this->shouldProcessPeriod($period)) { + if (!$this->shouldProcessPeriod($period)) { // if any period was skipped, we do not mark the Periods archiving as successful $success = false; continue; @@ -521,6 +526,7 @@ class CronArchive if ($success) { Option::set($this->lastRunKey($idSite, "periods"), time()); } + $this->archivedPeriodsArchivesWebsite++; $requestsWebsite = $this->requests - $requestsBefore; @@ -568,9 +574,11 @@ class CronArchive private function initSegmentsToArchive() { $segments = \Piwik\SettingsPiwik::getKnownSegmentsToArchive(); + if (empty($segments)) { return array(); } + $this->log("- Will pre-process " . count($segments) . " Segments for each website and each period: " . implode(", ", $segments)); return $segments; } @@ -603,7 +611,7 @@ class CronArchive // when some data was purged from this website // we make sure we query all previous days/weeks/months $processDaysSince = $lastTimestampWebsiteProcessedDay; - if($this->isOldReportInvalidatedForWebsite($idSite) + if ($this->isOldReportInvalidatedForWebsite($idSite) // when --force-all-websites option, // also forces to archive last52 days to be safe || $this->shouldArchiveAllSites) { @@ -634,7 +642,7 @@ class CronArchive $this->processed++; // If there is no visit today and we don't need to process this website, we can skip remaining archives - if ($visitsToday == 0 + if (0 == $visitsToday && !$shouldArchivePeriods ) { $this->log("Skipped website id $idSite, no visit today, " . $timerWebsite->__toString()); @@ -642,7 +650,7 @@ class CronArchive return false; } - if ($visitsLastDays == 0 + if (0 == $visitsLastDays && !$shouldArchivePeriods && $this->shouldArchiveAllSites ) { @@ -662,7 +670,7 @@ class CronArchive private function getSegmentsForSite($idSite) { $segmentsAllSites = $this->segments; - $segmentsThisSite = \Piwik\SettingsPiwik::getKnownSegmentsToArchiveForSite($idSite); + $segmentsThisSite = SettingsPiwik::getKnownSegmentsToArchiveForSite($idSite); if (!empty($segmentsThisSite)) { $this->log("Will pre-process the following " . count($segmentsThisSite) . " Segments for this website (id = $idSite): " . implode(", ", $segmentsThisSite)); } @@ -731,7 +739,7 @@ class CronArchive } // we have already logged the daily archive above - if($period != "day") { + if ($period != "day") { $this->logArchivedWebsite($idSite, $period, $date, $visitsInLastPeriods, $visitsLastPeriod, $timer); } @@ -744,7 +752,7 @@ class CronArchive private function logSection($title = "") { $this->log("---------------------------"); - if(!empty($title)) { + if (!empty($title)) { $this->log($title); } } @@ -788,7 +796,7 @@ class CronArchive { $url = $this->piwikUrl . $url . self::APPEND_TO_API_REQUEST; - if($this->shouldStartProfiler) { + if ($this->shouldStartProfiler) { $url .= "&xhprof=2"; } @@ -851,6 +859,7 @@ class CronArchive if (Common::isPhpCliMode()) { return; } + $token_auth = Common::getRequestVar('token_auth', '', 'string'); if ($token_auth !== $this->token_auth || strlen($token_auth) != 32 @@ -892,7 +901,7 @@ class CronArchive $this->shouldArchiveOnlySitesWithTrafficSince = $this->isShouldArchiveAllSitesWithTrafficSince(); $this->shouldArchiveOnlySpecificPeriods = $this->getPeriodsToProcess(); - if($this->shouldArchiveOnlySitesWithTrafficSince === false) { + if ($this->shouldArchiveOnlySitesWithTrafficSince === false) { // force-all-periods is not set here if (empty($this->lastSuccessRunTimestamp)) { // First time we run the script @@ -905,7 +914,7 @@ class CronArchive // force-all-periods is set here $this->archiveAndRespectTTL = false; - if($this->shouldArchiveOnlySitesWithTrafficSince === true) { + if ($this->shouldArchiveOnlySitesWithTrafficSince === true) { // force-all-periods without value $this->shouldArchiveOnlySitesWithTrafficSince = self::ARCHIVE_SITES_WITH_TRAFFIC_SINCE; } @@ -935,7 +944,7 @@ class CronArchive */ public function initWebsiteIds() { - if(count($this->shouldArchiveSpecifiedSites) > 0) { + if (count($this->shouldArchiveSpecifiedSites) > 0) { $this->log("- Will process " . count($this->shouldArchiveSpecifiedSites) . " websites (--force-idsites)"); return $this->shouldArchiveSpecifiedSites; @@ -978,12 +987,12 @@ class CronArchive $this->logFatalErrorUrlExpected(); } - if(!\Piwik\UrlHelper::isLookLikeUrl($piwikUrl)) { + if (!\Piwik\UrlHelper::isLookLikeUrl($piwikUrl)) { // try adding http:// in case it's missing $piwikUrl = "http://" . $piwikUrl; } - if(!\Piwik\UrlHelper::isLookLikeUrl($piwikUrl)) { + if (!\Piwik\UrlHelper::isLookLikeUrl($piwikUrl)) { $this->logFatalErrorUrlExpected(); } @@ -1099,12 +1108,14 @@ class CronArchive $websiteDayHasFinishedSinceLastRun = APISitesManager::getInstance()->getSitesIdFromTimezones($timezones); $websiteDayHasFinishedSinceLastRun = array_diff($websiteDayHasFinishedSinceLastRun, $websiteIds); $this->websiteDayHasFinishedSinceLastRun = $websiteDayHasFinishedSinceLastRun; + if (count($websiteDayHasFinishedSinceLastRun) > 0) { $ids = !empty($websiteDayHasFinishedSinceLastRun) ? ", IDs: " . implode(", ", $websiteDayHasFinishedSinceLastRun) : ""; $this->log("- Will process " . count($websiteDayHasFinishedSinceLastRun) . " other websites because the last time they were archived was on a different day (in the website's timezone) " . $ids); } + return $websiteDayHasFinishedSinceLastRun; } @@ -1170,6 +1181,7 @@ class CronArchive $this->log("WARNING: Automatically increasing --force-timeout-for-periods from {$this->forceTimeoutPeriod} to " . $this->todayArchiveTimeToLive . " to match the cache timeout for Today's report specified in Piwik UI > Settings > General Settings"); + return $this->todayArchiveTimeToLive; } @@ -1178,11 +1190,13 @@ class CronArchive if (empty($this->shouldArchiveAllPeriodsSince)) { return false; } + if (is_numeric($this->shouldArchiveAllPeriodsSince) && $this->shouldArchiveAllPeriodsSince > 1 ) { return (int)$this->shouldArchiveAllPeriodsSince; } + return true; } @@ -1192,6 +1206,7 @@ class CronArchive protected function removeWebsiteFromInvalidatedWebsites($idSite) { $websiteIdsInvalidated = APICoreAdminHome::getWebsiteIdsToInvalidate(); + if (count($websiteIdsInvalidated)) { $found = array_search($idSite, $websiteIdsInvalidated); if ($found !== false) { @@ -1209,25 +1224,29 @@ class CronArchive private function getVisitsLastPeriodFromApiResponse($stats) { - if(empty($stats)) { + if (empty($stats)) { return 0; } + $today = end($stats); + return $today['nb_visits']; } private function getVisitsFromApiResponse($stats) { - if(empty($stats)) { + if (empty($stats)) { return 0; } + $visits = 0; foreach($stats as $metrics) { - if(empty($metrics['nb_visits'])) { + if (empty($metrics['nb_visits'])) { continue; } $visits += $metrics['nb_visits']; } + return $visits; } @@ -1240,9 +1259,11 @@ class CronArchive private function getApiDateParameter($idSite, $period, $lastTimestampWebsiteProcessed = false) { $dateRangeForced = $this->getDateRangeToProcess(); - if(!empty($dateRangeForced)) { + + if (!empty($dateRangeForced)) { return $dateRangeForced; } + return $this->getDateLastN($idSite, $period, $lastTimestampWebsiteProcessed); } @@ -1256,7 +1277,7 @@ class CronArchive */ private function logArchivedWebsite($idSite, $period, $date, $visitsInLastPeriods, $visitsToday, Timer $timer) { - if(substr($date, 0, 4) === 'last') { + if (substr($date, 0, 4) === 'last') { $visitsInLastPeriods = (int)$visitsInLastPeriods . " visits in last " . $date . " " . $period . "s, "; $thisPeriod = $period == "day" ? "today" : "this " . $period; $visitsInLastPeriod = (int)$visitsToday . " visits " . $thisPeriod . ", "; @@ -1276,9 +1297,11 @@ class CronArchive if (empty($this->restrictToDateRange)) { return false; } + if (strpos($this->restrictToDateRange, ',') === false) { throw new Exception("--force-date-range expects a date range ie. YYYY-MM-DD,YYYY-MM-DD"); } + return $this->restrictToDateRange; } @@ -1289,6 +1312,7 @@ class CronArchive { $this->restrictToPeriods = array_intersect($this->restrictToPeriods, $this->getDefaultPeriodsToProcess()); $this->restrictToPeriods = array_intersect($this->restrictToPeriods, PeriodFactory::getPeriodsEnabledForAPI()); + return $this->restrictToPeriods; } @@ -1311,9 +1335,10 @@ class CronArchive private function shouldProcessPeriod($period) { - if(empty($this->shouldArchiveOnlySpecificPeriods)) { + if (empty($this->shouldArchiveOnlySpecificPeriods)) { return true; } + return in_array($period, $this->shouldArchiveOnlySpecificPeriods); } @@ -1344,6 +1369,7 @@ class CronArchive if (!empty($this->dateLastForced)) { $dateLast = $this->dateLastForced; } + return "last" . $dateLast; } @@ -1352,9 +1378,10 @@ class CronArchive */ private function getConcurrentRequestsPerWebsite() { - if ($this->concurrentRequestsPerWebsite !== false) { + if (false !== $this->concurrentRequestsPerWebsite) { return $this->concurrentRequestsPerWebsite; } + return self::MAX_CONCURRENT_API_REQUESTS; } } diff --git a/core/DataAccess/ArchivePurger.php b/core/DataAccess/ArchivePurger.php index 94e1622376..2c1379115d 100644 --- a/core/DataAccess/ArchivePurger.php +++ b/core/DataAccess/ArchivePurger.php @@ -81,8 +81,7 @@ class ArchivePurger protected static function getTemporaryArchiveIdsOlderThan(Date $date, $purgeArchivesOlderThan) { - $query = "SELECT idarchive - FROM " . ArchiveTableCreator::getNumericTable($date) . " + $query = "SELECT idarchive FROM " . ArchiveTableCreator::getNumericTable($date) . " WHERE name LIKE 'done%' AND (( value = " . ArchiveWriter::DONE_OK_TEMPORARY . " AND ts_archived < ?) diff --git a/core/DataAccess/ArchiveSelector.php b/core/DataAccess/ArchiveSelector.php index 5a715e6939..594889d6dd 100644 --- a/core/DataAccess/ArchiveSelector.php +++ b/core/DataAccess/ArchiveSelector.php @@ -14,10 +14,8 @@ use Piwik\ArchiveProcessor; use Piwik\Common; use Piwik\Date; use Piwik\Db; -use Piwik\Log; use Piwik\Period; use Piwik\Period\Range; -use Piwik\Piwik; use Piwik\Segment; /** @@ -150,7 +148,7 @@ class ArchiveSelector */ public static function getArchiveIds($siteIds, $periods, $segment, $plugins, $isSkipAggregationOfSubTables = false) { - if(empty($siteIds)) { + if (empty($siteIds)) { throw new \Exception("Website IDs could not be read from the request, ie. idSite="); } diff --git a/core/DataAccess/LogAggregator.php b/core/DataAccess/LogAggregator.php index 95a7603176..79db3148b7 100644 --- a/core/DataAccess/LogAggregator.php +++ b/core/DataAccess/LogAggregator.php @@ -494,7 +494,7 @@ class LogAggregator * * @param string $dimension One or more **log\_conversion\_item** columns to group aggregated data by. * Eg, `'idaction_sku'` or `'idaction_sku, idaction_category'`. - * @return Zend_Db_Statement A statement object that can be used to iterate through the query's + * @return \Zend_Db_Statement A statement object that can be used to iterate through the query's * result set. See [above](#queryEcommerceItems-result-set) to learn more * about what this query selects. * @api @@ -641,7 +641,7 @@ class LogAggregator if (strpos($joinColumn, ' ') === false) { $joinOn = $tableAlias . '.idaction = ' . $tableName . '.' . $joinColumn; } else { - // more complex join column like IF(...) + // more complex join column like if (...) $joinOn = $tableAlias . '.idaction = ' . $joinColumn; } $from[] = array( @@ -733,7 +733,7 @@ class LogAggregator * @param bool|string $where An optional SQL expression used in the SQL's **WHERE** clause. * @param array $additionalSelects Additional SELECT fields that are not included in the group by * clause. These can be aggregate expressions, eg, `SUM(somecol)`. - * @return Zend_Db_Statement + * @return \Zend_Db_Statement */ public function queryConversionsByDimension($dimensions = array(), $where = false, $additionalSelects = array()) { @@ -743,11 +743,11 @@ class LogAggregator $select = $this->getSelectStatement($dimensions, $tableName, $additionalSelects, $availableMetrics); - $from = array($tableName); - $where = $this->getWhereStatement($tableName, self::CONVERSION_DATETIME_FIELD, $where); + $from = array($tableName); + $where = $this->getWhereStatement($tableName, self::CONVERSION_DATETIME_FIELD, $where); $groupBy = $this->getGroupByStatement($dimensions, $tableName); $orderBy = false; - $query = $this->generateQuery($select, $from, $where, $groupBy, $orderBy); + $query = $this->generateQuery($select, $from, $where, $groupBy, $orderBy); return $this->getDb()->query($query['sql'], $query['bind']); } diff --git a/core/DataArray.php b/core/DataArray.php index 042d5ae961..04c9897125 100644 --- a/core/DataArray.php +++ b/core/DataArray.php @@ -108,7 +108,7 @@ class DataArray // In case the existing Row had no action metrics (eg. Custom Variable XYZ with "visit" scope) // but the new Row has action metrics (eg. same Custom Variable XYZ this time with a "page" scope) - if(!isset($oldRowToUpdate[Metrics::INDEX_MAX_ACTIONS])) { + if (!isset($oldRowToUpdate[Metrics::INDEX_MAX_ACTIONS])) { $toZero = array(Metrics::INDEX_MAX_ACTIONS, Metrics::INDEX_SUM_VISIT_LENGTH, Metrics::INDEX_BOUNCE_COUNT, @@ -247,8 +247,8 @@ class DataArray $oldRowToUpdate[Metrics::INDEX_EVENT_MAX_EVENT_VALUE] = round(max($newRowToAdd[Metrics::INDEX_EVENT_MAX_EVENT_VALUE], $oldRowToUpdate[Metrics::INDEX_EVENT_MAX_EVENT_VALUE]), self::EVENT_VALUE_PRECISION); // Update minimum only if it is set - if($newRowToAdd[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] !== false) { - if($oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] === false) { + if ($newRowToAdd[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] !== false) { + if ($oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] === false) { $oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] = round($newRowToAdd[Metrics::INDEX_EVENT_MIN_EVENT_VALUE], self::EVENT_VALUE_PRECISION); } else { $oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE] = round(min($newRowToAdd[Metrics::INDEX_EVENT_MIN_EVENT_VALUE], $oldRowToUpdate[Metrics::INDEX_EVENT_MIN_EVENT_VALUE]), self::EVENT_VALUE_PRECISION); @@ -360,7 +360,7 @@ class DataArray // if there are no "visit" column, we force one to prevent future complications // eg. This helps the setDefaultColumnsToDisplay() call - if(!isset($values[Metrics::INDEX_NB_VISITS])) { + if (!isset($values[Metrics::INDEX_NB_VISITS])) { $values[Metrics::INDEX_NB_VISITS] = 0; } } diff --git a/core/DataTable.php b/core/DataTable.php index bc5a57cff6..4d308f7d21 100644 --- a/core/DataTable.php +++ b/core/DataTable.php @@ -469,11 +469,13 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess * metadata can be used to specify a different type of operation. * * @param \Piwik\DataTable $tableToSum + * @param bool $doAggregateSubTables + * @throws Exception */ public function addDataTable(DataTable $tableToSum, $doAggregateSubTables = true) { - if($tableToSum instanceof Simple) { - if($tableToSum->getRowsCount() > 1) { + if ($tableToSum instanceof Simple) { + if ($tableToSum->getRowsCount() > 1) { throw new Exception("Did not expect a Simple table with more than one row in addDataTable()"); } $row = $tableToSum->getFirstRow(); @@ -897,7 +899,7 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess foreach ($this->getRows() as $row) { $row->renameColumn($oldName, $newName); - if($doRenameColumnsOfSubTables) { + if ($doRenameColumnsOfSubTables) { if (($idSubDataTable = $row->getIdSubDataTable()) !== null) { Manager::getInstance()->getTable($idSubDataTable)->renameColumn($oldName, $newName); } @@ -1602,7 +1604,7 @@ class DataTable implements DataTableInterface, \IteratorAggregate, \ArrayAccess } else { $rowFound->sumRow($row, $copyMeta = true, $this->getMetadata(self::COLUMN_AGGREGATION_OPS_METADATA_NAME)); - if($doAggregateSubTables) { + 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 diff --git a/core/DataTable/Filter/AddColumnsProcessedMetricsGoal.php b/core/DataTable/Filter/AddColumnsProcessedMetricsGoal.php index 742f1aef6d..963ac9acbd 100644 --- a/core/DataTable/Filter/AddColumnsProcessedMetricsGoal.php +++ b/core/DataTable/Filter/AddColumnsProcessedMetricsGoal.php @@ -8,12 +8,10 @@ */ namespace Piwik\DataTable\Filter; -use Exception; use Piwik\DataTable; use Piwik\DataTable\Row; use Piwik\Metrics; use Piwik\Piwik; -use Piwik\Tracker\GoalManager; /** * Adds goal related metrics to a {@link DataTable} using metrics that already exist. diff --git a/core/DataTable/Filter/BeautifyRangeLabels.php b/core/DataTable/Filter/BeautifyRangeLabels.php index 534f484bff..bf5e8d65d9 100644 --- a/core/DataTable/Filter/BeautifyRangeLabels.php +++ b/core/DataTable/Filter/BeautifyRangeLabels.php @@ -65,7 +65,7 @@ class BeautifyRangeLabels extends ColumnCallbackReplace parent::__construct($table, 'label', array($this, 'beautify'), array()); $this->labelSingular = $labelSingular; - $this->labelPlural = $labelPlural; + $this->labelPlural = $labelPlural; } /** diff --git a/core/DataTable/Filter/CalculateEvolutionFilter.php b/core/DataTable/Filter/CalculateEvolutionFilter.php index 80f789919e..0ef6a30a2f 100755 --- a/core/DataTable/Filter/CalculateEvolutionFilter.php +++ b/core/DataTable/Filter/CalculateEvolutionFilter.php @@ -121,6 +121,7 @@ class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage { $value = self::getPercentageValue($value, $divisor, $this->quotientPrecision); $value = self::appendPercentSign($value); + return $value; } @@ -152,6 +153,7 @@ class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage if ($appendPercentSign) { $number = self::appendPercentSign($number); } + return $number; } @@ -165,6 +167,7 @@ class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage if ($number > 0) { $number = '+' . $number; } + return $number; } diff --git a/core/DataTable/Filter/ColumnCallbackAddColumnQuotient.php b/core/DataTable/Filter/ColumnCallbackAddColumnQuotient.php index 5cc83d8e3d..81d8eadf04 100644 --- a/core/DataTable/Filter/ColumnCallbackAddColumnQuotient.php +++ b/core/DataTable/Filter/ColumnCallbackAddColumnQuotient.php @@ -109,6 +109,7 @@ class ColumnCallbackAddColumnQuotient extends BaseFilter if ($divisor > 0 && $value > 0) { $quotient = round($value / $divisor, $this->quotientPrecision); } + return $quotient; } diff --git a/core/DataTable/Filter/ColumnCallbackAddMetadata.php b/core/DataTable/Filter/ColumnCallbackAddMetadata.php index e89000f8fd..c7945839cb 100644 --- a/core/DataTable/Filter/ColumnCallbackAddMetadata.php +++ b/core/DataTable/Filter/ColumnCallbackAddMetadata.php @@ -48,12 +48,12 @@ class ColumnCallbackAddMetadata extends BaseFilter if (!is_array($columnsToRead)) { $columnsToRead = array($columnsToRead); } - $this->columnsToRead = $columnsToRead; - $this->functionToApply = $functionToApply; + $this->columnsToRead = $columnsToRead; + $this->functionToApply = $functionToApply; $this->functionParameters = $functionParameters; - $this->metadataToAdd = $metadataToAdd; - $this->applyToSummaryRow = $applyToSummaryRow; + $this->metadataToAdd = $metadataToAdd; + $this->applyToSummaryRow = $applyToSummaryRow; } /** diff --git a/core/DataTable/Filter/ColumnCallbackDeleteRow.php b/core/DataTable/Filter/ColumnCallbackDeleteRow.php index 189fbd3b81..414bf71e8a 100644 --- a/core/DataTable/Filter/ColumnCallbackDeleteRow.php +++ b/core/DataTable/Filter/ColumnCallbackDeleteRow.php @@ -25,7 +25,6 @@ use Piwik\DataTable\BaseFilter; */ class ColumnCallbackDeleteRow extends BaseFilter { - private $columnToFilter; private $function; private $functionParams; diff --git a/core/DataTable/Filter/ColumnCallbackReplace.php b/core/DataTable/Filter/ColumnCallbackReplace.php index e33dfa9a14..ca53405d7e 100644 --- a/core/DataTable/Filter/ColumnCallbackReplace.php +++ b/core/DataTable/Filter/ColumnCallbackReplace.php @@ -54,14 +54,14 @@ class ColumnCallbackReplace extends BaseFilter $extraColumnParameters = array()) { parent::__construct($table); - $this->functionToApply = $functionToApply; + $this->functionToApply = $functionToApply; $this->functionParameters = $functionParameters; if (!is_array($columnsToFilter)) { $columnsToFilter = array($columnsToFilter); } - $this->columnsToFilter = $columnsToFilter; + $this->columnsToFilter = $columnsToFilter; $this->extraColumnParameters = $extraColumnParameters; } @@ -73,6 +73,7 @@ class ColumnCallbackReplace extends BaseFilter public function filter($table) { foreach ($table->getRows() as $row) { + $extraColumnParameters = array(); foreach ($this->extraColumnParameters as $columnName) { $extraColumnParameters[] = $row->getColumn($columnName); @@ -86,9 +87,11 @@ class ColumnCallbackReplace extends BaseFilter } $parameters = array_merge(array($value), $extraColumnParameters); + if (!is_null($this->functionParameters)) { $parameters = array_merge($parameters, $this->functionParameters); } + $newValue = call_user_func_array($this->functionToApply, $parameters); $this->setElementToReplace($row, $column, $newValue); $this->filterSubTable($row); diff --git a/core/DataTable/Filter/ColumnDelete.php b/core/DataTable/Filter/ColumnDelete.php index 5aac6d44a6..743f5afd86 100644 --- a/core/DataTable/Filter/ColumnDelete.php +++ b/core/DataTable/Filter/ColumnDelete.php @@ -91,6 +91,7 @@ class ColumnDelete extends BaseFilter * See {@link ColumnDelete}. * * @param DataTable $table + * @return DataTable */ public function filter($table) { diff --git a/core/DataTable/Filter/GroupBy.php b/core/DataTable/Filter/GroupBy.php index 8633fb2e9d..b899bb9059 100755 --- a/core/DataTable/Filter/GroupBy.php +++ b/core/DataTable/Filter/GroupBy.php @@ -59,9 +59,9 @@ class GroupBy extends BaseFilter { parent::__construct($table); - $this->groupByColumn = $groupByColumn; + $this->groupByColumn = $groupByColumn; $this->reduceFunction = $reduceFunction; - $this->parameters = $parameters; + $this->parameters = $parameters; } /** @@ -82,7 +82,7 @@ class GroupBy extends BaseFilter // reduce the group by column of this row $groupByColumnValue = $row->getColumn($this->groupByColumn); - $parameters = array_merge(array($groupByColumnValue), $this->parameters); + $parameters = array_merge(array($groupByColumnValue), $this->parameters); $groupByValue = call_user_func_array($this->reduceFunction, $parameters); if (!isset($groupByRows[$groupByValue])) { diff --git a/core/DataTable/Filter/Limit.php b/core/DataTable/Filter/Limit.php index 5cf848a50e..415be29602 100644 --- a/core/DataTable/Filter/Limit.php +++ b/core/DataTable/Filter/Limit.php @@ -34,9 +34,9 @@ class Limit extends BaseFilter public function __construct($table, $offset, $limit = -1, $keepSummaryRow = false) { parent::__construct($table); - $this->offset = $offset; - $this->limit = $limit; + $this->offset = $offset; + $this->limit = $limit; $this->keepSummaryRow = $keepSummaryRow; } diff --git a/core/DataTable/Filter/Sort.php b/core/DataTable/Filter/Sort.php index 683e93cffe..9df2250288 100644 --- a/core/DataTable/Filter/Sort.php +++ b/core/DataTable/Filter/Sort.php @@ -38,11 +38,13 @@ class Sort extends BaseFilter public function __construct($table, $columnToSort, $order = 'desc', $naturalSort = true, $recursiveSort = false) { parent::__construct($table); + if ($recursiveSort) { $table->enableRecursiveSort(); } + $this->columnToSort = $columnToSort; - $this->naturalSort = $naturalSort; + $this->naturalSort = $naturalSort; $this->setOrder($order); } @@ -55,10 +57,10 @@ class Sort extends BaseFilter { if ($order == 'asc') { $this->order = 'asc'; - $this->sign = 1; + $this->sign = 1; } else { $this->order = 'desc'; - $this->sign = -1; + $this->sign = -1; } } @@ -225,17 +227,21 @@ class Sort extends BaseFilter if ($table instanceof Simple) { return; } + if (empty($this->columnToSort)) { return; } + $rows = $table->getRows(); if (count($rows) == 0) { return; } + $row = current($rows); if ($row === false) { return; } + $this->columnToSort = $this->selectColumnToSort($row); $value = $row->getColumn($this->columnToSort); @@ -248,6 +254,7 @@ class Sort extends BaseFilter $methodToUse = "sortString"; } } + $table->sort(array($this, $methodToUse), $this->columnToSort); } } diff --git a/core/DataTable/Filter/Truncate.php b/core/DataTable/Filter/Truncate.php index 192d85b82f..120fc37760 100644 --- a/core/DataTable/Filter/Truncate.php +++ b/core/DataTable/Filter/Truncate.php @@ -89,9 +89,10 @@ class Truncate extends BaseFilter return; } - $rows = $table->getRows(); - $count = $table->getRowsCount(); + $rows = $table->getRows(); + $count = $table->getRowsCount(); $newRow = new Row(array(Row::COLUMNS => array('label' => DataTable::LABEL_SUMMARY_ROW))); + for ($i = $this->truncateAfter; $i < $count; $i++) { if (!isset($rows[$i])) { // case when the last row is a summary row, it is not indexed by $cout but by DataTable::ID_SUMMARY_ROW diff --git a/core/DataTable/Manager.php b/core/DataTable/Manager.php index c19060b803..d225b8fb87 100644 --- a/core/DataTable/Manager.php +++ b/core/DataTable/Manager.php @@ -63,6 +63,7 @@ class Manager extends Singleton if (!isset($this->tables[$idTable])) { throw new TableNotFoundException(sprintf("This report has been reprocessed since your last click. To see this error less often, please increase the timeout value in seconds in Settings > General Settings. (error: id %s not found).", $idTable)); } + return $this->tables[$idTable]; } @@ -86,6 +87,7 @@ class Manager extends Singleton $this->deleteTable($id); } } + if ($deleteWhenIdTableGreaterThan == 0) { $this->tables = array(); $this->nextTableId = 1; diff --git a/core/DataTable/Map.php b/core/DataTable/Map.php index dd8bec7ca5..8795eac134 100644 --- a/core/DataTable/Map.php +++ b/core/DataTable/Map.php @@ -246,12 +246,14 @@ class Map implements DataTableInterface public function getColumn($name) { $values = array(); + foreach ($this->getDataTables() as $table) { $moreValues = $table->getColumn($name); foreach ($moreValues as &$value) { $values[] = $value; } } + return $values; } diff --git a/core/DataTable/Renderer.php b/core/DataTable/Renderer.php index 5705b3e205..f825739611 100644 --- a/core/DataTable/Renderer.php +++ b/core/DataTable/Renderer.php @@ -161,13 +161,16 @@ abstract class Renderer extends BaseFactory { $className = ucfirst(strtolower($id)); $className = 'Piwik\DataTable\Renderer\\' . $className; + return $className; } protected static function getInvalidClassIdExceptionMessage($id) { $availableRenderers = implode(', ', self::getRenderers()); - return Piwik::translate('General_ExceptionInvalidRendererFormat', array(self::getClassNameFromClassId($id), $availableRenderers)); + $klassName = self::getClassNameFromClassId($id); + + return Piwik::translate('General_ExceptionInvalidRendererFormat', array($klassName, $availableRenderers)); } /** @@ -187,12 +190,15 @@ abstract class Renderer extends BaseFactory $value = @mb_convert_encoding($value, 'UTF-8', 'UTF-8'); } $value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); + $htmlentities = array(" ", "¡", "¢", "£", "¤", "¥", "¦", "§", "¨", "©", "ª", "«", "¬", "­", "®", "¯", "°", "±", "²", "³", "´", "µ", "¶", "·", "¸", "¹", "º", "»", "¼", "½", "¾", "¿", "À", "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "×", "Ø", "Ù", "Ú", "Û", "Ü", "Ý", "Þ", "ß", "à", "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì", "í", "î", "ï", "ð", "ñ", "ò", "ó", "ô", "õ", "ö", "÷", "ø", "ù", "ú", "û", "ü", "ý", "þ", "ÿ", "€"); - $xmlentities = array("¢", "£", "¤", "¥", "¦", "§", "¨", "©", "ª", "«", "¬", "­", "®", "¯", "°", "±", "²", "³", "´", "µ", "¶", "·", "¸", "¹", "º", "»", "¼", "½", "¾", "¿", "À", "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "×", "Ø", "Ù", "Ú", "Û", "Ü", "Ý", "Þ", "ß", "à", "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì", "í", "î", "ï", "ð", "ñ", "ò", "ó", "ô", "õ", "ö", "÷", "ø", "ù", "ú", "û", "ü", "ý", "þ", "ÿ", "€"); - $value = str_replace($htmlentities, $xmlentities, $value); + $xmlentities = array("¢", "£", "¤", "¥", "¦", "§", "¨", "©", "ª", "«", "¬", "­", "®", "¯", "°", "±", "²", "³", "´", "µ", "¶", "·", "¸", "¹", "º", "»", "¼", "½", "¾", "¿", "À", "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "×", "Ø", "Ù", "Ú", "Û", "Ü", "Ý", "Þ", "ß", "à", "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì", "í", "î", "ï", "ð", "ñ", "ò", "ó", "ô", "õ", "ö", "÷", "ø", "ù", "ú", "û", "ü", "ý", "þ", "ÿ", "€"); + $value = str_replace($htmlentities, $xmlentities, $value); + } elseif ($value === false) { $value = 0; } + return $value; } diff --git a/core/DataTable/Renderer/Console.php b/core/DataTable/Renderer/Console.php index 88161165fc..0e1c127fb1 100644 --- a/core/DataTable/Renderer/Console.php +++ b/core/DataTable/Renderer/Console.php @@ -142,7 +142,7 @@ class Console extends Renderer foreach ($metadata as $id => $metadataIn) { $output .= "<br />"; $output .= $prefix . " <b>$id</b><br />"; - if(is_array($metadataIn)) { + if (is_array($metadataIn)) { foreach ($metadataIn as $name => $value) { $output .= $prefix . $prefix . "$name => $value"; } diff --git a/core/DataTable/Renderer/Json.php b/core/DataTable/Renderer/Json.php index 8fea38a658..f53ea60e67 100644 --- a/core/DataTable/Renderer/Json.php +++ b/core/DataTable/Renderer/Json.php @@ -11,7 +11,6 @@ namespace Piwik\DataTable\Renderer; use Piwik\Common; use Piwik\DataTable\Renderer; use Piwik\DataTable; -use Piwik\ProxyHttp; /** * JSON export. diff --git a/core/DataTable/Row.php b/core/DataTable/Row.php index 72e6d67b6c..07946adfd1 100644 --- a/core/DataTable/Row.php +++ b/core/DataTable/Row.php @@ -183,7 +183,7 @@ class Row implements \ArrayAccess, \IteratorAggregate if (isset($this->c[self::COLUMNS][$oldName])) { $this->c[self::COLUMNS][$newName] = $this->c[self::COLUMNS][$oldName]; } - // outside the if() since we want to delete nulled columns + // outside the if () since we want to delete nulled columns unset($this->c[self::COLUMNS][$oldName]); } @@ -500,9 +500,10 @@ class Row implements \ArrayAccess, \IteratorAggregate * * @param \Piwik\DataTable\Row $rowToSum The row to sum to this row. * @param bool $enableCopyMetadata Whether metadata should be copied or not. - * @param array $aggregationOperations for columns that should not be summed, determine which + * @param array|bool $aggregationOperations for columns that should not be summed, determine which * aggregation should be used (min, max). format: * `array('column name' => 'function name')` + * @throws Exception */ public function sumRow(Row $rowToSum, $enableCopyMetadata = true, $aggregationOperations = false) { @@ -528,7 +529,7 @@ class Row implements \ArrayAccess, \IteratorAggregate if ($columnToSumName == Metrics::INDEX_MAX_ACTIONS) { $operation = 'max'; } - if(empty($operation)) { + if (empty($operation)) { throw new Exception("Unknown aggregation operation for column $columnToSumName."); } diff --git a/core/Date.php b/core/Date.php index c5b4cd7af6..5b8e0fab6e 100644 --- a/core/Date.php +++ b/core/Date.php @@ -273,15 +273,16 @@ class Date // Unit tests pass (@see Date.test.php) but I'm pretty sure this is not the right way to do it date_default_timezone_set($this->timezone); $dtzone = timezone_open('UTC'); - $time = date('r', $this->timestamp); - $dtime = date_create($time); + $time = date('r', $this->timestamp); + $dtime = date_create($time); + date_timezone_set($dtime, $dtzone); - $dateWithTimezone = date_format($dtime, 'r'); + $dateWithTimezone = date_format($dtime, 'r'); $dateWithoutTimezone = substr($dateWithTimezone, 0, -6); - $timestamp = strtotime($dateWithoutTimezone); + $timestamp = strtotime($dateWithoutTimezone); date_default_timezone_set('UTC'); - return (int)$timestamp; + return (int) $timestamp; } /** diff --git a/core/Db.php b/core/Db.php index e845a5ab6e..4ad62684f6 100644 --- a/core/Db.php +++ b/core/Db.php @@ -271,7 +271,7 @@ class Db * * @param string $table The name of the table to delete from. Must be prefixed (see {@link Piwik\Common::prefixTable()}). * @param string $where The where clause of the query. Must include the WHERE keyword. - * @param $orderBy The column to order by and the order by direction, eg, `idvisit ASC`. + * @param string $orderBy The column to order by and the order by direction, eg, `idvisit ASC`. * @param int $maxRowsPerQuery The maximum number of rows to delete per `DELETE` query. * @param array $parameters Parameters to bind for each query. * @return int The total number of rows deleted. diff --git a/core/Db/Adapter/Mysqli.php b/core/Db/Adapter/Mysqli.php index c864d057b0..fa74f35c9d 100644 --- a/core/Db/Adapter/Mysqli.php +++ b/core/Db/Adapter/Mysqli.php @@ -56,8 +56,9 @@ class Mysqli extends Zend_Db_Adapter_Mysqli implements AdapterInterface */ public function checkServerVersion() { - $serverVersion = $this->getServerVersion(); + $serverVersion = $this->getServerVersion(); $requiredVersion = Config::getInstance()->General['minimum_mysql_version']; + if (version_compare($serverVersion, $requiredVersion) === -1) { throw new Exception(Piwik::translate('General_ExceptionDatabaseVersion', array('MySQL', $serverVersion, $requiredVersion))); } @@ -72,6 +73,7 @@ class Mysqli extends Zend_Db_Adapter_Mysqli implements AdapterInterface { $serverVersion = $this->getServerVersion(); $clientVersion = $this->getClientVersion(); + // incompatible change to DECIMAL implementation in 5.0.3 if (version_compare($serverVersion, '5.0.3') >= 0 && version_compare($clientVersion, '5.0.3') < 0 @@ -168,10 +170,12 @@ class Mysqli extends Zend_Db_Adapter_Mysqli implements AdapterInterface public function getClientVersion() { $this->_connect(); - $version = $this->_connection->server_version; - $major = (int)($version / 10000); - $minor = (int)($version % 10000 / 100); + + $version = $this->_connection->server_version; + $major = (int)($version / 10000); + $minor = (int)($version % 10000 / 100); $revision = (int)($version % 100); + return $major . '.' . $minor . '.' . $revision; } } diff --git a/core/Db/Adapter/Pdo/Mssql.php b/core/Db/Adapter/Pdo/Mssql.php index fd0248958e..ab032e145d 100644 --- a/core/Db/Adapter/Pdo/Mssql.php +++ b/core/Db/Adapter/Pdo/Mssql.php @@ -66,7 +66,7 @@ class Mssql extends Zend_Db_Adapter_Pdo_Mssql implements AdapterInterface try { $serverName = $this->_config["host"]; - $database = $this->_config["dbname"]; + $database = $this->_config["dbname"]; if (is_null($database)) { $database = 'master'; } @@ -134,8 +134,9 @@ class Mssql extends Zend_Db_Adapter_Pdo_Mssql implements AdapterInterface */ public function checkServerVersion() { - $serverVersion = $this->getServerVersion(); + $serverVersion = $this->getServerVersion(); $requiredVersion = Config::getInstance()->General['minimum_mssql_version']; + if (version_compare($serverVersion, $requiredVersion) === -1) { throw new Exception(Piwik::translate('General_ExceptionDatabaseVersion', array('MSSQL', $serverVersion, $requiredVersion))); } @@ -149,7 +150,7 @@ class Mssql extends Zend_Db_Adapter_Pdo_Mssql implements AdapterInterface public function getServerVersion() { try { - $stmt = $this->query("SELECT CAST(SERVERPROPERTY('productversion') as VARCHAR) as productversion"); + $stmt = $this->query("SELECT CAST(SERVERPROPERTY('productversion') as VARCHAR) as productversion"); $result = $stmt->fetchAll(Zend_Db::FETCH_NUM); if (count($result)) { return $result[0][0]; @@ -169,6 +170,7 @@ class Mssql extends Zend_Db_Adapter_Pdo_Mssql implements AdapterInterface { $serverVersion = $this->getServerVersion(); $clientVersion = $this->getClientVersion(); + if (version_compare($serverVersion, '10') >= 0 && version_compare($clientVersion, '10') < 0 ) { @@ -224,6 +226,7 @@ class Mssql extends Zend_Db_Adapter_Pdo_Mssql implements AdapterInterface if (preg_match('/(?:\[|\s)([0-9]{4})(?:\]|\s)/', $e->getMessage(), $match)) { return $match[1] == $errno; } + return false; } diff --git a/core/Db/Adapter/Pdo/Mysql.php b/core/Db/Adapter/Pdo/Mysql.php index 59c3880bc9..3ed5ae9c0f 100644 --- a/core/Db/Adapter/Pdo/Mysql.php +++ b/core/Db/Adapter/Pdo/Mysql.php @@ -92,8 +92,9 @@ class Mysql extends Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface */ public function checkServerVersion() { - $serverVersion = $this->getServerVersion(); + $serverVersion = $this->getServerVersion(); $requiredVersion = Config::getInstance()->General['minimum_mysql_version']; + if (version_compare($serverVersion, $requiredVersion) === -1) { throw new Exception(Piwik::translate('General_ExceptionDatabaseVersion', array('MySQL', $serverVersion, $requiredVersion))); } @@ -108,6 +109,7 @@ class Mysql extends Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface { $serverVersion = $this->getServerVersion(); $clientVersion = $this->getClientVersion(); + // incompatible change to DECIMAL implementation in 5.0.3 if (version_compare($serverVersion, '5.0.3') >= 0 && version_compare($clientVersion, '5.0.3') < 0 @@ -159,6 +161,7 @@ class Mysql extends Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface if (preg_match('/(?:\[|\s)([0-9]{4})(?:\]|\s)/', $e->getMessage(), $match)) { return $match[1] == $errno; } + return false; } @@ -170,9 +173,11 @@ class Mysql extends Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface public function isConnectionUTF8() { $charsetInfo = $this->fetchAll('SHOW VARIABLES LIKE ?', array('character_set_connection')); + if (empty($charsetInfo)) { return false; } + $charset = $charsetInfo[0]['Value']; return $charset === 'utf8'; } diff --git a/core/Db/Adapter/Pdo/Pgsql.php b/core/Db/Adapter/Pdo/Pgsql.php index c68280fe28..0a37ab2dc9 100644 --- a/core/Db/Adapter/Pdo/Pgsql.php +++ b/core/Db/Adapter/Pdo/Pgsql.php @@ -47,6 +47,7 @@ class Pgsql extends Zend_Db_Adapter_Pdo_Pgsql implements AdapterInterface { $databaseVersion = $this->getServerVersion(); $requiredVersion = Config::getInstance()->General['minimum_pgsql_version']; + if (version_compare($databaseVersion, $requiredVersion) === -1) { throw new Exception(Piwik::translate('General_ExceptionDatabaseVersion', array('PostgreSQL', $databaseVersion, $requiredVersion))); } @@ -146,6 +147,7 @@ class Pgsql extends Zend_Db_Adapter_Pdo_Pgsql implements AdapterInterface if (preg_match('/([0-9]{2}[0-9P][0-9]{2})/', $e->getMessage(), $match)) { return $match[1] == $map[$errno]; } + return false; } diff --git a/core/Db/BatchInsert.php b/core/Db/BatchInsert.php index 858dad4e38..1e818c2073 100644 --- a/core/Db/BatchInsert.php +++ b/core/Db/BatchInsert.php @@ -123,7 +123,7 @@ class BatchInsert { // Chroot environment: prefix the path with the absolute chroot path $chrootPath = Config::getInstance()->General['absolute_chroot_path']; - if(!empty($chrootPath)) { + if (!empty($chrootPath)) { $filePath = $chrootPath . $filePath; } diff --git a/core/Db/Schema.php b/core/Db/Schema.php index e210de5835..c7823cf70a 100644 --- a/core/Db/Schema.php +++ b/core/Db/Schema.php @@ -38,7 +38,7 @@ class Schema extends Singleton private static function getSchemaClassName($schemaName) { // Upgrade from pre 2.0.4 - if(strtolower($schemaName) == 'myisam' + if (strtolower($schemaName) == 'myisam' || empty($schemaName)) { $schemaName = self::DEFAULT_SCHEMA; } diff --git a/core/DeviceDetectorCache.php b/core/DeviceDetectorCache.php index 2c637aa95e..ba65b82c9f 100644 --- a/core/DeviceDetectorCache.php +++ b/core/DeviceDetectorCache.php @@ -32,6 +32,7 @@ class DeviceDetectorCache extends CacheFile implements \DeviceDetector\Cache\Cac if (empty($id)) { return false; } + $id = $this->cleanupId($id); if (array_key_exists($id, self::$staticCache)) { diff --git a/core/Error.php b/core/Error.php index f7decbbc16..c56e3301a7 100644 --- a/core/Error.php +++ b/core/Error.php @@ -8,11 +8,6 @@ */ namespace Piwik; -use Piwik\Common; -use Piwik\Log; -use Piwik\Piwik; -use Piwik\Version; - require_once PIWIK_INCLUDE_PATH . '/core/Log.php'; /** diff --git a/core/EventDispatcher.php b/core/EventDispatcher.php index d9d26b4377..d343da8beb 100644 --- a/core/EventDispatcher.php +++ b/core/EventDispatcher.php @@ -48,7 +48,7 @@ class EventDispatcher extends Singleton /** * Plugin\Manager instance used to get list of loaded plugins. * - * @var Piwik\Plugin\Manager + * @var \Piwik\Plugin\Manager */ private $pluginManager; diff --git a/core/ExceptionHandler.php b/core/ExceptionHandler.php index 0e526225d5..8566385070 100644 --- a/core/ExceptionHandler.php +++ b/core/ExceptionHandler.php @@ -9,7 +9,6 @@ namespace Piwik; use Piwik\API\ResponseBuilder; -use Piwik\Common; use Piwik\Plugin; /** diff --git a/core/Filechecks.php b/core/Filechecks.php index 33d0ed0696..3dc6d53195 100644 --- a/core/Filechecks.php +++ b/core/Filechecks.php @@ -43,7 +43,7 @@ class Filechecks $directoryToCheck = PIWIK_USER_PATH . $directoryToCheck; } - if(strpos($directoryToCheck, '/tmp/') !== false) { + if (strpos($directoryToCheck, '/tmp/') !== false) { $directoryToCheck = SettingsPiwik::rewriteTmpPathWithInstanceId($directoryToCheck); } @@ -87,9 +87,9 @@ class Filechecks $directoryList = "<code>chown -R ". self::getUserAndGroup() ." " . $realpath . "</code><br />" . $directoryList; } - if(function_exists('shell_exec')) { + if (function_exists('shell_exec')) { $currentUser = self::getUser(); - if(!empty($currentUser)) { + if (!empty($currentUser)) { $optionalUserInfo = " (running as user '" . $currentUser . "')"; } } @@ -211,13 +211,13 @@ class Filechecks private static function getUserAndGroup() { $user = self::getUser(); - if(!function_exists('shell_exec')) { + if (!function_exists('shell_exec')) { return $user . ':' . $user; } $group = trim(shell_exec('groups '. $user .' | cut -f3 -d" "')); - if(empty($group)) { + if (empty($group)) { $group = 'www-data'; } return $user . ':' . $group; @@ -225,7 +225,7 @@ class Filechecks private static function getUser() { - if(!function_exists('shell_exec')) { + if (!function_exists('shell_exec')) { return 'www-data'; } return trim(shell_exec('whoami')); diff --git a/core/FrontController.php b/core/FrontController.php index a50fb152ca..4b5ee6f20b 100644 --- a/core/FrontController.php +++ b/core/FrontController.php @@ -508,22 +508,22 @@ class FrontController extends Singleton protected function handleSSLRedirection() { // Specifically disable for the opt out iframe - if(Piwik::getModule() == 'CoreAdminHome' && Piwik::getAction() == 'optOut') { + if (Piwik::getModule() == 'CoreAdminHome' && Piwik::getAction() == 'optOut') { return; } // Disable Https for VisitorGenerator - if(Piwik::getModule() == 'VisitorGenerator') { + if (Piwik::getModule() == 'VisitorGenerator') { return; } - if(Common::isPhpCliMode()) { + if (Common::isPhpCliMode()) { return; } // Only enable this feature after Piwik is already installed - if(!SettingsPiwik::isPiwikInstalled()) { + if (!SettingsPiwik::isPiwikInstalled()) { return; } // proceed only when force_ssl = 1 - if(!SettingsPiwik::isHttpsForced()) { + if (!SettingsPiwik::isHttpsForced()) { return; } Url::redirectToHttps(); diff --git a/core/Http.php b/core/Http.php index 537330716a..16563ce617 100644 --- a/core/Http.php +++ b/core/Http.php @@ -165,7 +165,7 @@ class Http $aUrl = trim($aUrl); // other result data - $status = null; + $status = null; $headers = array(); if ($method == 'socket') { diff --git a/core/IP.php b/core/IP.php index 52f5f7c23f..691bc7442c 100644 --- a/core/IP.php +++ b/core/IP.php @@ -370,7 +370,7 @@ class IP { $proxyIps = array(); $config = Config::getInstance()->General; - if(isset($config['proxy_ips'])) { + if (isset($config['proxy_ips'])) { $proxyIps = $config['proxy_ips']; } if (!is_array($proxyIps)) { diff --git a/core/Log.php b/core/Log.php index a860dd1989..b3421d13e1 100644 --- a/core/Log.php +++ b/core/Log.php @@ -452,7 +452,7 @@ class Log extends Singleton if ($level == self::ERROR) { $message = $this->getMessageFormattedScreen($level, $tag, $datetime, $message); $this->writeErrorToStandardErrorOutput($message); - if(!isset($this->writers['screen'])) { + if (!isset($this->writers['screen'])) { echo $message; } } @@ -599,7 +599,7 @@ class Log extends Singleton */ private function writeErrorToStandardErrorOutput($message) { - if(defined('PIWIK_TEST_MODE')) { + if (defined('PIWIK_TEST_MODE')) { // do not log on stderr during tests (prevent display of errors in CI output) return; } diff --git a/core/Mail.php b/core/Mail.php index d26b08b154..179b1221ab 100644 --- a/core/Mail.php +++ b/core/Mail.php @@ -34,9 +34,13 @@ class Mail extends Zend_Mail public function setDefaultFromPiwik() { $customLogo = new CustomLogo(); - $fromEmailName = $customLogo->isEnabled() - ? Piwik::translate('CoreHome_WebAnalyticsReports') - : Piwik::translate('ScheduledReports_PiwikReports'); + + if ($customLogo->isEnabled()) { + $fromEmailName = Piwik::translate('CoreHome_WebAnalyticsReports'); + } else { + $fromEmailName = Piwik::translate('ScheduledReports_PiwikReports'); + } + $fromEmailAddress = Config::getInstance()->General['noreply_email_address']; $this->setFrom($fromEmailAddress, $fromEmailName); } @@ -77,20 +81,29 @@ class Mail extends Zend_Mail private function initSmtpTransport() { $mailConfig = Config::getInstance()->mail; + if (empty($mailConfig['host']) || $mailConfig['transport'] != 'smtp' ) { return; } + $smtpConfig = array(); - if (!empty($mailConfig['type'])) + if (!empty($mailConfig['type'])) { $smtpConfig['auth'] = strtolower($mailConfig['type']); - if (!empty($mailConfig['username'])) + } + + if (!empty($mailConfig['username'])) { $smtpConfig['username'] = $mailConfig['username']; - if (!empty($mailConfig['password'])) + } + + if (!empty($mailConfig['password'])) { $smtpConfig['password'] = $mailConfig['password']; - if (!empty($mailConfig['encryption'])) + } + + if (!empty($mailConfig['encryption'])) { $smtpConfig['ssl'] = $mailConfig['encryption']; + } $tr = new \Zend_Mail_Transport_Smtp($mailConfig['host'], $smtpConfig); Mail::setDefaultTransport($tr); @@ -112,12 +125,12 @@ class Mail extends Zend_Mail */ protected function parseDomainPlaceholderAsPiwikHostName($email) { - $hostname = Config::getInstance()->mail['defaultHostnameIfEmpty']; + $hostname = Config::getInstance()->mail['defaultHostnameIfEmpty']; $piwikHost = Url::getCurrentHost($hostname); // If known Piwik URL, use it instead of "localhost" $piwikUrl = SettingsPiwik::getPiwikUrl(); - $url = parse_url($piwikUrl); + $url = parse_url($piwikUrl); if ($this->isHostDefinedAndNotLocal($url)) { $piwikHost = $url['host']; } diff --git a/core/Menu/Group.php b/core/Menu/Group.php index 17e7c9bc5c..90e063e264 100644 --- a/core/Menu/Group.php +++ b/core/Menu/Group.php @@ -18,8 +18,8 @@ class Group public function add($subTitleMenu, $url, $tooltip = false) { $this->items[] = array( - 'name' => $subTitleMenu, - 'url' => $url, + 'name' => $subTitleMenu, + 'url' => $url, 'tooltip' => $tooltip );; } diff --git a/core/Menu/MenuAbstract.php b/core/Menu/MenuAbstract.php index 1fe1152c98..8fcc4786cc 100644 --- a/core/Menu/MenuAbstract.php +++ b/core/Menu/MenuAbstract.php @@ -9,7 +9,6 @@ namespace Piwik\Menu; use Piwik\Common; -use Piwik\Log; use Piwik\Plugins\SitesManager\API; use Piwik\Singleton; use Piwik\Plugin\Manager as PluginManager; @@ -215,8 +214,8 @@ abstract class MenuAbstract extends Singleton { foreach ($this->edits as $edit) { $mainMenuToEdit = $edit[0]; - $subMenuToEdit = $edit[1]; - $newUrl = $edit[2]; + $subMenuToEdit = $edit[1]; + $newUrl = $edit[2]; if ($subMenuToEdit === null) { $menuDataToEdit = @$this->menu[$mainMenuToEdit]; @@ -236,14 +235,14 @@ abstract class MenuAbstract extends Singleton { foreach($this->menuEntriesToRemove as $menuToDelete) { - if(empty($menuToDelete[1])) { + if (empty($menuToDelete[1])) { // Delete Main Menu - if(isset($this->menu[$menuToDelete[0]])) { + if (isset($this->menu[$menuToDelete[0]])) { unset($this->menu[$menuToDelete[0]]); } } else { // Delete Sub Menu - if(isset($this->menu[$menuToDelete[0]][$menuToDelete[1]])) { + if (isset($this->menu[$menuToDelete[0]][$menuToDelete[1]])) { unset($this->menu[$menuToDelete[0]][$menuToDelete[1]]); } } @@ -256,9 +255,10 @@ abstract class MenuAbstract extends Singleton { foreach ($this->renames as $rename) { $mainMenuOriginal = $rename[0]; - $subMenuOriginal = $rename[1]; - $mainMenuRenamed = $rename[2]; - $subMenuRenamed = $rename[3]; + $subMenuOriginal = $rename[1]; + $mainMenuRenamed = $rename[2]; + $subMenuRenamed = $rename[3]; + // Are we changing a submenu? if (!empty($subMenuOriginal)) { if (isset($this->menu[$mainMenuOriginal][$subMenuOriginal])) { diff --git a/core/Menu/MenuAdmin.php b/core/Menu/MenuAdmin.php index 5c814b6706..13e8480596 100644 --- a/core/Menu/MenuAdmin.php +++ b/core/Menu/MenuAdmin.php @@ -45,7 +45,9 @@ class MenuAdmin extends MenuAbstract */ public static function addEntry($adminMenuName, $url, $displayedForCurrentUser = true, $order = 20) { - self::getInstance()->add('General_Settings', $adminMenuName, $url, $displayedForCurrentUser, $order); + if ($displayedForCurrentUser) { + self::getInstance()->addItem('General_Settings', $adminMenuName, $url, $order); + } } /** @@ -59,7 +61,7 @@ class MenuAdmin extends MenuAbstract */ public function addDevelopmentItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('CoreAdminHome_MenuDevelopment', $menuName, $url, true, $order, $tooltip); + $this->addItem('CoreAdminHome_MenuDevelopment', $menuName, $url, $order, $tooltip); } /** @@ -73,7 +75,7 @@ class MenuAdmin extends MenuAbstract */ public function addDiagnosticItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('CoreAdminHome_MenuDiagnostic', $menuName, $url, true, $order, $tooltip); + $this->addItem('CoreAdminHome_MenuDiagnostic', $menuName, $url, $order, $tooltip); } /** @@ -87,7 +89,7 @@ class MenuAdmin extends MenuAbstract */ public function addPlatformItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('CorePluginsAdmin_MenuPlatform', $menuName, $url, true, $order, $tooltip); + $this->addItem('CorePluginsAdmin_MenuPlatform', $menuName, $url, $order, $tooltip); } /** @@ -101,7 +103,7 @@ class MenuAdmin extends MenuAbstract */ public function addSettingsItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('General_Settings', $menuName, $url, true, $order, $tooltip); + $this->addItem('General_Settings', $menuName, $url, $order, $tooltip); } /** @@ -115,7 +117,7 @@ class MenuAdmin extends MenuAbstract */ public function addManageItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('CoreAdminHome_MenuManage', $menuName, $url, true, $order, $tooltip); + $this->addItem('CoreAdminHome_MenuManage', $menuName, $url, $order, $tooltip); } /** diff --git a/core/Menu/MenuMain.php b/core/Menu/MenuMain.php index 5f27f3229e..adb6b538e9 100644 --- a/core/Menu/MenuMain.php +++ b/core/Menu/MenuMain.php @@ -11,7 +11,7 @@ namespace Piwik\Menu; /** * @deprecated since 2.4.0 * @see MenuReporting - * @method static \Piwik\Menu\MenuMain getInstance() + * @method static MenuMain getInstance() * @ignore */ class MenuMain extends MenuReporting diff --git a/core/Menu/MenuReporting.php b/core/Menu/MenuReporting.php index 28fddd8313..ac35151bcb 100644 --- a/core/Menu/MenuReporting.php +++ b/core/Menu/MenuReporting.php @@ -45,7 +45,7 @@ class MenuReporting extends MenuAbstract */ public function addVisitorsItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('General_Visitors', $menuName, $url, true, $order, $tooltip); + $this->addItem('General_Visitors', $menuName, $url, $order, $tooltip); } /** @@ -59,7 +59,7 @@ class MenuReporting extends MenuAbstract */ public function addActionsItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('General_Actions', $menuName, $url, true, $order, $tooltip); + $this->addItem('General_Actions', $menuName, $url, $order, $tooltip); } /** @@ -88,7 +88,7 @@ class MenuReporting extends MenuAbstract */ public function addReferrersItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('Referrers_Referrers', $menuName, $url, true, $order, $tooltip); + $this->addItem('Referrers_Referrers', $menuName, $url, $order, $tooltip); } /** diff --git a/core/Menu/MenuUser.php b/core/Menu/MenuUser.php index ad9b195d46..758ac3d578 100755 --- a/core/Menu/MenuUser.php +++ b/core/Menu/MenuUser.php @@ -26,7 +26,7 @@ namespace Piwik\Menu; * ); * } * - * @method static \Piwik\Menu\MenuUser getInstance() + * @method static MenuUser getInstance() */ class MenuUser extends MenuAbstract { @@ -42,7 +42,7 @@ class MenuUser extends MenuAbstract */ public function addManageItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('CoreAdminHome_MenuManage', $menuName, $url, true, $order, $tooltip); + $this->addItem('CoreAdminHome_MenuManage', $menuName, $url, $order, $tooltip); } /** @@ -56,7 +56,7 @@ class MenuUser extends MenuAbstract */ public function addPlatformItem($menuName, $url, $order = 50, $tooltip = false) { - $this->add('CorePluginsAdmin_MenuPlatform', $menuName, $url, true, $order, $tooltip); + $this->addItem('CorePluginsAdmin_MenuPlatform', $menuName, $url, $order, $tooltip); } /** diff --git a/core/Metrics.php b/core/Metrics.php index 03b9e2e094..0f8baf5a10 100644 --- a/core/Metrics.php +++ b/core/Metrics.php @@ -175,9 +175,11 @@ class Metrics public static function getVisitsMetricNames() { $names = array(); + foreach (self::$metricsAggregatedFromLogs as $metricId) { $names[$metricId] = self::$mappingFromIdToName[$metricId]; } + return $names; } diff --git a/core/Metrics/Processed.php b/core/Metrics/Processed.php index bbc638828a..0e6b7c969b 100644 --- a/core/Metrics/Processed.php +++ b/core/Metrics/Processed.php @@ -11,8 +11,6 @@ namespace Piwik\Metrics; use Piwik\Metrics; use Piwik\DataTable\Row; use Piwik\DataTable; -use Piwik\Piwik; -use Piwik\Tracker\GoalManager; class Processed extends Base { diff --git a/core/MetricsFormatter.php b/core/MetricsFormatter.php index 8c58215e30..8554663525 100644 --- a/core/MetricsFormatter.php +++ b/core/MetricsFormatter.php @@ -61,10 +61,10 @@ class MetricsFormatter // Display 01:45:17 time format if ($displayTimeAsSentence === false) { - $hours = floor($numberOfSeconds / 3600); + $hours = floor($numberOfSeconds / 3600); $minutes = floor(($reminder = ($numberOfSeconds - $hours * 3600)) / 60); $seconds = floor($reminder - $minutes * 60); - $time = sprintf("%02s", $hours) . ':' . sprintf("%02s", $minutes) . ':' . sprintf("%02s", $seconds); + $time = sprintf("%02s", $hours) . ':' . sprintf("%02s", $minutes) . ':' . sprintf("%02s", $seconds); $centiSeconds = ($numberOfSeconds * 100) % 100; if ($centiSeconds) { $time .= '.' . sprintf("%02s", $centiSeconds); @@ -76,19 +76,19 @@ class MetricsFormatter } $secondsInYear = 86400 * 365.25; - $years = floor($numberOfSeconds / $secondsInYear); + $years = floor($numberOfSeconds / $secondsInYear); $minusYears = $numberOfSeconds - $years * $secondsInYear; - $days = floor($minusYears / 86400); + $days = floor($minusYears / 86400); $minusDays = $numberOfSeconds - $days * 86400; - $hours = floor($minusDays / 3600); + $hours = floor($minusDays / 3600); $minusDaysAndHours = $minusDays - $hours * 3600; $minutes = floor($minusDaysAndHours / 60); - $seconds = $minusDaysAndHours - $minutes * 60; + $seconds = $minusDaysAndHours - $minutes * 60; $precision = ($seconds > 0 && $seconds < 0.01 ? 3 : 2); - $seconds = round($seconds, $precision); + $seconds = round($seconds, $precision); if ($years > 0) { $return = sprintf(Piwik::translate('General_YearsDays'), $years, $days); @@ -109,6 +109,7 @@ class MetricsFormatter if ($isHtml) { return str_replace(' ', ' ', $return); } + return $return; } @@ -134,6 +135,7 @@ class MetricsFormatter break; } } + return round($size, $precision) . " " . $currentUnit; } @@ -175,6 +177,7 @@ class MetricsFormatter $value = sprintf("%01." . $precision . "f", $value); } } + $prettyMoney = $currencyBefore . $space . $value . $currencyAfter; return $prettyMoney; } @@ -196,16 +199,19 @@ class MetricsFormatter $timeAsSentence = (substr($columnName, -16) == '_time_generation'); return self::getPrettyTimeFromSeconds($value, $timeAsSentence); } + // Add revenue symbol to revenues if (strpos($columnName, 'revenue') !== false && strpos($columnName, 'evolution') === false) { return self::getPrettyMoney($value, $idSite, $isHtml); } + // Add % symbol to rates if (strpos($columnName, '_rate') !== false) { if (strpos($value, "%") === false) { return $value . "%"; } } + return $value; } @@ -217,12 +223,14 @@ class MetricsFormatter */ public static function getCurrencySymbol($idSite) { - $symbols = MetricsFormatter::getCurrencyList(); - $site = new Site($idSite); + $symbols = MetricsFormatter::getCurrencyList(); + $site = new Site($idSite); $currency = $site->getCurrency(); + if (isset($symbols[$currency])) { return $symbols[$currency][0]; } + return ''; } @@ -235,10 +243,12 @@ class MetricsFormatter public static function getCurrencyList() { static $currenciesList = null; + if (is_null($currenciesList)) { require_once PIWIK_INCLUDE_PATH . '/core/DataFiles/Currencies.php'; $currenciesList = $GLOBALS['Piwik_CurrencyList']; } + return $currenciesList; } } diff --git a/core/Nonce.php b/core/Nonce.php index 3937c4f94b..1b64b87933 100644 --- a/core/Nonce.php +++ b/core/Nonce.php @@ -160,7 +160,7 @@ class Nonce * @param string $nonceName The nonce's unique ID. See {@link getNonce()}. * @param string|null $nonce The nonce from the client. If `null`, the value from the * **nonce** query parameter is used. - * @throws Exception if the nonce is invalid. See {@link verifyNonce()}. + * @throws \Exception if the nonce is invalid. See {@link verifyNonce()}. */ public static function checkNonce($nonceName, $nonce = null) { diff --git a/core/Option.php b/core/Option.php index c2c7816bba..c4410520ea 100644 --- a/core/Option.php +++ b/core/Option.php @@ -68,7 +68,7 @@ class Option */ public static function set($name, $value, $autoload = 0) { - return self::getInstance()->setValue($name, $value, $autoload); + self::getInstance()->setValue($name, $value, $autoload); } /** @@ -79,7 +79,7 @@ class Option */ public static function delete($name, $value = null) { - return self::getInstance()->deleteValue($name, $value); + self::getInstance()->deleteValue($name, $value); } /** @@ -91,7 +91,7 @@ class Option */ public static function deleteLike($namePattern, $value = null) { - return self::getInstance()->deleteNameLike($namePattern, $value); + self::getInstance()->deleteNameLike($namePattern, $value); } public static function clearCachedOption($name) @@ -162,12 +162,13 @@ class Option if (isset($this->all[$name])) { return $this->all[$name]; } - $value = Db::fetchOne('SELECT option_value ' . - 'FROM `' . Common::prefixTable('option') . '` ' . - 'WHERE option_name = ?', $name); + $value = Db::fetchOne('SELECT option_value FROM `' . Common::prefixTable('option') . '` ' . + 'WHERE option_name = ?', $name); + if ($value === false) { return false; } + $this->all[$name] = $value; return $value; } @@ -184,11 +185,11 @@ class Option protected function deleteValue($name, $value) { - $sql = 'DELETE FROM `' . Common::prefixTable('option') . '` WHERE option_name = ?'; + $sql = 'DELETE FROM `' . Common::prefixTable('option') . '` WHERE option_name = ?'; $bind[] = $name; if (isset($value)) { - $sql .= ' AND option_value = ?'; + $sql .= ' AND option_value = ?'; $bind[] = $value; } @@ -199,11 +200,11 @@ class Option protected function deleteNameLike($name, $value = null) { - $sql = 'DELETE FROM `' . Common::prefixTable('option') . '` WHERE option_name LIKE ?'; + $sql = 'DELETE FROM `' . Common::prefixTable('option') . '` WHERE option_name LIKE ?'; $bind[] = $name; if (isset($value)) { - $sql .= ' AND option_value = ?'; + $sql .= ' AND option_value = ?'; $bind[] = $value; } @@ -214,7 +215,7 @@ class Option protected function getNameLike($name) { - $sql = 'SELECT option_name, option_value FROM `' . Common::prefixTable('option') . '` WHERE option_name LIKE ?'; + $sql = 'SELECT option_name, option_value FROM `' . Common::prefixTable('option') . '` WHERE option_name LIKE ?'; $bind = array($name); $result = array(); @@ -235,9 +236,8 @@ class Option return; } - $all = Db::fetchAll('SELECT option_value, option_name - FROM `' . Common::prefixTable('option') . '` - WHERE autoload = 1'); + $all = Db::fetchAll('SELECT option_value, option_name FROM `' . Common::prefixTable('option') . '` + WHERE autoload = 1'); foreach ($all as $option) { $this->all[$option['option_name']] = $option['option_value']; } diff --git a/core/Period.php b/core/Period.php index 6898020ce7..1e3f188b5e 100644 --- a/core/Period.php +++ b/core/Period.php @@ -100,16 +100,20 @@ abstract class Period public function getDateStart() { $this->generate(); + if (count($this->subperiods) == 0) { return $this->getDate(); } + $periods = $this->getSubperiods(); + /** @var $currentPeriod Period */ $currentPeriod = $periods[0]; while ($currentPeriod->getNumberOfSubperiods() > 0) { - $periods = $currentPeriod->getSubperiods(); + $periods = $currentPeriod->getSubperiods(); $currentPeriod = $periods[0]; } + return $currentPeriod->getDate(); } @@ -121,16 +125,20 @@ abstract class Period public function getDateEnd() { $this->generate(); + if (count($this->subperiods) == 0) { return $this->getDate(); } + $periods = $this->getSubperiods(); + /** @var $currentPeriod Period */ $currentPeriod = $periods[count($periods) - 1]; while ($currentPeriod->getNumberOfSubperiods() > 0) { - $periods = $currentPeriod->getSubperiods(); + $periods = $currentPeriod->getSubperiods(); $currentPeriod = $periods[count($periods) - 1]; } + return $currentPeriod->getDate(); } @@ -212,10 +220,12 @@ abstract class Period public function toString($format = "Y-m-d") { $this->generate(); + $dateString = array(); foreach ($this->subperiods as $period) { $dateString[] = $period->toString($format); } + return $dateString; } @@ -259,6 +269,9 @@ abstract class Period */ public function getRangeString() { - return $this->getDateStart()->toString("Y-m-d") . "," . $this->getDateEnd()->toString("Y-m-d"); + $dateStart = $this->getDateStart(); + $dateEnd = $this->getDateEnd(); + + return $dateStart->toString("Y-m-d") . "," . $dateEnd->toString("Y-m-d"); } } diff --git a/core/Period/Day.php b/core/Period/Day.php index 5f64627e45..b8212844cd 100644 --- a/core/Period/Day.php +++ b/core/Period/Day.php @@ -37,8 +37,10 @@ class Day extends Period public function getLocalizedShortString() { //"Mon 15 Aug" - $date = $this->getDateStart(); - $out = $date->getLocalized(Piwik::translate('CoreHome_ShortDateFormat')); + $date = $this->getDateStart(); + $template = Piwik::translate('CoreHome_ShortDateFormat'); + + $out = $date->getLocalized($template); return $out; } @@ -50,8 +52,9 @@ class Day extends Period public function getLocalizedLongString() { //"Mon 15 Aug" - $date = $this->getDateStart(); + $date = $this->getDateStart(); $template = Piwik::translate('CoreHome_DateFormat'); + $out = $date->getLocalized($template); return $out; } diff --git a/core/Period/Factory.php b/core/Period/Factory.php index b490956531..05303f40df 100644 --- a/core/Period/Factory.php +++ b/core/Period/Factory.php @@ -60,7 +60,7 @@ class Factory public static function checkPeriodIsEnabled($period) { - if(!self::isPeriodEnabledForAPI($period)) { + if (!self::isPeriodEnabledForAPI($period)) { self::throwExceptionInvalidPeriod($period); } } diff --git a/core/Period/Month.php b/core/Period/Month.php index 167280f15b..4609180980 100644 --- a/core/Period/Month.php +++ b/core/Period/Month.php @@ -60,6 +60,7 @@ class Month extends Period if ($this->subperiodsProcessed) { return; } + parent::generate(); $date = $this->date; diff --git a/core/Period/Range.php b/core/Period/Range.php index 2ea6ab1792..36692dc0de 100644 --- a/core/Period/Range.php +++ b/core/Period/Range.php @@ -45,12 +45,14 @@ class Range extends Period public function __construct($strPeriod, $strDate, $timezone = 'UTC', $today = false) { $this->strPeriod = $strPeriod; - $this->strDate = $strDate; + $this->strDate = $strDate; + $this->timezone = $timezone; $this->defaultEndDate = null; - $this->timezone = $timezone; + if ($today === false) { $today = Date::factory('now', $this->timezone); } + $this->today = $today; } @@ -63,10 +65,12 @@ class Range extends Period { //"30 Dec 08 - 26 Feb 09" $dateStart = $this->getDateStart(); - $dateEnd = $this->getDateEnd(); - $template = Piwik::translate('CoreHome_ShortDateFormatWithYear'); + $dateEnd = $this->getDateEnd(); + $template = Piwik::translate('CoreHome_ShortDateFormatWithYear'); + $shortDateStart = $dateStart->getLocalized($template); - $shortDateEnd = $dateEnd->getLocalized($template); + $shortDateEnd = $dateEnd->getLocalized($template); + $out = "$shortDateStart - $shortDateEnd"; return $out; } @@ -90,9 +94,11 @@ class Range extends Period public function getDateStart() { $dateStart = parent::getDateStart(); + if (empty($dateStart)) { throw new Exception("Specified date range is invalid."); } + return $dateStart; } @@ -203,10 +209,12 @@ class Range extends Period } else { throw new Exception(Piwik::translate('General_ExceptionInvalidDateRange', array($this->strDate, ' \'lastN\', \'previousN\', \'YYYY-MM-DD,YYYY-MM-DD\''))); } + if ($this->strPeriod != 'range') { $this->fillArraySubPeriods($startDate, $endDate, $this->strPeriod); return; } + $this->processOptimalSubperiods($startDate, $endDate); // When period=range, we want End Date to be the actual specified end date, // rather than the end of the month / week / whatever is used for processing this range @@ -223,9 +231,11 @@ class Range extends Period public static function parseDateRange($dateString) { $matched = preg_match('/^([0-9]{4}-[0-9]{1,2}-[0-9]{1,2}),(([0-9]{4}-[0-9]{1,2}-[0-9]{1,2})|today|now|yesterday)$/D', trim($dateString), $regs); + if (empty($matched)) { return false; } + return $regs; } @@ -241,6 +251,7 @@ class Range extends Period if (!is_null($this->endDate)) { return $this->endDate; } + return parent::getDateEnd(); } @@ -425,7 +436,7 @@ class Range extends Period * @param int $lastN The number of periods of type `$period` that the result range should * span. * @param string $endDate The desired end date of the range. - * @param Site $site The site whose timezone should be used. + * @param \Piwik\Site $site The site whose timezone should be used. * @return string The date range string, eg, `'2012-01-02,2013-01-02'`. * @api */ @@ -434,6 +445,7 @@ class Range extends Period $last30Relative = new Range($period, $lastN, $site->getTimezone()); $last30Relative->setDefaultEndDate(Date::factory($endDate)); $date = $last30Relative->getDateStart()->toString() . "," . $last30Relative->getDateEnd()->toString(); + return $date; } diff --git a/core/Period/Week.php b/core/Period/Week.php index f7b7264943..23f7ab32b6 100644 --- a/core/Period/Week.php +++ b/core/Period/Week.php @@ -26,7 +26,7 @@ class Week extends Period { //"30 Dec - 6 Jan 09" $dateStart = $this->getDateStart(); - $dateEnd = $this->getDateEnd(); + $dateEnd = $this->getDateEnd(); $string = Piwik::translate('CoreHome_ShortWeekFormat'); $string = self::getTranslatedRange($string, $dateStart, $dateEnd); @@ -42,6 +42,7 @@ class Week extends Period { $format = Piwik::translate('CoreHome_LongWeekFormat'); $string = self::getTranslatedRange($format, $this->getDateStart(), $this->getDateEnd()); + return Piwik::translate('CoreHome_PeriodWeek') . " " . $string; } @@ -58,6 +59,7 @@ class Week extends Period $string = $dateStart->getLocalized($string); $string = str_replace('To%', '%', $string); $string = $dateEnd->getLocalized($string); + return $string; } @@ -68,10 +70,11 @@ class Week extends Period */ public function getPrettyString() { - $out = Piwik::translate('General_DateRangeFromTo', - array($this->getDateStart()->toString(), - $this->getDateEnd()->toString()) - ); + $dateStart = $this->getDateStart(); + $dateEnd = $this->getDateEnd(); + + $out = Piwik::translate('General_DateRangeFromTo', array($dateStart->toString(), $dateEnd->toString())); + return $out; } @@ -83,6 +86,7 @@ class Week extends Period if ($this->subperiodsProcessed) { return; } + parent::generate(); $date = $this->date; diff --git a/core/Period/Year.php b/core/Period/Year.php index 3582161e3a..cb2d202ff7 100644 --- a/core/Period/Year.php +++ b/core/Period/Year.php @@ -58,6 +58,7 @@ class Year extends Period if ($this->subperiodsProcessed) { return; } + parent::generate(); $year = $this->date->toString("Y"); @@ -78,10 +79,12 @@ class Year extends Period function toString($format = 'ignored') { $this->generate(); + $stringMonth = array(); foreach ($this->subperiods as $month) { $stringMonth[] = $month->getDateStart()->toString("Y") . "-" . $month->getDateStart()->toString("m") . "-01"; } + return $stringMonth; } } diff --git a/core/Piwik.php b/core/Piwik.php index c00d5e42e9..ea49b72675 100644 --- a/core/Piwik.php +++ b/core/Piwik.php @@ -9,7 +9,6 @@ namespace Piwik; use Exception; -use Piwik\Common; use Piwik\Db\Adapter; use Piwik\Db\Schema; use Piwik\Db; @@ -135,7 +134,7 @@ class Piwik // changes made to this code should be mirrored in plugins/CoreAdminHome/javascripts/jsTrackingGenerator.js var generateJsCode $jsCode = file_get_contents(PIWIK_INCLUDE_PATH . "/plugins/Morpheus/templates/javascriptCode.tpl"); $jsCode = htmlentities($jsCode); - if(substr($piwikUrl, 0, 4) !== 'http') { + if (substr($piwikUrl, 0, 4) !== 'http') { $piwikUrl = 'http://' . $piwikUrl; } preg_match('~^(http|https)://(.*)$~D', $piwikUrl, $matches); @@ -889,4 +888,4 @@ class Piwik return $result; } -}
\ No newline at end of file +} diff --git a/core/Plugin.php b/core/Plugin.php index 8839a96212..55a70ab501 100644 --- a/core/Plugin.php +++ b/core/Plugin.php @@ -354,7 +354,7 @@ class Plugin if ($this->cache->has()) { $components = $this->cache->get(); - if($this->includeComponents($components)) { + if ($this->includeComponents($components)) { return $components; } else { // problem including one cached file, refresh cache diff --git a/core/Plugin/ComponentFactory.php b/core/Plugin/ComponentFactory.php index 68415e9397..9cb9cd1c1b 100644 --- a/core/Plugin/ComponentFactory.php +++ b/core/Plugin/ComponentFactory.php @@ -74,7 +74,7 @@ class ComponentFactory * @param callback $predicate * @return mixed The component that satisfies $predicate or null if not found. */ - public static function getComponentIf($componentTypeClass, $pluginName, $predicate) + public static function getComponentif ($componentTypeClass, $pluginName, $predicate) { $pluginManager = PluginManager::getInstance(); diff --git a/core/Plugin/ConsoleCommand.php b/core/Plugin/ConsoleCommand.php index 884b6f60ee..29e2fc65f6 100644 --- a/core/Plugin/ConsoleCommand.php +++ b/core/Plugin/ConsoleCommand.php @@ -8,7 +8,6 @@ */ namespace Piwik\Plugin; -use Piwik\Common; use Symfony\Component\Console\Command\Command as SymfonyCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/core/Plugin/Controller.php b/core/Plugin/Controller.php index 3ebad0f1ed..53ceab3f75 100644 --- a/core/Plugin/Controller.php +++ b/core/Plugin/Controller.php @@ -897,7 +897,7 @@ abstract class Controller $tokenRequest = Common::getRequestVar('token_auth', false); $tokenUser = Piwik::getCurrentUserTokenAuth(); - if(empty($tokenRequest) && empty($tokenUser)) { + if (empty($tokenRequest) && empty($tokenUser)) { return; // UI tests } diff --git a/core/Plugin/ControllerAdmin.php b/core/Plugin/ControllerAdmin.php index b18fe67de6..e563e759f9 100644 --- a/core/Plugin/ControllerAdmin.php +++ b/core/Plugin/ControllerAdmin.php @@ -43,6 +43,7 @@ abstract class ControllerAdmin extends Controller private static function notifyAnyInvalidPlugin() { $missingPlugins = \Piwik\Plugin\Manager::getInstance()->getMissingPlugins(); + if (empty($missingPlugins)) { return; } @@ -50,9 +51,11 @@ abstract class ControllerAdmin extends Controller if (!Piwik::hasUserSuperUserAccess()) { return; } + $pluginsLink = Url::getCurrentQueryStringWithParametersModified(array( 'module' => 'CorePluginsAdmin', 'action' => 'plugins' )); + $invalidPluginsWarning = Piwik::translate('CoreAdminHome_InvalidPluginsWarning', array( self::getPiwikVersion(), '<strong>' . implode('</strong>, <strong>', $missingPlugins) . '</strong>')) @@ -167,8 +170,10 @@ abstract class ControllerAdmin extends Controller $view->currentAdminMenuName = MenuAdmin::getInstance()->getCurrentAdminMenuName(); $view->isDataPurgeSettingsEnabled = self::isDataPurgeSettingsEnabled(); - $view->enableFrames = PiwikConfig::getInstance()->General['enable_framed_settings']; - if (!$view->enableFrames) { + $enableFrames = PiwikConfig::getInstance()->General['enable_framed_settings']; + $view->enableFrames = $enableFrames; + + if (!$enableFrames) { $view->setXFrameOptions('sameorigin'); } @@ -192,6 +197,7 @@ abstract class ControllerAdmin extends Controller $view->adminMenu = $adminMenu; $notifications = $view->notifications; + if (empty($notifications)) { $view->notifications = NotificationManager::getAllNotificationsToDisplay(); NotificationManager::cancelAllNonPersistent(); diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index eb234c1b6c..da2ba679df 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -10,8 +10,6 @@ namespace Piwik\Plugin; use Piwik\Cache\PersistentCache; -use Piwik\Cache\PluginAwareStaticCache; -use Piwik\Cache\StaticCache; use Piwik\CacheFile; use Piwik\Common; use Piwik\Config as PiwikConfig; @@ -38,7 +36,7 @@ require_once PIWIK_INCLUDE_PATH . '/core/EventDispatcher.php'; /** * The singleton that manages plugin loading/unloading and installation/uninstallation. * - * @method static \Piwik\Plugin\Manager getInstance() + * @method static Manager getInstance() */ class Manager extends Singleton { @@ -166,7 +164,7 @@ class Manager extends Singleton public function isPluginOfficialAndNotBundledWithCore($pluginName) { static $gitModules; - if(empty($gitModules)) { + if (empty($gitModules)) { $gitModules = file_get_contents(PIWIK_INCLUDE_PATH . '/.gitmodules'); } // All submodules are officially maintained plugins @@ -541,7 +539,7 @@ class Manager extends Singleton $listPlugins = array_unique($listPlugins); foreach ($listPlugins as $pluginName) { // Hide plugins that are never going to be used - if($this->isPluginBogus($pluginName)) { + if ($this->isPluginBogus($pluginName)) { continue; } @@ -609,15 +607,15 @@ class Manager extends Singleton protected function isPluginThirdPartyAndBogus($pluginName) { - if($this->isPluginBundledWithCore($pluginName)) { + if ($this->isPluginBundledWithCore($pluginName)) { return false; } - if($this->isPluginBogus($pluginName)) { + if ($this->isPluginBogus($pluginName)) { return true; } $path = $this->getPluginsDirectory() . $pluginName; - if(!$this->isManifestFileFound($path)) { + if (!$this->isManifestFileFound($path)) { return true; } return false; @@ -773,7 +771,7 @@ class Manager extends Singleton $plugins = $this->getLoadedPlugins(); $enabled = $this->getActivatedPlugins(); - if(empty($enabled)) { + if (empty($enabled)) { return array(); } $enabled = array_combine($enabled, $enabled); diff --git a/core/Plugin/MetadataLoader.php b/core/Plugin/MetadataLoader.php index 25f48ce0a0..34bb90dcdc 100644 --- a/core/Plugin/MetadataLoader.php +++ b/core/Plugin/MetadataLoader.php @@ -101,6 +101,7 @@ class MetadataLoader ) { throw new Exception("Invalid JSON file: $path"); } + return $info; } } diff --git a/core/Plugin/Report.php b/core/Plugin/Report.php index 6d950babd2..9037ce664c 100644 --- a/core/Plugin/Report.php +++ b/core/Plugin/Report.php @@ -328,11 +328,12 @@ class Report { if ($this->menuTitle) { $action = $this->getMenuControllerAction(); - $menu->add($this->category, - $this->menuTitle, - array('module' => $this->module, 'action' => $action), - $this->isEnabled(), - $this->order); + if ($this->isEnabled()) { + $menu->addItem($this->category, + $this->menuTitle, + array('module' => $this->module, 'action' => $action), + $this->order); + } } } @@ -731,7 +732,7 @@ class Report */ public static function getForDimension(Dimension $dimension) { - return ComponentFactory::getComponentIf(__CLASS__, $dimension->getModule(), function (Report $report) use ($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/ViewDataTable.php b/core/Plugin/ViewDataTable.php index d7f72028cf..4f3b854127 100644 --- a/core/Plugin/ViewDataTable.php +++ b/core/Plugin/ViewDataTable.php @@ -275,11 +275,11 @@ abstract class ViewDataTable implements ViewInterface protected function assignRelatedReportsTitle() { - if(!empty($this->config->related_reports_title)) { + if (!empty($this->config->related_reports_title)) { // title already assigned by a plugin return; } - if(count($this->config->related_reports) == 1) { + if (count($this->config->related_reports) == 1) { $this->config->related_reports_title = Piwik::translate('General_RelatedReport') . ':'; } else { $this->config->related_reports_title = Piwik::translate('General_RelatedReports') . ':'; diff --git a/core/Plugin/Visualization.php b/core/Plugin/Visualization.php index e82a8d7f73..e7e79c62e2 100644 --- a/core/Plugin/Visualization.php +++ b/core/Plugin/Visualization.php @@ -498,6 +498,7 @@ class Visualization extends ViewDataTable 'filter_excludelowpop', 'filter_excludelowpop_value', ); + foreach ($deleteFromJavascriptVariables as $name) { if (isset($javascriptVariablesToSet[$name])) { unset($javascriptVariablesToSet[$name]); diff --git a/core/Profiler.php b/core/Profiler.php index 7468b1f5d6..2b92583d89 100644 --- a/core/Profiler.php +++ b/core/Profiler.php @@ -143,7 +143,7 @@ class Profiler { $totalTime = self::getDbElapsedSecs(); $queryCount = Profiler::getQueryCount(); - if($queryCount > 0) { + if ($queryCount > 0) { Log::debug(sprintf("Total queries = %d (total sql time = %.2fs)", $queryCount, $totalTime)); } } @@ -234,7 +234,7 @@ class Profiler $currentGitBranch = SettingsPiwik::getCurrentGitBranch(); $profilerNamespace = "piwik"; - if($currentGitBranch != 'master') { + if ($currentGitBranch != 'master') { $profilerNamespace .= "." . $currentGitBranch; } @@ -326,7 +326,7 @@ class Profiler { $runIds = file_get_contents( self::getPathToXHProfRunIds() ); $array = json_decode($runIds, $assoc = true); - if(!is_array($array)) { + if (!is_array($array)) { $array = array(); } return $array; diff --git a/core/ProxyHttp.php b/core/ProxyHttp.php index a1e7fda32c..69f7144b44 100644 --- a/core/ProxyHttp.php +++ b/core/ProxyHttp.php @@ -233,6 +233,7 @@ class ProxyHttp // FastCGI $key = 'Status:'; } + Common::sendHeader($key . ' ' . $status); } diff --git a/core/RankingQuery.php b/core/RankingQuery.php index f40ae1273e..f44845f075 100644 --- a/core/RankingQuery.php +++ b/core/RankingQuery.php @@ -215,7 +215,7 @@ class RankingQuery public function execute($innerQuery, $bind = array()) { $query = $this->generateQuery($innerQuery); - $data = Db::fetchAll($query, $bind); + $data = Db::fetchAll($query, $bind); if ($this->columnToMarkExcludedRows !== false) { // split the result into the regular result and the rows with special treatment diff --git a/core/Registry.php b/core/Registry.php index c57420e6f5..5022bf09e2 100644 --- a/core/Registry.php +++ b/core/Registry.php @@ -11,7 +11,7 @@ namespace Piwik; /** * Registry class. * - * @method static \Piwik\Registry getInstance() + * @method static Registry getInstance() * @api */ class Registry extends Singleton diff --git a/core/ReportRenderer/Csv.php b/core/ReportRenderer/Csv.php index 23ace2ac4d..94eca5172a 100644 --- a/core/ReportRenderer/Csv.php +++ b/core/ReportRenderer/Csv.php @@ -105,7 +105,7 @@ class Csv extends ReportRenderer ); $reportData = $csvRenderer->render($processedReport); - if(empty($reportData)) { + if (empty($reportData)) { $reportData = Piwik::translate('CoreHome_ThereIsNoDataForThisReport'); } diff --git a/core/ScheduledTask.php b/core/ScheduledTask.php index 15b702dab8..d570f5bea2 100644 --- a/core/ScheduledTask.php +++ b/core/ScheduledTask.php @@ -77,6 +77,7 @@ class ScheduledTask * should be executed and how long before the next execution. * @param int $priority The priority of the task. Tasks with a higher priority will be executed first. * Tasks with low priority will be executed last. + * @throws Exception */ public function __construct($objectInstance, $methodName, $methodParameter, $scheduledTime, $priority = self::NORMAL_PRIORITY) diff --git a/core/ScheduledTime.php b/core/ScheduledTime.php index f221a82a43..3da4afe98b 100644 --- a/core/ScheduledTime.php +++ b/core/ScheduledTime.php @@ -183,7 +183,7 @@ abstract class ScheduledTime * and a string description of the day within the period to execute the task on. * * @param string $periodType The scheduled period type. Can be `'hourly'`, `'daily'`, `'weekly'`, or `'monthly'`. - * @param string|int|false $periodDay A string describing the day within the scheduled period to execute + * @param bool|false|int|string $periodDay A string describing the day within the scheduled period to execute * the task on. Only valid for week and month periods. * * If `'weekly'` is supplied for `$periodType`, this should be a day @@ -192,6 +192,7 @@ abstract class ScheduledTime * If `'monthly'` is supplied for `$periodType`, this can be a numeric * day in the month or a day in one week of the month. For example, * `12`, `23`, `'first sunday'` or `'fourth tuesday'`. + * @throws Exception * @api */ public static function factory($periodType, $periodDay = false) @@ -203,13 +204,13 @@ abstract class ScheduledTime return new Daily(); case 'weekly': $result = new Weekly(); - if($periodDay !== false) { + if ($periodDay !== false) { $result->setDay($periodDay); } return $result; case 'monthly': $result = new Monthly($periodDay); - if($periodDay !== false) { + if ($periodDay !== false) { if (is_int($periodDay)) { $result->setDay($periodDay); } else { diff --git a/core/ScheduledTime/Monthly.php b/core/ScheduledTime/Monthly.php index d4900530e8..84189f9bad 100644 --- a/core/ScheduledTime/Monthly.php +++ b/core/ScheduledTime/Monthly.php @@ -46,7 +46,6 @@ class Monthly extends ScheduledTime $day = Weekly::getDayIntFromString($dayNumberString) % 7; // get week number - $week = false; $weekNumberString = strtolower($weekNumberString); if (isset(self::$weekNumberStringToInt[$weekNumberString])) { $week = self::$weekNumberStringToInt[$weekNumberString]; diff --git a/core/Segment.php b/core/Segment.php index e12b165028..a0952f3bd7 100644 --- a/core/Segment.php +++ b/core/Segment.php @@ -70,6 +70,7 @@ class Segment * @param string $segmentCondition The segment condition, eg, `'browserCode=ff;countryCode=CA'`. * @param array $idSites The list of sites the segment will be used with. Some segments are * dependent on the site, such as goal segments. + * @throws Exception */ public function __construct($segmentCondition, $idSites) { @@ -155,10 +156,10 @@ class Segment throw new Exception("You do not have enough permission to access the segment " . $name); } - if($matchType != SegmentExpression::MATCH_IS_NOT_NULL_NOR_EMPTY + if ($matchType != SegmentExpression::MATCH_IS_NOT_NULL_NOR_EMPTY && $matchType != SegmentExpression::MATCH_IS_NULL_OR_EMPTY) { - if(isset($segment['sqlFilterValue'])) { + if (isset($segment['sqlFilterValue'])) { $value = call_user_func($segment['sqlFilterValue'], $value); } diff --git a/core/Session/SaveHandler/DbTable.php b/core/Session/SaveHandler/DbTable.php index 249faca6e1..74fc5e388b 100644 --- a/core/Session/SaveHandler/DbTable.php +++ b/core/Session/SaveHandler/DbTable.php @@ -119,8 +119,7 @@ class DbTable implements Zend_Session_SaveHandler_Interface */ public function destroy($id) { - $sql = 'DELETE FROM ' . $this->config['name'] - . ' WHERE ' . $this->config['primary'] . ' = ?'; + $sql = 'DELETE FROM ' . $this->config['name'] . ' WHERE ' . $this->config['primary'] . ' = ?'; Db::get()->query($sql, array($id)); diff --git a/core/SettingsPiwik.php b/core/SettingsPiwik.php index 4e83190e70..26949c560a 100644 --- a/core/SettingsPiwik.php +++ b/core/SettingsPiwik.php @@ -179,7 +179,7 @@ class SettingsPiwik $url = $currentUrl; } - if(ProxyHttp::isHttps()) { + if (ProxyHttp::isHttps()) { $url = str_replace("http://", "https://", $url); } return $url; @@ -195,7 +195,7 @@ class SettingsPiwik $exists = file_exists($config); // Piwik is installed if the config file is found - if(!$exists) { + if (!$exists) { return false; } @@ -205,12 +205,12 @@ class SettingsPiwik if (array_key_exists('installation_in_progress', $general)) { $isInstallationInProgress = (bool) $general['installation_in_progress']; } - if($isInstallationInProgress) { + if ($isInstallationInProgress) { return false; } // Check that the database section is really set, ie. file is not empty - if(empty(Config::getInstance()->database['username'])) { + if (empty(Config::getInstance()->database['username'])) { return false; } return true; @@ -297,6 +297,8 @@ class SettingsPiwik * this will return false.. * * @param $piwikServerUrl + * @param bool $acceptInvalidSSLCertificates + * @throws Exception * @return bool */ public static function checkPiwikServerWorking($piwikServerUrl, $acceptInvalidSSLCertificates = false) @@ -337,7 +339,7 @@ class SettingsPiwik public static function getCurrentGitBranch() { $file = PIWIK_INCLUDE_PATH . '/.git/HEAD'; - if(!file_exists($file)) { + if (!file_exists($file)) { return ''; } $firstLineOfGitHead = file($file); @@ -385,19 +387,19 @@ class SettingsPiwik protected static function getPiwikInstanceId() { // until Piwik is installed, we use hostname as instance_id - if(!self::isPiwikInstalled() + if (!self::isPiwikInstalled() && Common::isPhpCliMode()) { // enterprise:install use case return Config::getHostname(); } // config.ini.php not ready yet, instance_id will not be set - if(!Config::getInstance()->existsLocalConfig()) { + if (!Config::getInstance()->existsLocalConfig()) { return false; } $instanceId = @Config::getInstance()->General['instance_id']; - if(!empty($instanceId)) { + if (!empty($instanceId)) { return $instanceId; } diff --git a/core/Site.php b/core/Site.php index 7efeee77ef..96b7316b76 100644 --- a/core/Site.php +++ b/core/Site.php @@ -94,7 +94,7 @@ class Site */ protected static function setSite($idSite, $infoSite) { - if(empty($idSite) || empty($infoSite)) { + if (empty($idSite) || empty($infoSite)) { throw new Exception("An unexpected website was found, check idSite in the request."); } @@ -361,7 +361,7 @@ class Site return API::getInstance()->getSitesIdWithAtLeastViewAccess($_restrictSitesToLogin); } - if(is_bool($ids)) { + if (is_bool($ids)) { return array(); } if (!is_array($ids)) { @@ -406,7 +406,7 @@ class Site $site = API::getInstance()->getSiteFromId($idsite); self::setSite($idsite, $site); } - if($field) { + if ($field) { return self::$infoSites[$idsite][$field]; } return self::$infoSites[$idsite]; diff --git a/core/Theme.php b/core/Theme.php index b0fe5abecb..f7f85a5291 100644 --- a/core/Theme.php +++ b/core/Theme.php @@ -64,7 +64,7 @@ class Theme return false; } $jsFiles = $info['javascript']; - if(!is_array($jsFiles)) { + if (!is_array($jsFiles)) { $jsFiles = array($jsFiles); } foreach($jsFiles as &$jsFile) { @@ -107,18 +107,18 @@ class Theme // Basic health check, we dont replace if not starting with plugins/ $posPluginsInPath = strpos($pathAsset, 'plugins'); - if( $posPluginsInPath !== 0) { + if ( $posPluginsInPath !== 0) { return $source; } // or if it's already rewritten - if(strpos($pathAsset, $this->themeName) !== false) { + if (strpos($pathAsset, $this->themeName) !== false) { return $source; } $pathPluginName = substr($pathAsset, strlen('plugins/')); $nextSlash = strpos($pathPluginName, '/'); - if($nextSlash === false) { + if ($nextSlash === false) { return $source; } $pathPluginName = substr($pathPluginName, 0, $nextSlash); @@ -133,11 +133,11 @@ class Theme // Strip trailing query string $fileToCheck = $overridingAsset; $queryStringPos = strpos($fileToCheck, '?'); - if( $queryStringPos !== false) { + if ( $queryStringPos !== false) { $fileToCheck = substr($fileToCheck, 0, $queryStringPos); } - if(file_exists($fileToCheck)) { + if (file_exists($fileToCheck)) { return str_replace($pathAsset, $overridingAsset, $source); } return $source; diff --git a/core/Tracker.php b/core/Tracker.php index 733f23d8a3..3aa27237a1 100644 --- a/core/Tracker.php +++ b/core/Tracker.php @@ -221,7 +221,7 @@ class Tracker */ public function main($args = null) { - if(!SettingsPiwik::isPiwikInstalled()) { + if (!SettingsPiwik::isPiwikInstalled()) { return $this->handleEmptyRequest(); } try { @@ -468,7 +468,7 @@ class Tracker Common::sendHeader('Content-Type: text/html; charset=utf-8'); echo $this->getMessageFromException($e); } else { - $this->outputTransparentGif(); + $this->outputTransparentGif (); } exit; } @@ -516,7 +516,7 @@ class Tracker } switch ($this->getState()) { case self::STATE_LOGGING_DISABLE: - $this->outputTransparentGif(); + $this->outputTransparentGif (); Common::printDebug("Logging disabled, display transparent logo"); break; @@ -528,7 +528,7 @@ class Tracker case self::STATE_NOSCRIPT_REQUEST: case self::STATE_NOTHING_TO_NOTICE: default: - $this->outputTransparentGif(); + $this->outputTransparentGif (); Common::printDebug("Nothing to notice => default behaviour"); break; } @@ -663,7 +663,7 @@ class Tracker return $visit; } - protected function outputTransparentGif() + protected function outputTransparentGif () { if (isset($GLOBALS['PIWIK_TRACKER_DEBUG']) && $GLOBALS['PIWIK_TRACKER_DEBUG'] @@ -717,7 +717,7 @@ class Tracker protected function handleEmptyRequest(Request $request = null) { - if(is_null($request)) { + if (is_null($request)) { $request = new Request($_GET + $_POST); } $countParameters = $request->getParamsCount(); diff --git a/core/Tracker/Action.php b/core/Tracker/Action.php index 6175d86e59..aa721a03c5 100644 --- a/core/Tracker/Action.php +++ b/core/Tracker/Action.php @@ -22,33 +22,51 @@ use Piwik\Tracker; */ abstract class Action { - const TYPE_PAGE_URL = 1; - const TYPE_OUTLINK = 2; - const TYPE_DOWNLOAD = 3; + const TYPE_PAGE_URL = 1; + const TYPE_OUTLINK = 2; + const TYPE_DOWNLOAD = 3; const TYPE_PAGE_TITLE = 4; - const TYPE_ECOMMERCE_ITEM_SKU = 5; + const TYPE_ECOMMERCE_ITEM_SKU = 5; const TYPE_ECOMMERCE_ITEM_NAME = 6; const TYPE_ECOMMERCE_ITEM_CATEGORY = 7; const TYPE_SITE_SEARCH = 8; - const TYPE_EVENT = 10; // Alias TYPE_EVENT_CATEGORY + const TYPE_EVENT = 10; // Alias TYPE_EVENT_CATEGORY const TYPE_EVENT_CATEGORY = 10; - const TYPE_EVENT_ACTION = 11; - const TYPE_EVENT_NAME = 12; + const TYPE_EVENT_ACTION = 11; + const TYPE_EVENT_NAME = 12; - const TYPE_CONTENT = 13; // Alias TYPE_CONTENT_NAME - const TYPE_CONTENT_NAME = 13; - const TYPE_CONTENT_PIECE = 14; - const TYPE_CONTENT_TARGET = 15; + const TYPE_CONTENT = 13; // Alias TYPE_CONTENT_NAME + const TYPE_CONTENT_NAME = 13; + const TYPE_CONTENT_PIECE = 14; + const TYPE_CONTENT_TARGET = 15; const TYPE_CONTENT_INTERACTION = 16; const DB_COLUMN_CUSTOM_FLOAT = 'custom_float'; private static $factoryPriority = array( - self::TYPE_PAGE_URL, self::TYPE_CONTENT, self::TYPE_SITE_SEARCH, self::TYPE_EVENT, self::TYPE_OUTLINK, self::TYPE_DOWNLOAD + self::TYPE_PAGE_URL, + self::TYPE_CONTENT, + self::TYPE_SITE_SEARCH, + self::TYPE_EVENT, + self::TYPE_OUTLINK, + self::TYPE_DOWNLOAD ); /** + * Public so that events listener can access it + * + * @var Request + */ + public $request; + + private $idLinkVisitAction; + private $actionIdsCached = array(); + private $actionName; + private $actionType; + private $actionUrl; + + /** * Makes the correct Action object based on the request. * * @param Request $request @@ -102,7 +120,7 @@ abstract class Action $instances = array(); foreach ($actions as $action) { - /** @var \Piwik\Tracker\Action $instance */ + /** @var \Piwik\Tracker\Action $action */ if ($action::shouldHandle($request)) { $instances[] = new $action($request); } @@ -111,19 +129,6 @@ abstract class Action return $instances; } - /** - * Public so that events listener can access it - * - * @var Request - */ - public $request; - - private $idLinkVisitAction; - private $actionIdsCached = array(); - private $actionName; - private $actionType; - private $actionUrl; - public function __construct($type, Request $request) { $this->actionType = $type; @@ -152,8 +157,7 @@ abstract class Action public function getCustomVariables() { - $customVariables = $this->request->getCustomVariables($scope = 'page'); - return $customVariables; + return $this->request->getCustomVariables($scope = 'page'); } // custom_float column @@ -164,8 +168,7 @@ abstract class Action protected function setActionName($name) { - $name = PageUrl::cleanupString((string)$name); - $this->actionName = $name; + $this->actionName = PageUrl::cleanupString((string)$name); } protected function setActionUrl($url) @@ -178,8 +181,7 @@ abstract class Action Common::printDebug(' After is "' . $url . '"'); } - $url = PageUrl::getUrlIfLookValid($url); - $this->actionUrl = $url; + $this->actionUrl = PageUrl::getUrlIfLookValid($url); } abstract protected function getActionsToLookup(); @@ -187,11 +189,13 @@ abstract class Action protected function getUrlAndType() { $url = $this->getActionUrl(); + if (!empty($url)) { // normalize urls by stripping protocol and www $url = PageUrl::normalizeUrl($url); return array($url['url'], self::TYPE_PAGE_URL, $url['prefixId']); } + return false; } @@ -214,9 +218,11 @@ abstract class Action public function getIdActionName() { - if(!isset($this->actionIdsCached['idaction_name'])) { + if (!isset($this->actionIdsCached['idaction_name'])) { + return false; } + return $this->actionIdsCached['idaction_name']; } @@ -230,24 +236,17 @@ abstract class Action return $this->idLinkVisitAction; } - public function writeDebugInfo() - { - $type = self::getTypeAsString($this->getActionType()); - Common::printDebug("Action is a $type, - Action name = " . $this->getActionName() . ", - Action URL = " . $this->getActionUrl()); - return true; - } - public static function getTypeAsString($type) { - $class = new \ReflectionClass("\\Piwik\\Tracker\\Action"); + $class = new \ReflectionClass("\\Piwik\\Tracker\\Action"); $constants = $class->getConstants(); $typeId = array_search($type, $constants); - if($typeId === false) { + + if (false === $typeId) { throw new Exception("Unexpected action type " . $type); } + return str_replace('TYPE_', '', $typeId); } @@ -262,24 +261,27 @@ abstract class Action */ public function loadIdsFromLogActionTable() { - if(!empty($this->actionIdsCached)) { + if (!empty($this->actionIdsCached)) { return; } - $actions = $this->getActionsToLookup(); + /** @var ActionDimension[] $dimensions */ $dimensions = ActionDimension::getAllDimensions(); + $actions = $this->getActionsToLookup(); foreach ($dimensions as $dimension) { $value = $dimension->onLookupAction($this->request, $this); - if ($value !== false) { + if (false !== $value) { $field = $dimension->getColumnName(); if (empty($field)) { - throw new Exception('Dimension ' . get_class($dimension) . ' does not define a field name'); + $dimensionClass = get_class($dimension); + throw new Exception('Dimension ' . $dimensionClass . ' does not define a field name'); } - $actions[$field] = array($value, $dimension->getActionId()); + $actionId = $dimension->getActionId(); + $actions[$field] = array($value, $actionId); Common::printDebug("$field = $value"); } } @@ -316,6 +318,7 @@ abstract class Action 'idaction_name_ref' => $idReferrerActionName ); + /** @var ActionDimension[] $dimensions */ $dimensions = ActionDimension::getAllDimensions(); foreach ($dimensions as $dimension) { @@ -347,12 +350,8 @@ abstract class Action } $visitAction = array_merge($visitAction, $customVariables); - $fields = implode(", ", array_keys($visitAction)); - $bind = array_values($visitAction); - $values = Common::getSqlStringFieldsArray($visitAction); - $sql = "INSERT INTO " . Common::prefixTable('log_link_visit_action') . " ($fields) VALUES ($values)"; - Tracker::getDatabase()->query($sql, $bind); + $this->recordAction($visitAction); $this->idLinkVisitAction = Tracker::getDatabase()->lastInsertId(); $visitAction['idlink_va'] = $this->idLinkVisitAction; @@ -370,13 +369,36 @@ abstract class Action Piwik::postEvent('Tracker.recordAction', array($trackerAction = $this, $visitAction)); } + public function writeDebugInfo() + { + $type = self::getTypeAsString($this->getActionType()); + $name = $this->getActionName(); + $url = $this->getActionUrl(); + + Common::printDebug("Action is a $type, + Action name = " . $name . ", + Action URL = " . $url); + + return true; + } + + private function recordAction($visitAction) + { + $fields = implode(", ", array_keys($visitAction)); + $bind = array_values($visitAction); + $values = Common::getSqlStringFieldsArray($visitAction); + + $sql = "INSERT INTO " . Common::prefixTable('log_link_visit_action') . " ($fields) VALUES ($values)"; + Tracker::getDatabase()->query($sql, $bind); + } + /** * @return bool */ - protected function isActionHasActionName() + private function isActionHasActionName() { - return in_array($this->getActionType(), array(self::TYPE_PAGE_TITLE, - self::TYPE_PAGE_URL, - self::TYPE_SITE_SEARCH)); + $types = array(self::TYPE_PAGE_TITLE, self::TYPE_PAGE_URL, self::TYPE_SITE_SEARCH); + + return in_array($this->getActionType(), $types); } } diff --git a/core/Tracker/ActionPageview.php b/core/Tracker/ActionPageview.php index fa3d0146dc..9088fc543a 100644 --- a/core/Tracker/ActionPageview.php +++ b/core/Tracker/ActionPageview.php @@ -38,7 +38,7 @@ class ActionPageview extends Action { return array( 'idaction_name' => array($this->getActionName(), Action::TYPE_PAGE_TITLE), - 'idaction_url' => $this->getUrlAndType() + 'idaction_url' => $this->getUrlAndType() ); } @@ -55,22 +55,38 @@ class ActionPageview extends Action private function cleanupActionName($actionName) { // get the delimiter, by default '/'; BC, we read the old action_category_delimiter first (see #1067) - $actionCategoryDelimiter = isset(Config::getInstance()->General['action_category_delimiter']) - ? Config::getInstance()->General['action_category_delimiter'] - : Config::getInstance()->General['action_url_category_delimiter']; + $actionCategoryDelimiter = $this->getActionCategoryDelimiter(); // create an array of the categories delimited by the delimiter $split = explode($actionCategoryDelimiter, $actionName); + $split = $this->trimEveryCategory($split); + $split = $this->removeEmptyCategories($split); - // trim every category - $split = array_map('trim', $split); + return $this->rebuildNameOfCleanedCategories($actionCategoryDelimiter, $split); + } + + private function rebuildNameOfCleanedCategories($actionCategoryDelimiter, $split) + { + return implode($actionCategoryDelimiter, $split); + } - // remove empty categories - $split = array_filter($split, 'strlen'); + private function removeEmptyCategories($split) + { + return array_filter($split, 'strlen'); + } + + private function trimEveryCategory($split) + { + return array_map('trim', $split); + } + + private function getActionCategoryDelimiter() + { + if (isset(Config::getInstance()->General['action_category_delimiter'])) { + return Config::getInstance()->General['action_category_delimiter']; + } - // rebuild the name from the array of cleaned categories - $actionName = implode($actionCategoryDelimiter, $split); - return $actionName; + return Config::getInstance()->General['action_url_category_delimiter']; } } diff --git a/core/Tracker/Cache.php b/core/Tracker/Cache.php index 0217b175de..db442378e7 100644 --- a/core/Tracker/Cache.php +++ b/core/Tracker/Cache.php @@ -45,16 +45,19 @@ class Cache */ static function getCacheWebsiteAttributes($idSite) { - if($idSite == 'all') { + if ('all' == $idSite) { return array(); } + $idSite = (int)$idSite; - if($idSite <= 0) { + if ($idSite <= 0) { return array(); } - $cache = self::getInstance(); - if (($cacheContent = $cache->get($idSite)) !== false) { + $cache = self::getInstance(); + $cacheContent = $cache->get($idSite); + + if (false !== $cacheContent) { return $cacheContent; } @@ -95,6 +98,7 @@ class Cache if (!empty($content)) { $cache->set($idSite, $content); } + return $content; } @@ -114,10 +118,12 @@ class Cache */ public static function getCacheGeneral() { - $cache = self::getInstance(); + $cache = self::getInstance(); $cacheId = 'general'; - if (($cacheContent = $cache->get($cacheId)) !== false) { + $cacheContent = $cache->get($cacheId); + + if (false !== $cacheContent) { return $cacheContent; } @@ -161,9 +167,10 @@ class Cache */ public static function setCacheGeneral($value) { - $cache = self::getInstance(); + $cache = self::getInstance(); $cacheId = 'general'; $cache->set($cacheId, $value); + return true; } @@ -177,6 +184,7 @@ class Cache if (!is_array($idSites)) { $idSites = array($idSites); } + foreach ($idSites as $idSite) { self::deleteCacheWebsiteAttributes($idSite); self::getCacheWebsiteAttributes($idSite); diff --git a/core/Tracker/Db.php b/core/Tracker/Db.php index 4ce13a0891..1fe081daac 100644 --- a/core/Tracker/Db.php +++ b/core/Tracker/Db.php @@ -77,10 +77,14 @@ abstract class Db */ protected function recordQueryProfile($query, $timer) { - if (!isset($this->queriesProfiling[$query])) $this->queriesProfiling[$query] = array('sum_time_ms' => 0, 'count' => 0); - $time = $timer->getTimeMs(2); + if (!isset($this->queriesProfiling[$query])) { + $this->queriesProfiling[$query] = array('sum_time_ms' => 0, 'count' => 0); + } + + $time = $timer->getTimeMs(2); $time += $this->queriesProfiling[$query]['sum_time_ms']; $count = $this->queriesProfiling[$query]['count'] + 1; + $this->queriesProfiling[$query] = array('sum_time_ms' => $time, 'count' => $count); } @@ -97,13 +101,12 @@ abstract class Db self::$profiling = false; foreach ($this->queriesProfiling as $query => $info) { - $time = $info['sum_time_ms']; + $time = $info['sum_time_ms']; $count = $info['count']; $queryProfiling = "INSERT INTO " . Common::prefixTable('log_profiling') . " (query,count,sum_time_ms) VALUES (?,$count,$time) - ON DUPLICATE KEY - UPDATE count=count+$count,sum_time_ms=sum_time_ms+$time"; + ON DUPLICATE KEY UPDATE count=count+$count,sum_time_ms=sum_time_ms+$time"; $this->query($queryProfiling, array($query)); } diff --git a/core/Tracker/Db/Mysqli.php b/core/Tracker/Db/Mysqli.php index 78e2d9ee29..e648c41af7 100644 --- a/core/Tracker/Db/Mysqli.php +++ b/core/Tracker/Db/Mysqli.php @@ -73,7 +73,16 @@ class Mysqli extends Db $timer = $this->initProfiler(); } - $this->connection = mysqli_connect($this->host, $this->username, $this->password, $this->dbname, $this->port, $this->socket); + $this->connection = mysqli_init(); + + // Make sure MySQL returns all matched rows on update queries including + // rows that actually didn't have to be updated because the values didn't + // change. This matches common behaviour among other database systems. + // See #6296 why this is important in tracker + $flags = MYSQLI_CLIENT_FOUND_ROWS; + mysqli_real_connect($this->connection, $this->host, $this->username, $this->password, $this->dbname, $this->port, $this->socket, $flags); + + // $this->connection = mysqli_connect($this->host, $this->username, $this->password, $this->dbname, $this->port, $this->socket); if (!$this->connection || mysqli_connect_errno()) { throw new DbException("Connect failed: " . mysqli_connect_error()); } @@ -205,8 +214,8 @@ class Mysqli extends Db return $result; } catch (Exception $e) { throw new DbException("Error query: " . $e->getMessage() . " - In query: $query - Parameters: " . var_export($parameters, true)); + In query: $query + Parameters: " . var_export($parameters, true)); } } @@ -278,57 +287,58 @@ class Mysqli extends Db return mysqli_affected_rows($this->connection); } - /** - * Start Transaction - * @return string TransactionID - */ - - public function beginTransaction() - { - if(!$this->activeTransaction === false ) { - return; - } - - if( $this->connection->autocommit(false) ) { - $this->activeTransaction = uniqid(); - return $this->activeTransaction; - } - } - - /** - * Commit Transaction - * @param string TransactionID from beginTransaction - */ - - public function commit($xid) - { - if($this->activeTransaction != $xid || $this->activeTransaction === false ) { - - return; - } - $this->activeTransaction = false; - - if(!$this->connection->commit() ) { - throw new DbException("Commit failed"); - } - $this->connection->autocommit(true); - } - - /** - * Rollback Transaction - * @param string TransactionID from beginTransaction - */ - - public function rollBack($xid) - { - if($this->activeTransaction != $xid || $this->activeTransaction === false ) { - return; - } - $this->activeTransaction = false; - - if(!$this->connection->rollback() ) { - throw new DbException("Rollback failed"); - } - $this->connection->autocommit(true); - } + /** + * Start Transaction + * @return string TransactionID + */ + public function beginTransaction() + { + if (!$this->activeTransaction === false ) { + return; + } + + if ( $this->connection->autocommit(false) ) { + $this->activeTransaction = uniqid(); + return $this->activeTransaction; + } + } + + /** + * Commit Transaction + * @param $xid + * @throws DbException + * @internal param TransactionID $string from beginTransaction + */ + public function commit($xid) + { + if ($this->activeTransaction != $xid || $this->activeTransaction === false ) { + + return; + } + $this->activeTransaction = false; + + if (!$this->connection->commit() ) { + throw new DbException("Commit failed"); + } + $this->connection->autocommit(true); + } + + /** + * Rollback Transaction + * @param $xid + * @throws DbException + * @internal param TransactionID $string from beginTransaction + */ + public function rollBack($xid) + { + if ($this->activeTransaction != $xid || $this->activeTransaction === false ) { + return; + } + $this->activeTransaction = false; + + if (!$this->connection->rollback() ) { + throw new DbException("Rollback failed"); + } + $this->connection->autocommit(true); + } } diff --git a/core/Tracker/Db/Pdo/Mysql.php b/core/Tracker/Db/Pdo/Mysql.php index a2f5a79b2c..ffc93b417b 100644 --- a/core/Tracker/Db/Pdo/Mysql.php +++ b/core/Tracker/Db/Pdo/Mysql.php @@ -195,8 +195,8 @@ class Mysql extends Db return $sth; } catch (PDOException $e) { throw new DbException("Error query: " . $e->getMessage() . " - In query: $query - Parameters: " . var_export($parameters, true)); + In query: $query + Parameters: " . var_export($parameters, true)); } } @@ -237,54 +237,55 @@ class Mysql extends Db return $queryResult->rowCount(); } - /** - * Start Transaction - * @return string TransactionID - */ - - public function beginTransaction() - { - if(!$this->activeTransaction === false ) { - return; - } - - if( $this->connection->beginTransaction() ) { - $this->activeTransaction = uniqid(); - return $this->activeTransaction; - } - } - - /** - * Commit Transaction - * @param string TransactionID from beginTransaction - */ + /** + * Start Transaction + * @return string TransactionID + */ + public function beginTransaction() + { + if (!$this->activeTransaction === false ) { + return; + } - public function commit($xid) - { - if($this->activeTransaction != $xid || $this->activeTransaction === false ) { - return; - } - $this->activeTransaction = false; + if ( $this->connection->beginTransaction() ) { + $this->activeTransaction = uniqid(); + return $this->activeTransaction; + } + } - if(!$this->connection->commit() ) { - throw new DbException("Commit failed"); - } - } + /** + * Commit Transaction + * @param $xid + * @throws DbException + * @internal param TransactionID $string from beginTransaction + */ + public function commit($xid) + { + if ($this->activeTransaction != $xid || $this->activeTransaction === false ) { + return; + } + $this->activeTransaction = false; - /** - * Rollback Transaction - * @param string TransactionID from beginTransaction - */ + if (!$this->connection->commit() ) { + throw new DbException("Commit failed"); + } + } - public function rollBack($xid) - { - if($this->activeTransaction != $xid || $this->activeTransaction === false ) { - return; - } - $this->activeTransaction = false; + /** + * Rollback Transaction + * @param $xid + * @throws DbException + * @internal param TransactionID $string from beginTransaction + */ + public function rollBack($xid) + { + if ($this->activeTransaction != $xid || $this->activeTransaction === false ) { + return; + } + $this->activeTransaction = false; - if(!$this->connection->rollBack() ) { - throw new DbException("Rollback failed"); - } - } + if (!$this->connection->rollBack() ) { + throw new DbException("Rollback failed"); + } + } } diff --git a/core/Tracker/GoalManager.php b/core/Tracker/GoalManager.php index 1a0944ad9a..7823b88cc2 100644 --- a/core/Tracker/GoalManager.php +++ b/core/Tracker/GoalManager.php @@ -34,6 +34,25 @@ class GoalManager const REVENUE_PRECISION = 2; const MAXIMUM_PRODUCT_CATEGORIES = 5; + + // In the GET items parameter, each item has the following array of information + const INDEX_ITEM_SKU = 0; + const INDEX_ITEM_NAME = 1; + const INDEX_ITEM_CATEGORY = 2; + const INDEX_ITEM_PRICE = 3; + const INDEX_ITEM_QUANTITY = 4; + + // Used in the array of items, internally to this class + const INTERNAL_ITEM_SKU = 0; + const INTERNAL_ITEM_NAME = 1; + const INTERNAL_ITEM_CATEGORY = 2; + const INTERNAL_ITEM_CATEGORY2 = 3; + const INTERNAL_ITEM_CATEGORY3 = 4; + const INTERNAL_ITEM_CATEGORY4 = 5; + const INTERNAL_ITEM_CATEGORY5 = 6; + const INTERNAL_ITEM_PRICE = 7; + const INTERNAL_ITEM_QUANTITY = 8; + public $idGoal; public $requestIsEcommerce; private $isGoalAnOrder; @@ -65,7 +84,7 @@ class GoalManager $this->idGoal = $request->getParam('idgoal'); $this->isGoalAnOrder = !empty($this->orderId); - $this->requestIsEcommerce = ($this->idGoal == 0); + $this->requestIsEcommerce = (0 == $this->idGoal); } public function isGoalAnOrder() @@ -87,30 +106,36 @@ class GoalManager public static function getGoalDefinitions($idSite) { $websiteAttributes = Cache::getCacheWebsiteAttributes($idSite); + if (isset($websiteAttributes['goals'])) { return $websiteAttributes['goals']; } + return array(); } public static function getGoalDefinition($idSite, $idGoal) { $goals = self::getGoalDefinitions($idSite); + foreach ($goals as $goal) { if ($goal['idgoal'] == $idGoal) { return $goal; } } + throw new Exception('Goal not found'); } public static function getGoalIds($idSite) { - $goals = self::getGoalDefinitions($idSite); + $goals = self::getGoalDefinitions($idSite); $goalIds = array(); + foreach ($goals as $goal) { $goalIds[] = $goal['idgoal']; } + return $goalIds; } @@ -131,14 +156,15 @@ class GoalManager $decodedActionUrl = $action->getActionUrl(); $actionType = $action->getActionType(); $goals = $this->getGoalDefinitions($idSite); + foreach ($goals as $goal) { $attribute = $goal['match_attribute']; // if the attribute to match is not the type of the current action - if ( (($attribute == 'url' || $attribute == 'title') && $actionType != Action::TYPE_PAGE_URL) - || ($attribute == 'file' && $actionType != Action::TYPE_DOWNLOAD) - || ($attribute == 'external_website' && $actionType != Action::TYPE_OUTLINK) - || ($attribute == 'manually') - || in_array($attribute, array('event_action', 'event_name', 'event_category')) && $actionType != Action::TYPE_EVENT + if ((($attribute == 'url' || $attribute == 'title') && $actionType != Action::TYPE_PAGE_URL) + || ($attribute == 'file' && $actionType != Action::TYPE_DOWNLOAD) + || ($attribute == 'external_website' && $actionType != Action::TYPE_OUTLINK) + || ($attribute == 'manually') + || in_array($attribute, array('event_action', 'event_name', 'event_category')) && $actionType != Action::TYPE_EVENT ) { continue; } @@ -169,23 +195,33 @@ class GoalManager $this->convertedGoals[] = $goal; } } + return count($this->convertedGoals) > 0; } + public function isManualGoalConversion() + { + return $this->idGoal > 0; + } + public function detectGoalId($idSite) { if (!Common::isGoalPluginEnabled()) { return false; } + $goals = $this->getGoalDefinitions($idSite); + if (!isset($goals[$this->idGoal])) { return false; } + $goal = $goals[$this->idGoal]; - $url = $this->request->getParam('url'); + $url = $this->request->getParam('url'); $goal['url'] = PageUrl::excludeQueryParametersFromUrl($url, $idSite); $this->convertedGoals[] = $goal; + return true; } @@ -199,18 +235,7 @@ class GoalManager */ public function recordGoals(Visitor $visitor, $visitorInformation, $visitCustomVariables, $action) { - $goal = array( - 'idvisit' => $visitorInformation['idvisit'], - 'idvisitor' => $visitorInformation['idvisitor'], - 'server_time' => Tracker::getDatetimeFromTimestamp($visitorInformation['visit_last_action_time']) - ); - - foreach (VisitDimension::getAllDimensions() as $dimension) { - $value = $dimension->onAnyGoalConversion($this->request, $visitor, $action); - if (false !== $value) { - $goal[$dimension->getColumnName()] = $value; - } - } + $goal = $this->getGoalFromVisitor($visitor, $visitorInformation, $action); // Copy Custom Variables from Visit row to the Goal conversion // Otherwise, set the Custom Variables found in the cookie sent with this request @@ -249,6 +274,7 @@ class GoalManager if (round($revenue) == $revenue) { return $revenue; } + return round($revenue, self::REVENUE_PRECISION); } @@ -291,7 +317,8 @@ class GoalManager // INSERT or Sync items in the Cart / Order for this visit & order $items = $this->getEcommerceItemsFromRequest(); - if ($items === false) { + + if (false === $items) { return; } @@ -338,12 +365,15 @@ class GoalManager private function getEcommerceItemsFromRequest() { $items = Common::unsanitizeInputValue($this->request->getParam('ec_items')); + if (empty($items)) { Common::printDebug("There are no Ecommerce items in the request"); // we still record an Ecommerce order without any item in it return array(); } + $items = Common::json_decode($items, $assoc = true); + if (!is_array($items)) { Common::printDebug("Error while json_decode the Ecommerce items = " . var_export($items, true)); return false; @@ -371,8 +401,7 @@ class GoalManager // Select all items currently in the Cart if any $sql = "SELECT idaction_sku, idaction_name, idaction_category, idaction_category2, idaction_category3, idaction_category4, idaction_category5, price, quantity, deleted, idorder as idorder_original_value FROM " . Common::prefixTable('log_conversion_item') . " - WHERE idvisit = ? - AND (idorder = ? OR idorder = ?)"; + WHERE idvisit = ? AND (idorder = ? OR idorder = ?)"; $bind = array($goal['idvisit'], isset($goal['idorder']) ? $goal['idorder'] : self::ITEM_IDORDER_ABANDONED_CART, @@ -385,6 +414,7 @@ class GoalManager Common::printDebug($itemsInDb); // Look at which items need to be deleted, which need to be added or updated, based on the SKU $skuFoundInDb = $itemsToUpdate = array(); + foreach ($itemsInDb as $itemInDb) { $skuFoundInDb[] = $itemInDb['idaction_sku']; @@ -435,27 +465,10 @@ class GoalManager $itemsToInsert[] = $item; } } + $this->insertEcommerceItems($goal, $itemsToInsert); } - // In the GET items parameter, each item has the following array of information - const INDEX_ITEM_SKU = 0; - const INDEX_ITEM_NAME = 1; - const INDEX_ITEM_CATEGORY = 2; - const INDEX_ITEM_PRICE = 3; - const INDEX_ITEM_QUANTITY = 4; - - // Used in the array of items, internally to this class - const INTERNAL_ITEM_SKU = 0; - const INTERNAL_ITEM_NAME = 1; - const INTERNAL_ITEM_CATEGORY = 2; - const INTERNAL_ITEM_CATEGORY2 = 3; - const INTERNAL_ITEM_CATEGORY3 = 4; - const INTERNAL_ITEM_CATEGORY4 = 5; - const INTERNAL_ITEM_CATEGORY5 = 6; - const INTERNAL_ITEM_PRICE = 7; - const INTERNAL_ITEM_QUANTITY = 8; - /** * Reads items from the request, then looks up the names from the lookup table * and returns a clean array of items ready for the database. @@ -468,9 +481,10 @@ class GoalManager // Clean up the items array $cleanedItems = array(); foreach ($items as $item) { - $name = $category = $category2 = $category3 = $category4 = $category5 = false; - $price = 0; + $name = $category = $category2 = $category3 = $category4 = $category5 = false; + $price = 0; $quantity = 1; + // items are passed in the request as an array: ( $sku, $name, $category, $price, $quantity ) if (empty($item[self::INDEX_ITEM_SKU])) { continue; @@ -562,6 +576,7 @@ class GoalManager $item[5] = $actionsLookedUp[$index * $columnsInEachRow + 5]; $item[6] = $actionsLookedUp[$index * $columnsInEachRow + 6]; } + return $cleanedItems; } @@ -579,6 +594,7 @@ class GoalManager if (empty($itemsToUpdate)) { return; } + Common::printDebug("Goal data used to update ecommerce items:"); Common::printDebug($goal); @@ -588,13 +604,10 @@ class GoalManager $updateParts = $sqlBind = array(); foreach ($newRow as $name => $value) { $updateParts[] = $name . " = ?"; - $sqlBind[] = $value; + $sqlBind[] = $value; } - $sql = 'UPDATE ' . Common::prefixTable('log_conversion_item') . " - SET " . implode($updateParts, ', ') . " - WHERE idvisit = ? - AND idorder = ? - AND idaction_sku = ?"; + $sql = 'UPDATE ' . Common::prefixTable('log_conversion_item') . " SET " . implode($updateParts, ', ') . " + WHERE idvisit = ? AND idorder = ? AND idaction_sku = ?"; $sqlBind[] = $newRow['idvisit']; $sqlBind[] = $item['idorder_original_value']; $sqlBind[] = $newRow['idaction_sku']; @@ -616,6 +629,7 @@ class GoalManager if (empty($itemsToInsert)) { return; } + Common::printDebug("Ecommerce items that are added to the cart/order"); Common::printDebug($itemsToInsert); @@ -625,6 +639,7 @@ class GoalManager VALUES "; $i = 0; $bind = array(); + foreach ($itemsToInsert as $item) { if ($i > 0) { $sql .= ','; @@ -634,6 +649,7 @@ class GoalManager $i++; $bind = array_merge($bind, $newRow); } + Tracker::getDatabase()->query($sql, $bind); Common::printDebug($sql); Common::printDebug($bind); @@ -685,7 +701,7 @@ class GoalManager Common::printDebug("- Goal " . $convertedGoal['idgoal'] . " matched. Recording..."); $conversion = $goal; $conversion['idgoal'] = $convertedGoal['idgoal']; - $conversion['url'] = $convertedGoal['url']; + $conversion['url'] = $convertedGoal['url']; if (!is_null($action)) { $conversion['idaction_url'] = $action->getIdActionUrl(); @@ -741,11 +757,11 @@ class GoalManager $newGoalDebug['idvisitor'] = bin2hex($newGoalDebug['idvisitor']); Common::printDebug($newGoalDebug); - $fields = implode(", ", array_keys($conversion)); + $fields = implode(", ", array_keys($conversion)); $bindFields = Common::getSqlStringFieldsArray($conversion); - $sql = 'INSERT IGNORE INTO ' . Common::prefixTable('log_conversion') . " - ($fields) VALUES ($bindFields) "; - $bind = array_values($conversion); + + $sql = 'INSERT IGNORE INTO ' . Common::prefixTable('log_conversion') . " ($fields) VALUES ($bindFields) "; + $bind = array_values($conversion); $result = Tracker::getDatabase()->query($sql, $bind); // If a record was inserted, we return true @@ -775,24 +791,29 @@ class GoalManager protected function updateExistingConversion($newGoal, $updateWhere) { $updateParts = $sqlBind = $updateWhereParts = array(); + foreach ($newGoal as $name => $value) { $updateParts[] = $name . " = ?"; - $sqlBind[] = $value; + $sqlBind[] = $value; } + foreach ($updateWhere as $name => $value) { $updateWhereParts[] = $name . " = ?"; - $sqlBind[] = $value; + $sqlBind[] = $value; } - $sql = 'UPDATE ' . Common::prefixTable('log_conversion') . " - SET " . implode($updateParts, ', ') . " - WHERE " . implode($updateWhereParts, ' AND '); + + $table = Common::prefixTable('log_conversion'); + $parts = implode($updateParts, ', '); + $sql = 'UPDATE ' . $table . " SET " . $parts . " WHERE " . implode($updateWhereParts, ' AND '); try { Tracker::getDatabase()->query($sql, $sqlBind); } catch(Exception $e){ Common::printDebug("There was an error while updating the Conversion: " . $e->getMessage()); + return false; } + return true; } @@ -842,6 +863,7 @@ class GoalManager throw new Exception(Piwik::translate('General_ExceptionInvalidGoalPattern', array($pattern_type))); break; } + return $match; } @@ -859,7 +881,7 @@ class GoalManager foreach ($dimensions as $dimension) { $value = $dimension->$hook($this->request, $visitor, $action, $this); - if ($value !== false) { + if (false !== $value) { $fieldName = $dimension->getColumnName(); $visitor->setVisitorColumn($fieldName, $value); @@ -869,4 +891,24 @@ class GoalManager return $valuesToUpdate; } + + private function getGoalFromVisitor(Visitor $visitor, $visitorInformation, $action) + { + $goal = array( + 'idvisit' => $visitorInformation['idvisit'], + 'idvisitor' => $visitorInformation['idvisitor'], + 'server_time' => Tracker::getDatetimeFromTimestamp($visitorInformation['visit_last_action_time']) + ); + + $visitDimensions = VisitDimension::getAllDimensions(); + + foreach ($visitDimensions as $dimension) { + $value = $dimension->onAnyGoalConversion($this->request, $visitor, $action); + if (false !== $value) { + $goal[$dimension->getColumnName()] = $value; + } + } + + return $goal; + } } diff --git a/core/Tracker/PageUrl.php b/core/Tracker/PageUrl.php index 1d8486eda0..ae55b48aac 100644 --- a/core/Tracker/PageUrl.php +++ b/core/Tracker/PageUrl.php @@ -49,17 +49,22 @@ class PageUrl if (empty($parsedUrl['query'])) { if (empty($parsedUrl['fragment'])) { + return UrlHelper::getParseUrlReverse($parsedUrl); } + // Exclude from the hash tag as well $queryParameters = UrlHelper::getArrayFromQueryString($parsedUrl['fragment']); $parsedUrl['fragment'] = UrlHelper::getQueryStringWithExcludedParameters($queryParameters, $parametersToExclude); $url = UrlHelper::getParseUrlReverse($parsedUrl); + return $url; } + $queryParameters = UrlHelper::getArrayFromQueryString($parsedUrl['query']); $parsedUrl['query'] = UrlHelper::getQueryStringWithExcludedParameters($queryParameters, $parametersToExclude); $url = UrlHelper::getParseUrlReverse($parsedUrl); + return $url; } @@ -79,17 +84,15 @@ class PageUrl ); $website = Cache::getCacheWebsiteAttributes($idSite); - $excludedParameters = isset($website['excluded_parameters']) - ? $website['excluded_parameters'] - : array(); + $excludedParameters = self::getExcludedParametersFromWebsite($website); if (!empty($excludedParameters)) { Common::printDebug('Excluding parameters "' . implode(',', $excludedParameters) . '" from URL'); } $parametersToExclude = array_merge($excludedParameters, - self::$queryParametersToExclude, - $campaignTrackingParameters); + self::$queryParametersToExclude, + $campaignTrackingParameters); $parametersToExclude = array_map('strtolower', $parametersToExclude); return $parametersToExclude; @@ -152,6 +155,7 @@ class PageUrl if (empty($parsedUrl)) { return $parsedUrl; } + if (!empty($parsedUrl['host'])) { $parsedUrl['host'] = mb_strtolower($parsedUrl['host'], 'UTF-8'); } @@ -174,19 +178,24 @@ class PageUrl public static function convertMatrixUrl($originalUrl) { $posFirstSemiColon = strpos($originalUrl, ";"); - if ($posFirstSemiColon === false) { + + if (false === $posFirstSemiColon) { return $originalUrl; } + $posQuestionMark = strpos($originalUrl, "?"); - $replace = ($posQuestionMark === false); + $replace = (false === $posQuestionMark); + if ($posQuestionMark > $posFirstSemiColon) { $originalUrl = substr_replace($originalUrl, ";", $posQuestionMark, 1); $replace = true; } + if ($replace) { $originalUrl = substr_replace($originalUrl, "?", strpos($originalUrl, ";"), 1); $originalUrl = str_replace(";", "&", $originalUrl); } + return $originalUrl; } @@ -214,6 +223,7 @@ class PageUrl $value = urlencode(mb_convert_encoding($decoded, 'UTF-8', $encoding)); } } + return $value; } @@ -226,6 +236,7 @@ class PageUrl $value = PageUrl::reencodeParameterValue($value, $encoding); } } + return $queryParameters; } @@ -247,12 +258,13 @@ class PageUrl { // if query params are encoded w/ non-utf8 characters (due to browser bug or whatever), // encode to UTF-8. - if ($encoding !== false - && strtolower($encoding) != 'utf-8' + if (false !== $encoding + && 'utf-8' != strtolower($encoding) && function_exists('mb_check_encoding') ) { $queryParameters = PageUrl::reencodeParametersArray($queryParameters, $encoding); } + return $queryParameters; } @@ -261,6 +273,7 @@ class PageUrl $url = Common::unsanitizeInputValue($url); $url = PageUrl::cleanupString($url); $url = PageUrl::convertMatrixUrl($url); + return $url; } @@ -274,6 +287,7 @@ class PageUrl public static function reconstructNormalizedUrl($url, $prefixId) { $map = array_flip(self::$urlPrefixMap); + if ($prefixId !== null && isset($map[$prefixId])) { $fullUrl = $map[$prefixId] . $url; } else { @@ -283,7 +297,8 @@ class PageUrl // Clean up host & hash tags, for URLs $parsedUrl = @parse_url($fullUrl); $parsedUrl = PageUrl::cleanupHostAndHashTag($parsedUrl); - $url = UrlHelper::getParseUrlReverse($parsedUrl); + $url = UrlHelper::getParseUrlReverse($parsedUrl); + if (!empty($url)) { return $url; } @@ -302,12 +317,14 @@ class PageUrl { foreach (self::$urlPrefixMap as $prefix => $id) { if (strtolower(substr($url, 0, strlen($prefix))) == $prefix) { + return array( 'url' => substr($url, strlen($prefix)), 'prefixId' => $id ); } } + return array('url' => $url, 'prefixId' => null); } @@ -317,10 +334,20 @@ class PageUrl if (!UrlHelper::isLookLikeUrl($url)) { Common::printDebug("WARNING: URL looks invalid and is discarded"); - $url = false; - return $url; + + return false; } + return $url; } + + private static function getExcludedParametersFromWebsite($website) + { + if (isset($website['excluded_parameters'])) { + return $website['excluded_parameters']; + } + + return array(); + } } diff --git a/core/Tracker/Request.php b/core/Tracker/Request.php index b34ee88709..8ded0dc7a2 100644 --- a/core/Tracker/Request.php +++ b/core/Tracker/Request.php @@ -138,10 +138,12 @@ class Request if (!$this->isTimestampValid($cookieFirstVisitTimestamp)) { $cookieFirstVisitTimestamp = $this->getCurrentTimestamp(); } + $daysSinceFirstVisit = round(($this->getCurrentTimestamp() - $cookieFirstVisitTimestamp) / 86400, $precision = 0); if ($daysSinceFirstVisit < 0) { $daysSinceFirstVisit = 0; } + return $daysSinceFirstVisit; } @@ -152,12 +154,14 @@ class Request { $daysSinceLastOrder = false; $lastOrderTimestamp = $this->getParam('_ects'); + if ($this->isTimestampValid($lastOrderTimestamp)) { $daysSinceLastOrder = round(($this->getCurrentTimestamp() - $lastOrderTimestamp) / 86400, $precision = 0); if ($daysSinceLastOrder < 0) { $daysSinceLastOrder = 0; } } + return $daysSinceLastOrder; } @@ -168,12 +172,14 @@ class Request { $daysSinceLastVisit = 0; $lastVisitTimestamp = $this->getParam('_viewts'); + if ($this->isTimestampValid($lastVisitTimestamp)) { $daysSinceLastVisit = round(($this->getCurrentTimestamp() - $lastVisitTimestamp) / 86400, $precision = 0); if ($daysSinceLastVisit < 0) { $daysSinceLastVisit = 0; } } + return $daysSinceLastVisit; } @@ -297,6 +303,7 @@ class Request if (!isset($supportedParams[$name])) { throw new Exception("Requested parameter $name is not a known Tracking API Parameter."); } + $paramDefaultValue = $supportedParams[$name][0]; $paramType = $supportedParams[$name][1]; @@ -318,7 +325,7 @@ class Request protected function isTimestampValid($time) { return $time <= $this->getCurrentTimestamp() - && $time > $this->getCurrentTimestamp() - 10 * 365 * 86400; + && $time > $this->getCurrentTimestamp() - 10 * 365 * 86400; } public function getIdSite() @@ -338,9 +345,11 @@ class Request * request. */ Piwik::postEvent('Tracker.Request.getIdSite', array(&$idSite, $this->params)); + if ($idSite <= 0) { throw new Exception('Invalid idSite: \'' . $idSite . '\''); } + return $idSite; } @@ -359,9 +368,11 @@ class Request } $customVar = Common::unsanitizeInputValues(Common::getRequestVar($parameter, '', 'json', $this->params)); + if (!is_array($customVar)) { return array(); } + $customVariables = array(); $maxCustomVars = CustomVariables::getMaxCustomVariables(); foreach ($customVar as $id => $keyValue) { @@ -374,13 +385,14 @@ class Request Common::printDebug("Invalid custom variables detected (id=$id)"); continue; } + if (strlen($keyValue[1]) == 0) { $keyValue[1] = ""; } // We keep in the URL when Custom Variable have empty names // and values, as it means they can be deleted server side - $key = self::truncateCustomVariable($keyValue[0]); + $key = self::truncateCustomVariable($keyValue[0]); $value = self::truncateCustomVariable($keyValue[1]); $customVariables['custom_var_k' . $id] = $key; $customVariables['custom_var_v' . $id] = $value; @@ -407,6 +419,7 @@ class Request if (!$this->shouldUseThirdPartyCookie()) { return; } + Common::printDebug("We manage the cookie..."); $cookie = $this->makeThirdPartyCookie(); @@ -455,7 +468,7 @@ class Request // If User ID is set it takes precedence $userId = $this->getForcedUserId(); - if($userId) { + if ($userId) { $userIdHashed = $this->getUserIdHashed($userId); $idVisitor = $this->truncateIdAsVisitorId($userIdHashed); Common::printDebug("Request will be recorded for this user_id = " . $userId . " (idvisitor = $idVisitor)"); @@ -502,6 +515,7 @@ class Request return $binVisitorId; } } + return false; } @@ -512,6 +526,7 @@ class Request } else { $ipString = IP::getIpFromHeader(); } + $ip = IP::P2N($ipString); return $ip; } @@ -536,9 +551,11 @@ class Request public function getForcedUserId() { $userId = $this->getParam('uid'); - if(strlen($userId) > 0) { + + if (strlen($userId) > 0) { return $userId; } + return null; } @@ -572,6 +589,7 @@ class Request ) { return (int)$generationTime; } + return false; } diff --git a/core/Tracker/TableLogAction.php b/core/Tracker/TableLogAction.php index c547d742b8..7ae99a535e 100644 --- a/core/Tracker/TableLogAction.php +++ b/core/Tracker/TableLogAction.php @@ -36,17 +36,17 @@ class TableLogAction { // Add url prefix if not set foreach($actionsNameAndType as &$action) { - if(count($action) == 2) { + if (2 == count($action)) { $action[] = null; } } + $actionIds = self::queryIdsAction($actionsNameAndType); list($queriedIds, $fieldNamesToInsert) = self::processIdsToInsert($actionsNameAndType, $actionIds); $insertedIds = self::insertNewIdsAction($actionsNameAndType, $fieldNamesToInsert); - - $queriedIds = $queriedIds + $insertedIds; + $queriedIds = $queriedIds + $insertedIds; return $queriedIds; } @@ -58,9 +58,10 @@ class TableLogAction */ private static function getIdActionMatchingNameAndType($name, $type) { - $sql = TableLogAction::getSqlSelectActionId(); - $bind = array($name, $name, $type); + $sql = TableLogAction::getSqlSelectActionId(); + $bind = array($name, $name, $type); $idAction = \Piwik\Db::fetchOne($sql, $bind); + return $idAction; } @@ -75,6 +76,7 @@ class TableLogAction // now, we handle the cases =@ (contains) and !@ (does not contain) // build the expression based on the match type $sql = 'SELECT idaction FROM ' . Common::prefixTable('log_action') . ' WHERE %s AND type = ' . $actionType . ' )'; + switch ($matchType) { case '=@': // use concat to make sure, no %s occurs because some plugins use %s in their sql @@ -87,7 +89,9 @@ class TableLogAction throw new \Exception("This match type $matchType is not available for action-segments."); break; } + $sql = sprintf($sql, $where); + return $sql; } @@ -97,6 +101,7 @@ class TableLogAction FROM " . Common::prefixTable('log_action') . " WHERE " . " ( hash = CRC32(?) AND name = ? AND type = ? ) "; + return $sql; } @@ -106,6 +111,7 @@ class TableLogAction "( name, hash, type, url_prefix ) VALUES (?,CRC32(?),?,?)"; // Then, we insert all new actions in the lookup table $inserted = array(); + foreach ($fieldNamesToInsert as $fieldName) { list($name, $type, $urlPrefix) = $actionsNameAndType[$fieldName]; @@ -116,13 +122,15 @@ class TableLogAction Common::printDebug("Recorded a new action (" . Action::getTypeAsString($type) . ") in the lookup table: " . $name . " (idaction = " . $actionId . ")"); } + return $inserted; } private static function queryIdsAction($actionsNameAndType) { - $sql = TableLogAction::getSqlSelectActionId(); + $sql = TableLogAction::getSqlSelectActionId(); $bind = array(); + $i = 0; foreach ($actionsNameAndType as &$actionNameType) { list($name, $type, $urlPrefix) = $actionNameType; @@ -141,6 +149,7 @@ class TableLogAction if (empty($bind)) { return false; } + $actionIds = Tracker::getDatabase()->fetchAll($sql, $bind); return $actionIds; } @@ -150,6 +159,7 @@ class TableLogAction // For the Actions found in the lookup table, add the idaction in the array, // If not found in lookup table, queue for INSERT $fieldNamesToInsert = $fieldNameToActionId = array(); + foreach ($actionsNameAndType as $fieldName => &$actionNameType) { @list($name, $type, $urlPrefix) = $actionNameType; if (empty($name)) { @@ -172,6 +182,7 @@ class TableLogAction $fieldNamesToInsert[] = $fieldName; } } + return array($fieldNameToActionId, $fieldNamesToInsert); } @@ -197,6 +208,7 @@ class TableLogAction // for urls trim protocol and www because it is not recorded in the db $valueToMatch = preg_replace('@^http[s]?://(www\.)?@i', '', $valueToMatch); } + $valueToMatch = Common::sanitizeInputValue(Common::unsanitizeInputValue($valueToMatch)); if ($matchType == SegmentExpression::MATCH_EQUAL @@ -214,6 +226,7 @@ class TableLogAction // "name contains $string" match can match several idaction so we cannot return yet an idaction // special case $sql = TableLogAction::getSelectQueryWhereNameContains($matchType, $actionType); + return array( // mark that the returned value is an sql-expression instead of a literal value 'SQL' => $sql, @@ -229,15 +242,16 @@ class TableLogAction private static function guessActionTypeFromSegment($segmentName) { $exactMatch = array( - 'eventAction' => Action::TYPE_EVENT_ACTION, - 'eventCategory' => Action::TYPE_EVENT_CATEGORY, - 'eventName' => Action::TYPE_EVENT_NAME, - 'contentPiece' => Action::TYPE_CONTENT_PIECE, - 'contentTarget' => Action::TYPE_CONTENT_TARGET, - 'contentName' => Action::TYPE_CONTENT_NAME, + 'eventAction' => Action::TYPE_EVENT_ACTION, + 'eventCategory' => Action::TYPE_EVENT_CATEGORY, + 'eventName' => Action::TYPE_EVENT_NAME, + 'contentPiece' => Action::TYPE_CONTENT_PIECE, + 'contentTarget' => Action::TYPE_CONTENT_TARGET, + 'contentName' => Action::TYPE_CONTENT_NAME, 'contentInteraction' => Action::TYPE_CONTENT_INTERACTION, ); - if(!empty($exactMatch[$segmentName])) { + + if (!empty($exactMatch[$segmentName])) { return $exactMatch[$segmentName]; } diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php index 90b58a88b0..75633d95b6 100644 --- a/core/Tracker/Visit.php +++ b/core/Tracker/Visit.php @@ -109,8 +109,9 @@ class Visit implements VisitInterface $visitIsConverted = false; $action = null; - $requestIsManualGoalConversion = ($this->goalManager->idGoal > 0); + $isManualGoalConversion = $this->goalManager->isManualGoalConversion(); $requestIsEcommerce = $this->goalManager->requestIsEcommerce; + if ($requestIsEcommerce) { $someGoalsConverted = true; @@ -118,23 +119,26 @@ class Visit implements VisitInterface if ($this->goalManager->isGoalAnOrder()) { $visitIsConverted = true; } - } // this request is from the JS call to piwikTracker.trackGoal() - elseif ($requestIsManualGoalConversion) { + + } elseif ($isManualGoalConversion) { + // this request is from the JS call to piwikTracker.trackGoal() $someGoalsConverted = $this->goalManager->detectGoalId($this->request->getIdSite()); - $visitIsConverted = $someGoalsConverted; + $visitIsConverted = $someGoalsConverted; + // if we find a idgoal in the URL, but then the goal is not valid, this is most likely a fake request if (!$someGoalsConverted) { Common::printDebug('Invalid goal tracking request for goal id = ' . $this->goalManager->idGoal); return; } - } // normal page view, potentially triggering a URL matching goal - else { + + } else { + // normal page view, potentially triggering a URL matching goal $action = Action::factory($this->request); $action->writeDebugInfo(); $someGoalsConverted = $this->goalManager->detectGoalsMatchingUrl($this->request->getIdSite(), $action); - $visitIsConverted = $someGoalsConverted; + $visitIsConverted = $someGoalsConverted; $action->loadIdsFromLogActionTable(); } @@ -153,6 +157,7 @@ class Visit implements VisitInterface if (!$isLastActionInTheSameVisit) { Common::printDebug("Visitor detected, but last action was more than 30 minutes ago..."); } + // Known visit when: // ( - the visitor has the Piwik cookie with the idcookie ID used by Piwik to match the visitor // OR @@ -165,12 +170,15 @@ class Visit implements VisitInterface ) { $idReferrerActionUrl = $this->visitorInfo['visit_exit_idaction_url']; $idReferrerActionName = $this->visitorInfo['visit_exit_idaction_name']; + try { $this->goalManager->detectIsThereExistingCartInVisit($this->visitorInfo); $this->handleExistingVisit($visitor, $action, $visitIsConverted); + if (!is_null($action)) { $action->record($visitor, $idReferrerActionUrl, $idReferrerActionName); } + } catch (VisitorNotFoundInDb $e) { // There is an edge case when: @@ -179,7 +187,7 @@ class Visit implements VisitInterface // because the UPDATE didn't affect any rows (one row was found, but not updated since no field changed) // - the exception is caught here and will result in a new visit incorrectly // In this case, we cancel the current conversion to be recorded: - if ($requestIsManualGoalConversion + if ($isManualGoalConversion || $requestIsEcommerce ) { $someGoalsConverted = $visitIsConverted = false; @@ -239,8 +247,7 @@ class Visit implements VisitInterface // TODO we should not have to sync this->visitorInfo and $visitor columns. // TODO it should be its own dimension - $this->visitorInfo['time_spent_ref_action'] = $this->getTimeSpentReferrerAction(); - $visitor->setVisitorColumn('time_spent_ref_action', $this->visitorInfo['time_spent_ref_action']); + $this->setVisitorColumn($visitor, 'time_spent_ref_action', $this->getTimeSpentReferrerAction()); // update visitorInfo foreach ($valuesToUpdate as $name => $value) { @@ -262,8 +269,7 @@ class Visit implements VisitInterface $this->updateExistingVisit($valuesToUpdate); - $this->visitorInfo['visit_last_action_time'] = $this->request->getCurrentTimestamp(); - $visitor->setVisitorColumn('visit_last_action_time', $this->visitorInfo['visit_last_action_time']); + $this->setVisitorColumn($visitor, 'visit_last_action_time', $this->request->getCurrentTimestamp()); } /** @@ -275,8 +281,8 @@ class Visit implements VisitInterface if ($timeSpent < 0) { $timeSpent = 0; } - $visitStandardLength = Config::getInstance()->Tracker['visit_standard_length']; - if($timeSpent > $visitStandardLength) { + $visitStandardLength = $this->getVisitStandardLength(); + if ($timeSpent > $visitStandardLength) { $timeSpent = $visitStandardLength; } return $timeSpent; @@ -297,15 +303,7 @@ class Visit implements VisitInterface { Common::printDebug("New Visit (IP = " . IP::N2P($this->getVisitorIp()) . ")"); - $this->visitorInfo = $this->getNewVisitorInformation($visitor); - - // Add Custom variable key,value to the visitor array - $this->visitorInfo = array_merge($this->visitorInfo, $this->visitorCustomVariables); - - $visitor->clearVisitorInfo(); - foreach ($this->visitorInfo as $key => $value) { - $visitor->setVisitorColumn($key, $value); - } + $this->setNewVisitorInformation($visitor); $dimensions = $this->getAllVisitDimensions(); @@ -331,13 +329,9 @@ class Visit implements VisitInterface $idVisit = $this->insertNewVisit( $this->visitorInfo ); - $this->visitorInfo['idvisit'] = $idVisit; - $this->visitorInfo['visit_first_action_time'] = $this->request->getCurrentTimestamp(); - $this->visitorInfo['visit_last_action_time'] = $this->request->getCurrentTimestamp(); - - $visitor->setVisitorColumn('idvisit', $this->visitorInfo['idvisit']); - $visitor->setVisitorColumn('visit_first_action_time', $this->visitorInfo['visit_first_action_time']); - $visitor->setVisitorColumn('visit_last_action_time', $this->visitorInfo['visit_last_action_time']); + $this->setVisitorColumn($visitor, 'idvisit', $idVisit); + $this->setVisitorColumn($visitor, 'visit_first_action_time', $this->request->getCurrentTimestamp()); + $this->setVisitorColumn($visitor, 'visit_last_action_time', $this->request->getCurrentTimestamp()); } /** @@ -353,7 +347,7 @@ class Visit implements VisitInterface // If the visitor had a first party ID cookie, then we use this value if (!empty($this->visitorInfo['idvisitor']) - && strlen($this->visitorInfo['idvisitor']) == Tracker::LENGTH_BINARY_ID + && Tracker::LENGTH_BINARY_ID == strlen($this->visitorInfo['idvisitor']) ) { return $this->visitorInfo['idvisitor']; } @@ -366,8 +360,7 @@ class Visit implements VisitInterface */ public static function generateUniqueVisitorId() { - $uniqueId = substr(Common::generateUniqId(), 0, Tracker::LENGTH_HEX_ID_STRING); - return $uniqueId; + return substr(Common::generateUniqId(), 0, Tracker::LENGTH_HEX_ID_STRING); } /** @@ -387,9 +380,10 @@ class Visit implements VisitInterface */ protected function getSettingsObject() { - if(is_null($this->userSettings)) { + if (is_null($this->userSettings)) { $this->userSettings = new Settings( $this->request, $this->getVisitorIp() ); } + return $this->userSettings; } @@ -410,33 +404,42 @@ class Visit implements VisitInterface public static function isHostKnownAliasHost($urlHost, $idSite) { $websiteData = Cache::getCacheWebsiteAttributes($idSite); + if (isset($websiteData['hosts'])) { $canonicalHosts = array(); foreach ($websiteData['hosts'] as $host) { - $canonicalHosts[] = str_replace('www.', '', mb_strtolower($host, 'UTF-8')); + $canonicalHosts[] = self::toCanonicalHost($host); } - $canonicalHost = str_replace('www.', '', mb_strtolower($urlHost, 'UTF-8')); + + $canonicalHost = self::toCanonicalHost($urlHost); if (in_array($canonicalHost, $canonicalHosts)) { return true; } } + return false; } + private static function toCanonicalHost($host) + { + $hostLower = mb_strtolower($host, 'UTF-8'); + return str_replace('www.', '', $hostLower); + } + /** * @return mixed */ protected function insertNewVisit($visit) { - $fields = implode(", ", array_keys($visit)); + $fields = array_keys($visit); + $fields = implode(", ", $fields); $values = Common::getSqlStringFieldsArray($visit); - $sql = "INSERT INTO " . Common::prefixTable('log_visit') . " ($fields) VALUES ($values)"; + $sql = "INSERT INTO " . Common::prefixTable('log_visit') . " ($fields) VALUES ($values)"; $bind = array_values($visit); Tracker::getDatabase()->query($sql, $bind); - $idVisit = Tracker::getDatabase()->lastInsertId(); - return $idVisit; + return Tracker::getDatabase()->lastInsertId(); } /** @@ -445,25 +448,7 @@ class Visit implements VisitInterface */ protected function updateExistingVisit($valuesToUpdate) { - $sqlQuery = "UPDATE " . Common::prefixTable('log_visit') . " - SET %s - WHERE idsite = ? - AND idvisit = ?"; - // build sql query - $updateParts = $sqlBind = array(); - foreach ($valuesToUpdate as $name => $value) { - // Case where bind parameters don't work - if(strpos($value, $name) !== false) { - //$name = 'visit_total_events' - //$value = 'visit_total_events + 1'; - $updateParts[] = " $name = $value "; - } else { - $updateParts[] = $name . " = ?"; - $sqlBind[] = $value; - } - } - $sqlQuery = sprintf($sqlQuery, implode($updateParts, ', ') ); - array_push($sqlBind, $this->request->getIdSite(), (int)$this->visitorInfo['idvisit']); + list($sqlQuery, $sqlBind) = $this->getUpdateExistingVisitQuery($valuesToUpdate); $result = Tracker::getDatabase()->query($sqlQuery, $sqlBind); @@ -471,6 +456,7 @@ class Visit implements VisitInterface if (isset($valuesToUpdate['idvisitor'])) { $valuesToUpdate['idvisitor'] = bin2hex($valuesToUpdate['idvisitor']); } + Common::printDebug('Updating existing visit: ' . var_export($valuesToUpdate, true)); if (Tracker::getDatabase()->rowCount($result) == 0) { @@ -483,7 +469,13 @@ class Visit implements VisitInterface } } - protected function printVisitorInformation() + private function setVisitorColumn(Visitor $visitor, $key, $value) + { + $this->visitorInfo[$key] = $value; + $visitor->setVisitorColumn($key, $value); + } + + private function printVisitorInformation() { $debugVisitInfo = $this->visitorInfo; $debugVisitInfo['idvisitor'] = bin2hex($debugVisitInfo['idvisitor']); @@ -491,13 +483,22 @@ class Visit implements VisitInterface Common::printDebug($debugVisitInfo); } - protected function getNewVisitorInformation($visitor) + private function setNewVisitorInformation(Visitor $visitor) { - return array( - 'idvisitor' => $this->getVisitorIdcookie($visitor), - 'config_id' => $this->getSettingsObject()->getConfigId(), - 'location_ip' => $this->getVisitorIp(), - ); + $idVisitor = $this->getVisitorIdcookie($visitor); + $visitorIp = $this->getVisitorIp(); + $configId = $this->getSettingsObject()->getConfigId(); + + $this->visitorInfo = array(); + $visitor->clearVisitorInfo(); + + $this->setVisitorColumn($visitor, 'idvisitor', $idVisitor); + $this->setVisitorColumn($visitor, 'config_id', $configId); + $this->setVisitorColumn($visitor, 'location_ip', $visitorIp); + + foreach ($this->visitorCustomVariables as $key => $value) { + $this->setVisitorColumn($visitor, $key, $value); + } } /** @@ -508,7 +509,7 @@ class Visit implements VisitInterface * @param $visitIsConverted * @return array */ - protected function getExistingVisitFieldsToUpdate($visitor, $action, $visitIsConverted) + private function getExistingVisitFieldsToUpdate($visitor, $action, $visitIsConverted) { $valuesToUpdate = array(); @@ -526,8 +527,7 @@ class Visit implements VisitInterface } // Custom Variables overwrite previous values on each page view - $valuesToUpdate = array_merge($valuesToUpdate, $this->visitorCustomVariables); - return $valuesToUpdate; + return array_merge($valuesToUpdate, $this->visitorCustomVariables); } /** @@ -567,7 +567,50 @@ class Visit implements VisitInterface foreach($dimensions as $dimension) { $dimensionNames[] = $dimension->getColumnName(); } + Common::printDebug("Following dimensions have been collected from plugins: " . implode(", ", $dimensionNames)); + return $dimensions; } + + private function fieldsToQuery($valuesToUpdate) + { + $updateParts = array(); + $sqlBind = array(); + + foreach ($valuesToUpdate as $name => $value) { + // Case where bind parameters don't work + if ($value === $name . ' + 1') { + //$name = 'visit_total_events' + //$value = 'visit_total_events + 1'; + $updateParts[] = " $name = $value "; + } else { + $updateParts[] = $name . " = ?"; + $sqlBind[] = $value; + } + } + + return array($updateParts, $sqlBind); + } + + private function getUpdateExistingVisitQuery($valuesToUpdate) + { + $sqlQuery = "UPDATE " . Common::prefixTable('log_visit') . " SET %s WHERE idsite = ? AND idvisit = ?"; + + // build sql query + list($updateParts, $sqlBind) = $this->fieldsToQuery($valuesToUpdate); + + $idSite = $this->request->getIdSite(); + $idVisit = (int) $this->visitorInfo['idvisit']; + + $sqlQuery = sprintf($sqlQuery, implode($updateParts, ', ')); + array_push($sqlBind, $idSite, $idVisit); + + return array($sqlQuery, $sqlBind); + } + + private function getVisitStandardLength() + { + return Config::getInstance()->Tracker['visit_standard_length']; + } } diff --git a/core/Tracker/VisitExcluded.php b/core/Tracker/VisitExcluded.php index 586c874a0c..48eb1e3db7 100644 --- a/core/Tracker/VisitExcluded.php +++ b/core/Tracker/VisitExcluded.php @@ -8,7 +8,6 @@ */ namespace Piwik\Tracker; -use DeviceDetector\Parser\Bot; use Piwik\Common; use Piwik\Config; use Piwik\DeviceDetectorFactory; @@ -27,16 +26,16 @@ class VisitExcluded */ public function __construct(Request $request, $ip = false, $userAgent = false) { - if ($ip === false) { + if (false === $ip) { $ip = $request->getIp(); } - if ($userAgent === false) { + if (false === $userAgent) { $userAgent = $request->getUserAgent(); } - $this->request = $request; - $this->idSite = $request->getIdSite(); + $this->request = $request; + $this->idSite = $request->getIdSite(); $this->userAgent = $userAgent; $this->ip = $ip; } @@ -200,6 +199,7 @@ class VisitExcluded Common::printDebug('Piwik ignore cookie was found, visit not tracked.'); return true; } + return false; } @@ -211,12 +211,14 @@ class VisitExcluded protected function isVisitorIpExcluded() { $websiteAttributes = Cache::getCacheWebsiteAttributes($this->idSite); + if (!empty($websiteAttributes['excluded_ips'])) { if (IP::isIpInRange($this->ip, $websiteAttributes['excluded_ips'])) { Common::printDebug('Visitor IP ' . IP::N2P($this->ip) . ' is excluded from being tracked'); return true; } } + return false; } @@ -232,6 +234,7 @@ class VisitExcluded protected function isUserAgentExcluded() { $websiteAttributes = Cache::getCacheWebsiteAttributes($this->idSite); + if (!empty($websiteAttributes['excluded_user_agents'])) { foreach ($websiteAttributes['excluded_user_agents'] as $excludedUserAgent) { // if the excluded user agent string part is in this visit's user agent, this visit should be excluded @@ -240,6 +243,7 @@ class VisitExcluded } } } + return false; } @@ -254,12 +258,14 @@ class VisitExcluded $spamHosts = explode(",", $spamHosts); $referrerUrl = $this->request->getParam('urlref'); + foreach($spamHosts as $spamHost) { - if( strpos($referrerUrl, $spamHost) !== false) { + if ( strpos($referrerUrl, $spamHost) !== false) { Common::printDebug('Referrer URL is a known spam: ' . $spamHost); return true; } } + return false; } } diff --git a/core/Tracker/Visitor.php b/core/Tracker/Visitor.php index b412078151..a73361e014 100644 --- a/core/Tracker/Visitor.php +++ b/core/Tracker/Visitor.php @@ -209,16 +209,16 @@ class Visitor */ protected function getWindowLookupThisVisit() { - $visitStandardLength = Config::getInstance()->Tracker['visit_standard_length']; + $visitStandardLength = Config::getInstance()->Tracker['visit_standard_length']; $lookBackNSecondsCustom = Config::getInstance()->Tracker['window_look_back_for_visitor']; $lookAheadNSeconds = $visitStandardLength; - $lookBackNSeconds = $visitStandardLength; + $lookBackNSeconds = $visitStandardLength; if ($lookBackNSecondsCustom > $lookBackNSeconds) { $lookBackNSeconds = $lookBackNSecondsCustom; } - $timeLookBack = date('Y-m-d H:i:s', $this->request->getCurrentTimestamp() - $lookBackNSeconds); + $timeLookBack = date('Y-m-d H:i:s', $this->request->getCurrentTimestamp() - $lookBackNSeconds); $timeLookAhead = date('Y-m-d H:i:s', $this->request->getCurrentTimestamp() + $lookAheadNSeconds); return array($timeLookBack, $timeLookAhead); @@ -240,6 +240,7 @@ class Visitor || $isForcedVisitorIdMustMatch || $isForcedUserIdMustMatch || !$isVisitorIdToLookup); + return $shouldMatchOneFieldOnly; } diff --git a/core/Translate.php b/core/Translate.php index 34bd35ba12..65381c0a2d 100644 --- a/core/Translate.php +++ b/core/Translate.php @@ -68,7 +68,7 @@ class Translate private static function loadCoreTranslationFile($language) { - if(empty($language)) { + if (empty($language)) { return; } $path = PIWIK_INCLUDE_PATH . '/lang/' . $language . '.json'; @@ -174,7 +174,7 @@ class Translate } $js = 'var translations = ' . Common::json_encode($clientSideTranslations) . ';'; - $js .= "\n" . 'if(typeof(piwik_translations) == \'undefined\') { var piwik_translations = new Object; }' . + $js .= "\n" . 'if (typeof(piwik_translations) == \'undefined\') { var piwik_translations = new Object; }' . 'for(var i in translations) { piwik_translations[i] = translations[i];} '; return $js; } diff --git a/core/Translate/Validate/NoScripts.php b/core/Translate/Validate/NoScripts.php index 0ee0fc9a57..e7f032ff55 100644 --- a/core/Translate/Validate/NoScripts.php +++ b/core/Translate/Validate/NoScripts.php @@ -28,12 +28,14 @@ class NoScripts extends ValidateAbstract // check if any translation contains restricted script tags $serializedStrings = serialize($translations); $invalids = array("<script", 'document.', 'javascript:', 'src=', 'background=', 'onload='); + foreach ($invalids as $invalid) { if (stripos($serializedStrings, $invalid) !== false) { $this->message = 'script tags restricted for language files'; return false; } } + return true; } } diff --git a/core/Translate/Writer.php b/core/Translate/Writer.php index 617b8b9552..c43beca189 100644 --- a/core/Translate/Writer.php +++ b/core/Translate/Writer.php @@ -71,7 +71,7 @@ class Writer protected $filterMessages = array(); const UNFILTERED = 'unfiltered'; - const FILTERED = 'filtered'; + const FILTERED = 'filtered'; protected $currentState = self::UNFILTERED; @@ -152,12 +152,14 @@ class Writer public function getTranslations($lang) { $path = $this->getTranslationPathBaseDirectory('lang', $lang); + if (!is_readable($path)) { return array(); } $data = file_get_contents($path); $translations = json_decode($data, true); + return $translations; } diff --git a/core/Twig.php b/core/Twig.php index b0707350c4..2e0ef95844 100755 --- a/core/Twig.php +++ b/core/Twig.php @@ -46,7 +46,7 @@ class Twig $loaders = array(); //create loader for custom theme to overwrite twig templates - if($theme && $theme->getPluginName() != \Piwik\Plugin\Manager::DEFAULT_THEME) { + if ($theme && $theme->getPluginName() != \Piwik\Plugin\Manager::DEFAULT_THEME) { $customLoader = $this->getCustomThemeLoader($theme); if ($customLoader) { //make it possible to overwrite plugin templates @@ -187,7 +187,7 @@ class Twig * @return \Twig_Loader_Filesystem */ protected function getCustomThemeLoader(Plugin $theme){ - if(!file_exists(sprintf("%s/plugins/%s/templates/", PIWIK_INCLUDE_PATH, $theme->getPluginName()))){ + if (!file_exists(sprintf("%s/plugins/%s/templates/", PIWIK_INCLUDE_PATH, $theme->getPluginName()))){ return false; } $themeLoader = new Twig_Loader_Filesystem(array( diff --git a/core/Unzip/Gzip.php b/core/Unzip/Gzip.php index 16f08abf0a..7e572e35ea 100755 --- a/core/Unzip/Gzip.php +++ b/core/Unzip/Gzip.php @@ -48,6 +48,7 @@ class Gzip implements UncompressInterface public function extract($pathExtracted) { $file = gzopen($this->filename, 'r'); + if ($file === false) { $this->error = "gzopen failed"; return false; @@ -60,7 +61,7 @@ class Gzip implements UncompressInterface fclose($output); $success = gzclose($file); - if ($success === false) { + if (false === $success) { $this->error = "gzclose failed"; return false; } diff --git a/core/Unzip/PclZip.php b/core/Unzip/PclZip.php index b0ce4b3a75..ff03aac3d9 100644 --- a/core/Unzip/PclZip.php +++ b/core/Unzip/PclZip.php @@ -35,7 +35,7 @@ class PclZip implements UncompressInterface */ public function __construct($filename) { - $this->pclzip = new \PclZip($filename); + $this->pclzip = new \PclZip($filename); $this->filename = $filename; } @@ -55,7 +55,7 @@ class PclZip implements UncompressInterface foreach ($list as $entry) { $filename = str_replace('\\', '/', $entry['stored_filename']); - $parts = explode('/', $filename); + $parts = explode('/', $filename); if (!strncmp($filename, '/', 1) || array_search('..', $parts) !== false || diff --git a/core/Unzip/ZipArchive.php b/core/Unzip/ZipArchive.php index c8d7edd874..e68e168c0c 100644 --- a/core/Unzip/ZipArchive.php +++ b/core/Unzip/ZipArchive.php @@ -53,8 +53,9 @@ class ZipArchive implements UncompressInterface } $fileselector = array(); - $list = array(); + $list = array(); $count = $this->ziparchive->numFiles; + if ($count === 0) { return 0; } @@ -63,7 +64,7 @@ class ZipArchive implements UncompressInterface $entry = $this->ziparchive->statIndex($i); $filename = str_replace('\\', '/', $entry['name']); - $parts = explode('/', $filename); + $parts = explode('/', $filename); if (!strncmp($filename, '/', 1) || array_search('..', $parts) !== false || @@ -71,6 +72,7 @@ class ZipArchive implements UncompressInterface ) { return 0; } + $fileselector[] = $entry['name']; $list[] = array( 'filename' => $pathExtracted . $entry['name'], @@ -84,8 +86,10 @@ class ZipArchive implements UncompressInterface } $res = $this->ziparchive->extractTo($pathExtracted, $fileselector); - if ($res === false) + if ($res === false) { return 0; + } + return $list; } @@ -128,6 +132,7 @@ class ZipArchive implements UncompressInterface } else { $statusString = 'Unknown status'; } + return $statusString . '(' . $this->ziparchive->status . ')'; } } diff --git a/core/UpdateCheck.php b/core/UpdateCheck.php index 228ac23a85..43639da9dc 100644 --- a/core/UpdateCheck.php +++ b/core/UpdateCheck.php @@ -36,7 +36,7 @@ class UpdateCheck */ public static function check($force = false, $interval = null) { - if(!self::isAutoUpdateEnabled()) { + if (!self::isAutoUpdateEnabled()) { return; } diff --git a/core/Updater.php b/core/Updater.php index 1527da723a..0069d1b71b 100644 --- a/core/Updater.php +++ b/core/Updater.php @@ -355,6 +355,7 @@ class Updater * @param string $updateSql Update SQL query. * @param int|false $errorToIgnore A MySQL error code to ignore. * @param string $file The Update file that's calling this method. + * @throws UpdaterErrorException */ public static function handleQueryError($e, $updateSql, $errorToIgnore, $file) { @@ -371,6 +372,7 @@ class Updater * * @param int $error * @param int|int[] $errorCodesToIgnore + * @return boolean */ public static function isDbErrorOneOf($error, $errorCodesToIgnore) { diff --git a/core/Updates/2.0-a17.php b/core/Updates/2.0-a17.php index 2df452c1ab..5d65143596 100644 --- a/core/Updates/2.0-a17.php +++ b/core/Updates/2.0-a17.php @@ -35,7 +35,7 @@ class Updates_2_0_a17 extends Updates } } - if(!empty($errors)) { + if (!empty($errors)) { throw new \Exception("Warnings during the update: <br>" . implode("<br>", $errors)); } } diff --git a/core/Updates/2.0-b13.php b/core/Updates/2.0-b13.php index 78cc791566..a5e9546b90 100644 --- a/core/Updates/2.0-b13.php +++ b/core/Updates/2.0-b13.php @@ -35,7 +35,7 @@ class Updates_2_0_b13 extends Updates } } - if(!empty($errors)) { + if (!empty($errors)) { throw new \Exception("Warnings during the update: <br>" . implode("<br>", $errors)); } } diff --git a/core/Updates/2.0.3-b7.php b/core/Updates/2.0.3-b7.php index f3fa6a34aa..add119e462 100644 --- a/core/Updates/2.0.3-b7.php +++ b/core/Updates/2.0.3-b7.php @@ -56,7 +56,7 @@ class Updates_2_0_3_b7 extends Updates } } - if(!empty($errors)) { + if (!empty($errors)) { throw new \Exception("Warnings during the update: <br>" . implode("<br>", $errors)); } } diff --git a/core/Updates/2.1.1-b11.php b/core/Updates/2.1.1-b11.php index 45b781a1cf..3fa0364e73 100644 --- a/core/Updates/2.1.1-b11.php +++ b/core/Updates/2.1.1-b11.php @@ -41,17 +41,14 @@ class Updates_2_1_1_b11 extends Updates // returning visit segment foreach ($archiveNumericTables as $table) { // get archives w/ *._returning - $sql = "SELECT idarchive, idsite, period, date1, date2 - FROM $table - WHERE name IN ('" . implode("','", $returningMetrics) . "') - GROUP BY idarchive"; + $sql = "SELECT idarchive, idsite, period, date1, date2 FROM $table + WHERE name IN ('" . implode("','", $returningMetrics) . "') + GROUP BY idarchive"; $idArchivesWithReturning = Db::fetchAll($sql); // get archives for visitssummary returning visitor segment - $sql = "SELECT idarchive, idsite, period, date1, date2 - FROM $table - WHERE name = ? - GROUP BY idarchive"; + $sql = "SELECT idarchive, idsite, period, date1, date2 FROM $table + WHERE name = ? GROUP BY idarchive"; $visitSummaryReturningSegmentDone = Rules::getDoneFlagArchiveContainsOnePlugin( new Segment(VisitFrequencyApi::RETURNING_VISITOR_SEGMENT, $idSites = array()), 'VisitsSummary'); $idArchivesWithVisitReturningSegment = Db::fetchAll($sql, array($visitSummaryReturningSegmentDone)); diff --git a/core/Updates/2.4.0-b1.php b/core/Updates/2.4.0-b1.php index a0f6d64f65..cc0d615d54 100644 --- a/core/Updates/2.4.0-b1.php +++ b/core/Updates/2.4.0-b1.php @@ -8,9 +8,6 @@ */ namespace Piwik\Updates; -use Faker\Provider\File; -use Piwik\Filesystem; -use Piwik\Plugins\Installation\ServerFilesGenerator; use Piwik\Updates; class Updates_2_4_0_b1 extends Updates diff --git a/core/Url.php b/core/Url.php index 32ea140f20..75b0731e78 100644 --- a/core/Url.php +++ b/core/Url.php @@ -10,12 +10,7 @@ namespace Piwik; use Exception; -use Piwik\Config; -use Piwik\Common; -use Piwik\IP; -use Piwik\ProxyHttp; use Piwik\Session; -use Piwik\UrlHelper; /** * Provides URL related helper methods. @@ -346,7 +341,7 @@ class Url $hostHeaders = array(); $config = Config::getInstance()->General; - if(isset($config['proxy_host_headers'])) { + if (isset($config['proxy_host_headers'])) { $hostHeaders = $config['proxy_host_headers']; } @@ -473,6 +468,7 @@ class Url * Redirects the user to the specified URL. * * @param string $url + * @throws Exception * @api */ public static function redirectToUrl($url) @@ -490,7 +486,7 @@ class Url echo "Invalid URL to redirect to."; } - if(Common::isPhpCliMode()) { + if (Common::isPhpCliMode()) { throw new Exception("If you were using a browser, Piwik would redirect you to this URL: $url \n\n"); } exit; @@ -501,7 +497,7 @@ class Url */ public static function redirectToHttps() { - if(ProxyHttp::isHttps()) { + if (ProxyHttp::isHttps()) { return; } $url = self::getCurrentUrl(); diff --git a/core/View.php b/core/View.php index bc02e4c792..6200a23113 100644 --- a/core/View.php +++ b/core/View.php @@ -9,12 +9,8 @@ namespace Piwik; use Exception; -use Piwik\Access; use Piwik\AssetManager\UIAssetCacheBuster; -use Piwik\Common; use Piwik\Plugins\UsersManager\API as APIUsersManager; -use Piwik\SettingsPiwik; -use Piwik\Version; use Piwik\View\ViewInterface; use Twig_Environment; diff --git a/core/View/ReportsByDimension.php b/core/View/ReportsByDimension.php index e1cb058459..dbb59be930 100644 --- a/core/View/ReportsByDimension.php +++ b/core/View/ReportsByDimension.php @@ -104,10 +104,10 @@ class ReportsByDimension extends View // display it initially $categories = $this->dimensionCategories; if (!empty($categories)) { - $firstCategory = reset($categories); + $firstCategory = reset($categories); $firstReportInfo = reset($firstCategory); - $oldGet = $_GET; + $oldGet = $_GET; $oldPost = $_POST; foreach ($firstReportInfo['params'] as $key => $value) { @@ -120,7 +120,7 @@ class ReportsByDimension extends View $action = $firstReportInfo['params']['action']; $this->firstReport = FrontController::getInstance()->fetchDispatch($module, $action); - $_GET = $oldGet; + $_GET = $oldGet; $_POST = $oldPost; } diff --git a/core/ViewDataTable/Config.php b/core/ViewDataTable/Config.php index 2bd748d3e4..1706e4b15f 100644 --- a/core/ViewDataTable/Config.php +++ b/core/ViewDataTable/Config.php @@ -598,7 +598,7 @@ class Config // don't add the related report if it references this report if ($this->controllerName == $module && $this->controllerAction == $action) { - if(empty($queryParams)) { + if (empty($queryParams)) { return; } } diff --git a/core/ViewDataTable/Manager.php b/core/ViewDataTable/Manager.php index 19e2335ce1..5d05650657 100644 --- a/core/ViewDataTable/Manager.php +++ b/core/ViewDataTable/Manager.php @@ -156,46 +156,7 @@ class Manager { $result = array(); - // add normal view icons (eg, normal table, all columns, goals) - $normalViewIcons = array( - 'class' => 'tableAllColumnsSwitch', - 'buttons' => array(), - ); - - if ($view->config->show_table) { - $normalViewIcons['buttons'][] = static::getFooterIconFor(HtmlTable::ID); - } - - if ($view->config->show_table_all_columns) { - $normalViewIcons['buttons'][] = static::getFooterIconFor(HtmlTable\AllColumns::ID); - } - - if ($view->config->show_goals) { - $goalButton = static::getFooterIconFor(Goals::ID); - if (Common::getRequestVar('idGoal', false) == 'ecommerceOrder') { - $goalButton['icon'] = 'plugins/Morpheus/images/ecommerceOrder.gif'; - } - - $normalViewIcons['buttons'][] = $goalButton; - } - - if ($view->config->show_ecommerce) { - $normalViewIcons['buttons'][] = array( - 'id' => 'ecommerceOrder', - 'title' => Piwik::translate('General_EcommerceOrders'), - 'icon' => 'plugins/Morpheus/images/ecommerceOrder.gif', - 'text' => Piwik::translate('General_EcommerceOrders') - ); - - $normalViewIcons['buttons'][] = array( - 'id' => 'ecommerceAbandonedCart', - 'title' => Piwik::translate('General_AbandonedCarts'), - 'icon' => 'plugins/Morpheus/images/ecommerceAbandonedCart.gif', - 'text' => Piwik::translate('General_AbandonedCarts') - ); - } - - $normalViewIcons['buttons'] = array_filter($normalViewIcons['buttons']); + $normalViewIcons = self::getNormalViewIcons($view); if (!empty($normalViewIcons['buttons'])) { $result[] = $normalViewIcons; @@ -207,25 +168,7 @@ class Manager 'buttons' => array(), ); - // add graph views - $graphViewIcons = array( - 'class' => 'tableGraphViews tableGraphCollapsed', - 'buttons' => array(), - ); - - if ($view->config->show_all_views_icons) { - if ($view->config->show_bar_chart) { - $graphViewIcons['buttons'][] = static::getFooterIconFor(Bar::ID); - } - - if ($view->config->show_pie_chart) { - $graphViewIcons['buttons'][] = static::getFooterIconFor(Pie::ID); - } - - if ($view->config->show_tag_cloud) { - $graphViewIcons['buttons'][] = static::getFooterIconFor(Cloud::ID); - } - } + $graphViewIcons = self::getGraphViewIcons($view); $nonCoreVisualizations = static::getNonCoreViewDataTables(); @@ -331,4 +274,75 @@ class Manager { return sprintf('viewDataTableParameters_%s_%s', $login, $controllerAction); } + + private static function getNormalViewIcons(ViewDataTable $view) + { + // add normal view icons (eg, normal table, all columns, goals) + $normalViewIcons = array( + 'class' => 'tableAllColumnsSwitch', + 'buttons' => array(), + ); + + if ($view->config->show_table) { + $normalViewIcons['buttons'][] = static::getFooterIconFor(HtmlTable::ID); + } + + if ($view->config->show_table_all_columns) { + $normalViewIcons['buttons'][] = static::getFooterIconFor(HtmlTable\AllColumns::ID); + } + + if ($view->config->show_goals) { + $goalButton = static::getFooterIconFor(Goals::ID); + if (Common::getRequestVar('idGoal', false) == 'ecommerceOrder') { + $goalButton['icon'] = 'plugins/Morpheus/images/ecommerceOrder.gif'; + } + + $normalViewIcons['buttons'][] = $goalButton; + } + + if ($view->config->show_ecommerce) { + $normalViewIcons['buttons'][] = array( + 'id' => 'ecommerceOrder', + 'title' => Piwik::translate('General_EcommerceOrders'), + 'icon' => 'plugins/Morpheus/images/ecommerceOrder.gif', + 'text' => Piwik::translate('General_EcommerceOrders') + ); + + $normalViewIcons['buttons'][] = array( + 'id' => 'ecommerceAbandonedCart', + 'title' => Piwik::translate('General_AbandonedCarts'), + 'icon' => 'plugins/Morpheus/images/ecommerceAbandonedCart.gif', + 'text' => Piwik::translate('General_AbandonedCarts') + ); + } + + $normalViewIcons['buttons'] = array_filter($normalViewIcons['buttons']); + + return $normalViewIcons; + } + + private static function getGraphViewIcons(ViewDataTable $view) + { + // add graph views + $graphViewIcons = array( + 'class' => 'tableGraphViews tableGraphCollapsed', + 'buttons' => array(), + ); + + if ($view->config->show_all_views_icons) { + if ($view->config->show_bar_chart) { + $graphViewIcons['buttons'][] = static::getFooterIconFor(Bar::ID); + } + + if ($view->config->show_pie_chart) { + $graphViewIcons['buttons'][] = static::getFooterIconFor(Pie::ID); + } + + if ($view->config->show_tag_cloud) { + $graphViewIcons['buttons'][] = static::getFooterIconFor(Cloud::ID); + } + } + + return $graphViewIcons; + } } diff --git a/core/ViewDataTable/Request.php b/core/ViewDataTable/Request.php index 9493889944..352ce25899 100644 --- a/core/ViewDataTable/Request.php +++ b/core/ViewDataTable/Request.php @@ -119,8 +119,8 @@ class Request if (isset($_GET[$nameVar])) { return Common::sanitizeInputValue($_GET[$nameVar]); } - $default = $this->getDefault($nameVar); - return $default; + + return $this->getDefault($nameVar); } /** diff --git a/core/Visualization/Sparkline.php b/core/Visualization/Sparkline.php index 8a7b406342..642c1325cb 100644 --- a/core/Visualization/Sparkline.php +++ b/core/Visualization/Sparkline.php @@ -32,6 +32,7 @@ class Sparkline implements ViewInterface public static $enableSparklineImages = true; private static $colorNames = array('backgroundColor', 'lineColor', 'minPointColor', 'lastPointColor', 'maxPointColor'); + private $values = array(); /** * Width of the sparkline @@ -60,7 +61,6 @@ class Sparkline implements ViewInterface */ public function setHeight($height) { - if (!is_numeric($height) || $height <= 0) { return; } @@ -74,7 +74,6 @@ class Sparkline implements ViewInterface */ public function setWidth($width) { - if (!is_numeric($width) || $width <= 0) { return; } @@ -110,7 +109,9 @@ class Sparkline implements ViewInterface $min = $max = $last = null; $i = 0; - $toRemove = array('%', str_replace('%s', '', Piwik::translate('General_Seconds'))); + $seconds = Piwik::translate('General_Seconds'); + $toRemove = array('%', str_replace('%s', '', $seconds)); + foreach ($this->values as $value) { // 50% and 50s should be plotted as 50 $value = str_replace($toRemove, '', $value); @@ -158,6 +159,7 @@ class Sparkline implements ViewInterface private function setSparklineColors($sparkline) { $colors = Common::getRequestVar('colors', false, 'json'); + if (empty($colors)) { // quick fix so row evolution sparklines will have color in widgetize's iframes $colors = array( 'backgroundColor' => '#ffffff', diff --git a/core/dispatch.php b/core/dispatch.php index f18b73f0bd..133f26f355 100644 --- a/core/dispatch.php +++ b/core/dispatch.php @@ -24,7 +24,7 @@ if (!defined('PIWIK_ENABLE_ERROR_HANDLER') || PIWIK_ENABLE_ERROR_HANDLER) { FrontController::setUpSafeMode(); -if(!defined('PIWIK_ENABLE_DISPATCH')) { +if (!defined('PIWIK_ENABLE_DISPATCH')) { define('PIWIK_ENABLE_DISPATCH', true); } @@ -33,7 +33,7 @@ if (PIWIK_ENABLE_DISPATCH) { $controller->init(); $response = $controller->dispatch(); - if(is_array($response)) { + if (is_array($response)) { var_export($response); } elseif (!is_null($response)) { echo $response; diff --git a/core/testMinimumPhpVersion.php b/core/testMinimumPhpVersion.php index bce404c9e6..3dd3defd3e 100644 --- a/core/testMinimumPhpVersion.php +++ b/core/testMinimumPhpVersion.php @@ -129,7 +129,7 @@ if (!function_exists('Piwik_ExitWithMessage')) { $message = str_replace("\t", "", $message); $message = strip_tags($message); - if($isCli) { + if ($isCli) { echo $message; } else { echo $headerPage . $content . $footerPage; diff --git a/plugins/API/API.php b/plugins/API/API.php index 00758ca6bb..c65c04fffe 100644 --- a/plugins/API/API.php +++ b/plugins/API/API.php @@ -259,7 +259,7 @@ class API extends \Piwik\Plugin\API SegmentExpression::MATCH_IS_NULL_OR_EMPTY, SegmentExpression::MATCH_NOT_EQUAL, ); - if(in_array($matchType, $acceptedMatches)) { + if (in_array($matchType, $acceptedMatches)) { return $value; } $message = "Invalid Segment match type: try using 'userId' segment with one of the following match types: %s."; @@ -524,7 +524,7 @@ class API extends \Piwik\Plugin\API */ public function getSuggestedValuesForSegment($segmentName, $idSite) { - if(empty(Config::getInstance()->General['enable_segment_suggested_values'])) { + if (empty(Config::getInstance()->General['enable_segment_suggested_values'])) { return array(); } Piwik::checkUserHasViewAccess($idSite); @@ -549,7 +549,7 @@ class API extends \Piwik\Plugin\API } // if period=range is disabled, do not proceed - if(!Period\Factory::isPeriodEnabledForAPI('range')) { + if (!Period\Factory::isPeriodEnabledForAPI('range')) { return array(); } diff --git a/plugins/API/Controller.php b/plugins/API/Controller.php index 9a6b3fc5e7..18e39d58a2 100644 --- a/plugins/API/Controller.php +++ b/plugins/API/Controller.php @@ -60,7 +60,7 @@ class Controller extends \Piwik\Plugin\Controller foreach ($segments as $segment) { // Eg. Event Value is a metric, not in the Visit metric category, // we make sure it is displayed along with the Events dimensions - if($segment['type'] == 'metric' && $segment['category'] != Piwik::translate('General_Visit')) { + if ($segment['type'] == 'metric' && $segment['category'] != Piwik::translate('General_Visit')) { $segment['type'] = 'dimension'; } diff --git a/plugins/API/RowEvolution.php b/plugins/API/RowEvolution.php index 7a5290c44f..b57a788050 100644 --- a/plugins/API/RowEvolution.php +++ b/plugins/API/RowEvolution.php @@ -279,7 +279,7 @@ class RowEvolution // note: some reports should not be filtered with AddColumnProcessedMetrics // specifically, reports without the Metrics::INDEX_NB_VISITS metric such as Goals.getVisitsUntilConversion & Goal.getDaysToConversion // this is because the AddColumnProcessedMetrics filter removes all datable rows lacking this metric - if( isset($metadata['metrics']['nb_visits']) + if ( isset($metadata['metrics']['nb_visits']) && !empty($label)) { $parameters['filter_add_columns_when_show_all_columns'] = '1'; } @@ -430,7 +430,7 @@ class RowEvolution $labelRow, $apiModule, $apiAction, $labelUseAbsoluteUrl); $prettyLabel = $labelRow->getColumn('label_html'); - if($prettyLabel !== false) { + if ($prettyLabel !== false) { $actualLabels[$labelIdx] = $prettyLabel; } diff --git a/plugins/Actions/Actions/ActionSiteSearch.php b/plugins/Actions/Actions/ActionSiteSearch.php index 9631aa0473..d19cfaa6fc 100644 --- a/plugins/Actions/Actions/ActionSiteSearch.php +++ b/plugins/Actions/Actions/ActionSiteSearch.php @@ -73,7 +73,7 @@ class ActionSiteSearch extends Action { $siteSearch = $this->detectSiteSearch($this->originalUrl); - if(empty($siteSearch)) { + if (empty($siteSearch)) { return false; } @@ -169,10 +169,10 @@ class ActionSiteSearch extends Action // @see excludeQueryParametersFromUrl() // Excluded the detected parameters from the URL $parametersToExclude = array($categoryParameterRaw, $keywordParameterRaw); - if(isset($parsedUrl['query'])) { + if (isset($parsedUrl['query'])) { $parsedUrl['query'] = UrlHelper::getQueryStringWithExcludedParameters(UrlHelper::getArrayFromQueryString($parsedUrl['query']), $parametersToExclude); } - if(isset($parsedUrl['fragment'])) { + if (isset($parsedUrl['fragment'])) { $parsedUrl['fragment'] = UrlHelper::getQueryStringWithExcludedParameters(UrlHelper::getArrayFromQueryString($parsedUrl['fragment']), $parametersToExclude); } } diff --git a/plugins/Actions/Archiver.php b/plugins/Actions/Archiver.php index 14d4214744..67408ced64 100644 --- a/plugins/Actions/Archiver.php +++ b/plugins/Actions/Archiver.php @@ -241,7 +241,7 @@ class Archiver extends \Piwik\Plugin\Archiver // 1) No result Keywords // 2) For each page view, count number of times the referrer page was a Site Search if ($this->isSiteSearchEnabled()) { - $this->updateQuerySelectFromForSiteSearch($select, $from); + $this->updateQuerySelectFromForSiteSearch($select, $from); } $this->archiveDayQueryProcess($select, $from, $where, $orderBy, $groupBy, "idaction_name", $rankingQuery); diff --git a/plugins/Annotations/AnnotationList.php b/plugins/Annotations/AnnotationList.php index 89a5b9131f..cf068e6f35 100755 --- a/plugins/Annotations/AnnotationList.php +++ b/plugins/Annotations/AnnotationList.php @@ -331,7 +331,7 @@ class AnnotationList if ($serialized !== false) { $result[$id] = @unserialize($serialized); - if(empty($result[$id])) { + if (empty($result[$id])) { // in case unserialize failed $result[$id] = array(); } diff --git a/plugins/CoreAdminHome/API.php b/plugins/CoreAdminHome/API.php index 530cc10156..a25a522cb4 100644 --- a/plugins/CoreAdminHome/API.php +++ b/plugins/CoreAdminHome/API.php @@ -66,19 +66,23 @@ class API extends \Piwik\Plugin\API public function invalidateArchivedReports($idSites, $dates, $period = false) { $idSites = Site::getIdSitesFromIdSitesString($idSites); + if (empty($idSites)) { throw new Exception("Specify a value for &idSites= as a comma separated list of website IDs, for which your token_auth has 'admin' permission"); } + Piwik::checkUserHasAdminAccess($idSites); - if(!empty($period)) { + if (!empty($period)) { $period = Period\Factory::build($period, Date::today()); } // Ensure the specified dates are valid $toInvalidate = $invalidDates = array(); + $dates = explode(',', trim($dates)); $dates = array_unique($dates); + foreach ($dates as $theDate) { $theDate = trim($theDate); try { @@ -141,7 +145,7 @@ class API extends \Piwik\Plugin\API } } - if(empty($minDate)) { + if (empty($minDate)) { throw new Exception("Check the 'dates' parameter is a valid date."); } @@ -169,7 +173,7 @@ class API extends \Piwik\Plugin\API $sql = implode(" OR ", $sql); $sqlPeriod = ""; - if($invalidateForPeriod) { + if ($invalidateForPeriod) { $sqlPeriod = " AND period = ? "; $bind[] = $invalidateForPeriod; } diff --git a/plugins/CoreAdminHome/Controller.php b/plugins/CoreAdminHome/Controller.php index 6b672d07e8..d1278607fd 100644 --- a/plugins/CoreAdminHome/Controller.php +++ b/plugins/CoreAdminHome/Controller.php @@ -278,7 +278,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin $successLogo = $logo->copyUploadedLogoToFilesystem(); $successFavicon = $logo->copyUploadedFaviconToFilesystem(); - if($successLogo || $successFavicon) { + if ($successLogo || $successFavicon) { return '1'; } return '0'; @@ -291,7 +291,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin private function saveGeneralSettings() { - if(!self::isGeneralSettingsAdminEnabled()) { + if (!self::isGeneralSettingsAdminEnabled()) { // General settings + Beta channel + SMTP settings is disabled return; } @@ -339,7 +339,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin { // Whether to display or not the general settings (cron, beta, smtp) $view->isGeneralSettingsAdminEnabled = self::isGeneralSettingsAdminEnabled(); - if($view->isGeneralSettingsAdminEnabled) { + if ($view->isGeneralSettingsAdminEnabled) { $this->displayWarningIfConfigFileNotWritable(); } diff --git a/plugins/CoreAdminHome/CustomLogo.php b/plugins/CoreAdminHome/CustomLogo.php index fe7e78ac6e..eda7ef0638 100644 --- a/plugins/CoreAdminHome/CustomLogo.php +++ b/plugins/CoreAdminHome/CustomLogo.php @@ -88,7 +88,7 @@ class CustomLogo */ public function isCustomLogoWritable() { - if(Config::getInstance()->General['enable_custom_logo_check'] == 0) { + if (Config::getInstance()->General['enable_custom_logo_check'] == 0) { return true; } $pathUserLogo = $this->getPathUserLogo(); @@ -196,7 +196,7 @@ class CustomLogo $image = imagecreatefrompng($file); break; case 'image/gif': - $image = imagecreatefromgif($file); + $image = imagecreatefromgif ($file); break; default: return false; diff --git a/plugins/CoreAdminHome/Tasks.php b/plugins/CoreAdminHome/Tasks.php index 461ca5ca52..d633b9fd5d 100644 --- a/plugins/CoreAdminHome/Tasks.php +++ b/plugins/CoreAdminHome/Tasks.php @@ -35,7 +35,7 @@ class Tasks extends \Piwik\Plugin\Tasks list($year, $month) = explode('_', $date); // Somehow we may have archive tables created with older dates, prevent exception from being thrown - if($year > 1990) { + if ($year > 1990) { ArchivePurger::purgeOutdatedArchives(Date::factory("$year-$month-15")); } } diff --git a/plugins/CoreConsole/Commands/GenerateTest.php b/plugins/CoreConsole/Commands/GenerateTest.php index a9ace19a8b..ff68eec784 100644 --- a/plugins/CoreConsole/Commands/GenerateTest.php +++ b/plugins/CoreConsole/Commands/GenerateTest.php @@ -42,7 +42,7 @@ class GenerateTest extends GeneratePluginBase ); $testClass = $this->getTestClass($testType); - if(!empty($testClass)) { + if (!empty($testClass)) { $replace['\PHPUnit_Framework_TestCase'] = $testClass; } @@ -167,7 +167,7 @@ class GenerateTest extends GeneratePluginBase */ protected function getTestFilesWhitelist($testType) { - if('Integration' == $testType) { + if ('Integration' == $testType) { return array( '/.gitignore', '/tests', diff --git a/plugins/CoreConsole/TravisYmlView.php b/plugins/CoreConsole/TravisYmlView.php index cb4fabfda2..a89b5f1df5 100644 --- a/plugins/CoreConsole/TravisYmlView.php +++ b/plugins/CoreConsole/TravisYmlView.php @@ -89,6 +89,7 @@ class TravisYmlView extends View $this->pluginName = $pluginName; $customTravisBuildSteps = array(); + foreach (self::$travisYmlExtendableSectionNames as $name) { $customTravisBuildSteps[$name] = array(); @@ -102,6 +103,7 @@ class TravisYmlView extends View $customTravisBuildSteps[$name]['after'] = $this->changeIndent(file_get_contents($afterStepsTemplate), ' '); } } + $this->customTravisBuildSteps = $customTravisBuildSteps; } @@ -160,12 +162,14 @@ class TravisYmlView extends View preg_match_all("/^[a-zA-Z_]+:/m", $yamlText, $allMatches, PREG_OFFSET_CAPTURE); $result = array(); + foreach ($allMatches[0] as $match) { $matchLength = strlen($match[0]); $sectionName = substr($match[0], 0, $matchLength - 1); $result[$sectionName] = $match[1] + $matchLength; } + return $result; } @@ -206,6 +210,7 @@ class TravisYmlView extends View $testsToExclude[] = array('php' => '5.4', 'env' => 'TEST_SUITE=PluginTests MYSQL_ADAPTER=PDO_MYSQL TEST_AGAINST_CORE=latest_stable'); } + if ($this->isTargetPluginContainsUITests()) { $testsToRun[] = array('name' => 'UITests', 'vars' => "MYSQL_ADAPTER=PDO_MYSQL"); diff --git a/plugins/CoreHome/Columns/VisitGoalBuyer.php b/plugins/CoreHome/Columns/VisitGoalBuyer.php index 1fcf91cb96..8867efd708 100644 --- a/plugins/CoreHome/Columns/VisitGoalBuyer.php +++ b/plugins/CoreHome/Columns/VisitGoalBuyer.php @@ -72,7 +72,7 @@ class VisitGoalBuyer extends VisitDimension // Ecommerce buyer status $visitEcommerceStatus = $this->getBuyerType($request, $goalBuyer); - if($visitEcommerceStatus != self::TYPE_BUYER_NONE + if ($visitEcommerceStatus != self::TYPE_BUYER_NONE // only update if the value has changed (prevents overwriting the value in case a request has // updated it in the meantime) && $visitEcommerceStatus != $goalBuyer) { diff --git a/plugins/CoreHome/Controller.php b/plugins/CoreHome/Controller.php index b0d3770cbe..387c31e9e9 100644 --- a/plugins/CoreHome/Controller.php +++ b/plugins/CoreHome/Controller.php @@ -103,9 +103,11 @@ class Controller extends \Piwik\Plugin\Controller ) { $module = 'MultiSites'; } + if ($defaultReport == Piwik::getLoginPluginName()) { $module = Piwik::getLoginPluginName(); } + $idSite = Common::getRequestVar('idSite', false, 'int'); parent::redirectToIndex($module, $action, $idSite); } @@ -113,10 +115,12 @@ class Controller extends \Piwik\Plugin\Controller public function showInContext() { $controllerName = Common::getRequestVar('moduleToLoad'); - $actionName = Common::getRequestVar('actionToLoad', 'index'); + $actionName = Common::getRequestVar('actionToLoad', 'index'); + if ($actionName == 'showInContext') { throw new Exception("Preventing infinite recursion..."); } + $view = $this->getDefaultIndexView(); $view->content = FrontController::getInstance()->fetchDispatch($controllerName, $actionName); return $view->render(); @@ -146,12 +150,16 @@ class Controller extends \Piwik\Plugin\Controller ) { return; } + $websiteId = Common::getRequestVar('idSite', false, 'int'); + if ($websiteId) { + $website = new Site($websiteId); - $datetimeCreationDate = $website->getCreationDate()->getDatetime(); + $datetimeCreationDate = $website->getCreationDate()->getDatetime(); $creationDateLocalTimezone = Date::factory($datetimeCreationDate, $website->getTimezone())->toString('Y-m-d'); - $todayLocalTimezone = Date::factory('now', $website->getTimezone())->toString('Y-m-d'); + $todayLocalTimezone = Date::factory('now', $website->getTimezone())->toString('Y-m-d'); + if ($creationDateLocalTimezone == $todayLocalTimezone) { Piwik::redirectToModule('CoreHome', 'index', array('date' => 'today', diff --git a/plugins/CoreHome/DataTableRowAction/RowEvolution.php b/plugins/CoreHome/DataTableRowAction/RowEvolution.php index 915139d300..b0922f05bf 100644 --- a/plugins/CoreHome/DataTableRowAction/RowEvolution.php +++ b/plugins/CoreHome/DataTableRowAction/RowEvolution.php @@ -86,7 +86,7 @@ class RowEvolution if (empty($this->apiMethod)) throw new Exception("Parameter apiMethod not set."); $this->label = ResponseBuilder::getLabelFromRequest($_GET); - if(!is_array($this->label)) { + if (!is_array($this->label)) { throw new Exception("Expected label to be an array, got instead: " . $this->label); } $this->label = $this->label[0]; @@ -337,7 +337,7 @@ class RowEvolution $labelPretty = $dataTableMap->getColumn('label_html'); $labelPretty = array_filter($labelPretty, 'strlen'); $labelPretty = current($labelPretty); - if(!empty($labelPretty)) { + if (!empty($labelPretty)) { return $labelPretty; } return $rowLabel; diff --git a/plugins/CorePluginsAdmin/Controller.php b/plugins/CorePluginsAdmin/Controller.php index 01c2837857..70942c7715 100644 --- a/plugins/CorePluginsAdmin/Controller.php +++ b/plugins/CorePluginsAdmin/Controller.php @@ -293,7 +293,7 @@ class Controller extends Plugin\ControllerAdmin $suffix = Piwik::translate('CorePluginsAdmin_PluginNotWorkingAlternative'); // If the plugin has been renamed, we do not show message to ask user to update plugin - if($pluginName != Request::renameModule($pluginName)) { + if ($pluginName != Request::renameModule($pluginName)) { $suffix = "You may uninstall the plugin or manually delete the files in piwik/plugins/$pluginName/"; } @@ -359,7 +359,7 @@ class Controller extends Plugin\ControllerAdmin return $message; } - if(Common::isPhpCliMode()) { + if (Common::isPhpCliMode()) { Piwik_ExitWithMessage("Error:" . var_export($lastError, true)); } diff --git a/plugins/CorePluginsAdmin/PluginInstaller.php b/plugins/CorePluginsAdmin/PluginInstaller.php index 58fd074909..8bb9c475d0 100644 --- a/plugins/CorePluginsAdmin/PluginInstaller.php +++ b/plugins/CorePluginsAdmin/PluginInstaller.php @@ -155,7 +155,7 @@ class PluginInstaller private function makeSureThereAreNoMissingRequirements($metadata) { $requires = array(); - if(!empty($metadata->require)) { + if (!empty($metadata->require)) { $requires = (array) $metadata->require; } diff --git a/plugins/CorePluginsAdmin/UpdateCommunication.php b/plugins/CorePluginsAdmin/UpdateCommunication.php index ad6c570e7e..3ed004993f 100644 --- a/plugins/CorePluginsAdmin/UpdateCommunication.php +++ b/plugins/CorePluginsAdmin/UpdateCommunication.php @@ -109,34 +109,8 @@ class UpdateCommunication $hasPluginUpdate = $hasPluginUpdate || !$plugin['isTheme']; } - $subject = Piwik::translate('CoreUpdater_NotificationSubjectAvailablePluginUpdate'); - $message = Piwik::translate('ScheduledReports_EmailHello'); - $message .= "\n\n"; - $message .= Piwik::translate('CoreUpdater_ThereIsNewPluginVersionAvailableForUpdate'); - $message .= "\n\n"; - - foreach ($pluginsToBeNotified as $plugin) { - $message .= sprintf(' * %s %s', $plugin['name'], $plugin['latestVersion']); - $message .= "\n"; - } - - $message .= "\n"; - - $host = SettingsPiwik::getPiwikUrl(); - if ($hasThemeUpdate) { - $message .= Piwik::translate('CoreUpdater_NotificationClickToUpdateThemes') . "\n"; - $message .= $host. 'index.php?module=CorePluginsAdmin&action=themes'; - } - if ($hasPluginUpdate) { - if ($hasThemeUpdate) { - $message .= "\n\n"; - } - $message .= Piwik::translate('CoreUpdater_NotificationClickToUpdatePlugins') . "\n"; - $message .= $host. 'index.php?module=CorePluginsAdmin&action=plugins'; - } - - $message .= "\n\n"; - $message .= Piwik::translate('Installation_HappyAnalysing'); + $subject = Piwik::translate('CoreUpdater_NotificationSubjectAvailablePluginUpdate'); + $message = $this->buildNotificationMessage($pluginsToBeNotified, $hasThemeUpdate, $hasPluginUpdate); $this->sendEmailNotification($subject, $message); } @@ -161,24 +135,24 @@ class UpdateCommunication } } - private function setHasLatestUpdateNotificationReceived($plugin) + protected function setHasLatestUpdateNotificationReceived($plugin) { $latestVersion = $this->getLatestVersion($plugin); Option::set($this->getNotificationSentOptionName($plugin), $latestVersion); } - private function getLatestVersionSent($plugin) + protected function getLatestVersionSent($plugin) { return Option::get($this->getNotificationSentOptionName($plugin)); } - private function getLatestVersion($plugin) + protected function getLatestVersion($plugin) { return $plugin['latestVersion']; } - private function hasNotificationAlreadyReceived($plugin) + protected function hasNotificationAlreadyReceived($plugin) { $latestVersion = $this->getLatestVersion($plugin); $lastVersionSent = $this->getLatestVersionSent($plugin); @@ -192,7 +166,7 @@ class UpdateCommunication return false; } - private function getNotificationSentOptionName($plugin) + protected function getNotificationSentOptionName($plugin) { return 'last_update_communication_sent_plugin_' . $plugin['name']; } @@ -207,4 +181,39 @@ class UpdateCommunication return $plugins; } + + protected function buildNotificationMessage($pluginsToBeNotified, $hasThemeUpdate, $hasPluginUpdate) + { + $message = Piwik::translate('ScheduledReports_EmailHello'); + $message .= "\n\n"; + $message .= Piwik::translate('CoreUpdater_ThereIsNewPluginVersionAvailableForUpdate'); + $message .= "\n\n"; + + foreach ($pluginsToBeNotified as $plugin) { + $message .= sprintf(' * %s %s', $plugin['name'], $plugin['latestVersion']); + $message .= "\n"; + } + + $message .= "\n"; + + $host = SettingsPiwik::getPiwikUrl(); + + if ($hasThemeUpdate) { + $message .= Piwik::translate('CoreUpdater_NotificationClickToUpdateThemes') . "\n"; + $message .= $host . 'index.php?module=CorePluginsAdmin&action=themes'; + } + + if ($hasPluginUpdate) { + if ($hasThemeUpdate) { + $message .= "\n\n"; + } + $message .= Piwik::translate('CoreUpdater_NotificationClickToUpdatePlugins') . "\n"; + $message .= $host . 'index.php?module=CorePluginsAdmin&action=plugins'; + } + + $message .= "\n\n"; + $message .= Piwik::translate('Installation_HappyAnalysing'); + + return $message; + } } diff --git a/plugins/CoreUpdater/Commands/Update.php b/plugins/CoreUpdater/Commands/Update.php index e5a0e39d33..108281c460 100644 --- a/plugins/CoreUpdater/Commands/Update.php +++ b/plugins/CoreUpdater/Commands/Update.php @@ -40,7 +40,7 @@ class Update extends ConsoleCommand try { $this->makeUpdate($input, $output, $doDryRun); - if(!$doDryRun) { + if (!$doDryRun) { $this->writeSuccessMessage($output, array("Piwik has been successfully updated!")); } diff --git a/plugins/CoreUpdater/Controller.php b/plugins/CoreUpdater/Controller.php index 1d1d689b56..cc27c3e9aa 100644 --- a/plugins/CoreUpdater/Controller.php +++ b/plugins/CoreUpdater/Controller.php @@ -327,11 +327,11 @@ class Controller extends \Piwik\Plugin\Controller $doExecuteUpdates = Common::getRequestVar('updateCorePlugins', 0, 'integer') == 1; - if(is_null($doDryRun)) { + if (is_null($doDryRun)) { $doDryRun = !$doExecuteUpdates; } - if($doDryRun) { + if ($doDryRun) { $viewWelcome->queries = $updater->getSqlQueriesToExecute(); $viewWelcome->isMajor = $updater->hasMajorDbUpdate(); $this->doWelcomeUpdates($viewWelcome, $componentsWithUpdateFile); diff --git a/plugins/CoreUpdater/UpdateCommunication.php b/plugins/CoreUpdater/UpdateCommunication.php index 5a113f74d5..cd52e80a3e 100644 --- a/plugins/CoreUpdater/UpdateCommunication.php +++ b/plugins/CoreUpdater/UpdateCommunication.php @@ -76,7 +76,7 @@ class UpdateCommunication $this->sendEmailNotification($subject, $message); } - private function isVersionLike($latestVersion) + protected function isVersionLike($latestVersion) { return strlen($latestVersion) < 18; } @@ -101,7 +101,7 @@ class UpdateCommunication } } - private function isNewVersionAvailable() + protected function isNewVersionAvailable() { UpdateCheck::check(); @@ -119,7 +119,7 @@ class UpdateCommunication return $hasUpdate; } - private function hasNotificationAlreadyReceived() + protected function hasNotificationAlreadyReceived() { $latestVersion = $this->getLatestVersion(); $lastVersionSent = $this->getLatestVersionSent(); diff --git a/plugins/CustomVariables/Archiver.php b/plugins/CustomVariables/Archiver.php index 241e2772a0..47e1363dc4 100644 --- a/plugins/CustomVariables/Archiver.php +++ b/plugins/CustomVariables/Archiver.php @@ -39,7 +39,7 @@ class Archiver extends \Piwik\Plugin\Archiver { parent::__construct($processor); - if($processor->getParams()->getSite()->isEcommerceEnabled()) { + if ($processor->getParams()->getSite()->isEcommerceEnabled()) { $this->maximumRowsInDataTableLevelZero = self::MAX_ROWS_WHEN_ECOMMERCE; $this->maximumRowsInSubDataTable = self::MAX_ROWS_WHEN_ECOMMERCE; } else { diff --git a/plugins/Dashboard/Controller.php b/plugins/Dashboard/Controller.php index 5e319ddb25..c7a89a75a5 100644 --- a/plugins/Dashboard/Controller.php +++ b/plugins/Dashboard/Controller.php @@ -104,38 +104,13 @@ class Controller extends \Piwik\Plugin\Controller $session->dashboardLayout = $layout; $session->setExpirationSeconds(1800); } else { - $this->saveLayoutForUser(Piwik::getCurrentUserLogin(), $idDashboard, $layout); + $this->getModel()->updateLayoutForUser(Piwik::getCurrentUserLogin(), $idDashboard, $layout); } } - /** - * Records the layout in the DB for the given user. - * - * @param string $login - * @param int $idDashboard - * @param string $layout - */ - protected function saveLayoutForUser($login, $idDashboard, $layout) - { - $paramsBind = array($login, $idDashboard, $layout, $layout); - $query = sprintf('INSERT INTO %s (login, iddashboard, layout) VALUES (?,?,?) ON DUPLICATE KEY UPDATE layout=?', - Common::prefixTable('user_dashboard')); - Db::query($query, $paramsBind); - } - - /** - * Updates the name of a dashboard - * - * @param string $login - * @param int $idDashboard - * @param string $name - */ - protected function updateDashboardName($login, $idDashboard, $name) + private function getModel() { - $paramsBind = array($name, $login, $idDashboard); - $query = sprintf('UPDATE %s SET name = ? WHERE login = ? AND iddashboard = ?', - Common::prefixTable('user_dashboard')); - Db::query($query, $paramsBind); + return new Model(); } /** @@ -153,9 +128,7 @@ class Controller extends \Piwik\Plugin\Controller // first layout can't be removed if ($idDashboard != 1) { - $query = sprintf('DELETE FROM %s WHERE iddashboard = ? AND login = ?', - Common::prefixTable('user_dashboard')); - Db::query($query, array($idDashboard, Piwik::getCurrentUserLogin())); + $this->getModel()->deleteDashboardForUser($idDashboard, Piwik::getCurrentUserLogin()); } } @@ -171,7 +144,7 @@ class Controller extends \Piwik\Plugin\Controller return '[]'; } - $login = Piwik::getCurrentUserLogin(); + $login = Piwik::getCurrentUserLogin(); $dashboards = $this->dashboard->getAllDashboards($login); Json::sendHeaderJSON(); @@ -189,38 +162,22 @@ class Controller extends \Piwik\Plugin\Controller if (Piwik::isUserIsAnonymous()) { return '0'; } - $user = Piwik::getCurrentUserLogin(); - $nextId = $this->getNextIdDashboard($user); - $name = urldecode(Common::getRequestVar('name', '', 'string')); - $type = urldecode(Common::getRequestVar('type', 'default', 'string')); + $name = urldecode(Common::getRequestVar('name', '', 'string')); + $type = urldecode(Common::getRequestVar('type', 'default', 'string')); $layout = '{}'; + $login = Piwik::getCurrentUserLogin(); if ($type == 'default') { $layout = $this->dashboard->getDefaultLayout(); } - $query = sprintf('INSERT INTO %s (login, iddashboard, name, layout) VALUES (?, ?, ?, ?)', - Common::prefixTable('user_dashboard')); - Db::query($query, array($user, $nextId, $name, $layout)); + $nextId = $this->getModel()->createNewDashboardForUser($login, $name, $layout); Json::sendHeaderJSON(); return Common::json_encode($nextId); } - private function getNextIdDashboard($login) - { - $nextIdQuery = sprintf('SELECT MAX(iddashboard)+1 FROM %s WHERE login = ?', - Common::prefixTable('user_dashboard')); - $nextId = Db::fetchOne($nextIdQuery, array($login)); - - if (empty($nextId)) { - $nextId = 1; - return $nextId; - } - return $nextId; - } - public function copyDashboardToUser() { $this->checkTokenInUrl(); @@ -228,18 +185,16 @@ class Controller extends \Piwik\Plugin\Controller if (!Piwik::hasUserSuperUserAccess()) { return '0'; } + $login = Piwik::getCurrentUserLogin(); - $name = urldecode(Common::getRequestVar('name', '', 'string')); - $user = urldecode(Common::getRequestVar('user', '', 'string')); + $name = urldecode(Common::getRequestVar('name', '', 'string')); + $user = urldecode(Common::getRequestVar('user', '', 'string')); $idDashboard = Common::getRequestVar('dashboardId', 0, 'int'); + $layout = $this->dashboard->getLayoutForUser($login, $idDashboard); if ($layout !== false) { - $nextId = $this->getNextIdDashboard($user); - - $query = sprintf('INSERT INTO %s (login, iddashboard, name, layout) VALUES (?, ?, ?, ?)', - Common::prefixTable('user_dashboard')); - Db::query($query, array($user, $nextId, $name, $layout)); + $nextId = $this->getModel()->createNewDashboardForUser($user, $name, $layout); Json::sendHeaderJSON(); return Common::json_encode($nextId); @@ -255,17 +210,18 @@ class Controller extends \Piwik\Plugin\Controller { $this->checkTokenInUrl(); - $layout = Common::unsanitizeInputValue(Common::getRequestVar('layout')); + $layout = Common::unsanitizeInputValue(Common::getRequestVar('layout')); $idDashboard = Common::getRequestVar('idDashboard', 1, 'int'); - $name = Common::getRequestVar('name', '', 'string'); + $name = Common::getRequestVar('name', '', 'string'); + if (Piwik::isUserIsAnonymous()) { $session = new SessionNamespace("Dashboard"); $session->dashboardLayout = $layout; $session->setExpirationSeconds(1800); } else { - $this->saveLayoutForUser(Piwik::getCurrentUserLogin(), $idDashboard, $layout); + $this->getModel()->updateLayoutForUser(Piwik::getCurrentUserLogin(), $idDashboard, $layout); if (!empty($name)) { - $this->updateDashboardName(Piwik::getCurrentUserLogin(), $idDashboard, $name); + $this->getModel()->updateDashboardName(Piwik::getCurrentUserLogin(), $idDashboard, $name); } } } @@ -279,10 +235,7 @@ class Controller extends \Piwik\Plugin\Controller if (Piwik::hasUserSuperUserAccess()) { $layout = Common::unsanitizeInputValue(Common::getRequestVar('layout')); - $paramsBind = array('', '1', $layout, $layout); - $query = sprintf('INSERT INTO %s (login, iddashboard, layout) VALUES (?,?,?) ON DUPLICATE KEY UPDATE layout=?', - Common::prefixTable('user_dashboard')); - Db::query($query, $paramsBind); + $this->getModel()->createOrUpdateDashboard('', '1', $layout); } } diff --git a/plugins/Dashboard/Dashboard.php b/plugins/Dashboard/Dashboard.php index cb545465ff..1ff5a98182 100644 --- a/plugins/Dashboard/Dashboard.php +++ b/plugins/Dashboard/Dashboard.php @@ -10,7 +10,6 @@ namespace Piwik\Plugins\Dashboard; use Piwik\Common; use Piwik\Db; -use Piwik\DbHelper; use Piwik\Piwik; use Piwik\WidgetsList; @@ -42,10 +41,7 @@ class Dashboard extends \Piwik\Plugin */ public function getLayoutForUser($login, $idDashboard) { - $paramsBind = array($login, $idDashboard); - $query = sprintf('SELECT layout FROM %s WHERE login = ? AND iddashboard = ?', - Common::prefixTable('user_dashboard')); - $return = Db::fetchAll($query, $paramsBind); + $return = $this->getModel()->getLayoutForUser($login, $idDashboard); if (count($return) == 0) { return false; @@ -54,6 +50,11 @@ class Dashboard extends \Piwik\Plugin return $return[0]['layout']; } + private function getModel() + { + return new Model(); + } + public function getDefaultLayout() { $defaultLayout = $this->getLayoutForUser('', 1); @@ -107,9 +108,7 @@ class Dashboard extends \Piwik\Plugin public function getAllDashboards($login) { - $dashboards = Db::fetchAll('SELECT iddashboard, name, layout - FROM ' . Common::prefixTable('user_dashboard') . - ' WHERE login = ? ORDER BY iddashboard', array($login)); + $dashboards = $this->getModel()->getAllDashboardsForUser($login); $nameless = 1; foreach ($dashboards as &$dashboard) { @@ -219,23 +218,17 @@ class Dashboard extends \Piwik\Plugin public function deleteDashboardLayout($userLogin) { - Db::query('DELETE FROM ' . Common::prefixTable('user_dashboard') . ' WHERE login = ?', array($userLogin)); + $this->getModel()->deleteAllLayoutsForUser($userLogin); } public function install() { - $dashboard = "login VARCHAR( 100 ) NOT NULL , - iddashboard INT NOT NULL , - name VARCHAR( 100 ) NULL DEFAULT NULL , - layout TEXT NOT NULL, - PRIMARY KEY ( login , iddashboard )"; - - DbHelper::createTable('user_dashboard', $dashboard); + Model::install(); } public function uninstall() { - Db::dropTables(Common::prefixTable('user_dashboard')); + Model::uninstall(); } public function getClientSideTranslationKeys(&$translationKeys) diff --git a/plugins/Dashboard/Model.php b/plugins/Dashboard/Model.php new file mode 100644 index 0000000000..39dcb06557 --- /dev/null +++ b/plugins/Dashboard/Model.php @@ -0,0 +1,147 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +namespace Piwik\Plugins\Dashboard; + +use Piwik\Common; +use Piwik\Db; +use Piwik\DbHelper; + +class Model +{ + private static $rawPrefix = 'user_dashboard'; + private $table; + + public function __construct() + { + $this->table = Common::prefixTable(self::$rawPrefix); + } + + /** + * Returns the layout in the DB for the given user, or false if the layout has not been set yet. + * Parameters must be checked BEFORE this function call + * + * @param string $login + * @param int $idDashboard + * + * @return bool|string + */ + public function getLayoutForUser($login, $idDashboard) + { + $query = sprintf('SELECT layout FROM %s WHERE login = ? AND iddashboard = ?', + $this->table); + $bind = array($login, $idDashboard); + $layouts = Db::fetchAll($query, $bind); + + return $layouts; + } + + public function getAllDashboardsForUser($login) + { + $dashboards = Db::fetchAll('SELECT iddashboard, name, layout FROM ' . $this->table . + ' WHERE login = ? ORDER BY iddashboard', array($login)); + + return $dashboards; + } + + public function deleteAllLayoutsForUser($userLogin) + { + Db::query('DELETE FROM ' . $this->table . ' WHERE login = ?', array($userLogin)); + } + + /** + * Updates the name of a dashboard + * + * @param string $login + * @param int $idDashboard + * @param string $name + */ + public function updateDashboardName($login, $idDashboard, $name) + { + $bind = array($name, $login, $idDashboard); + $query = sprintf('UPDATE %s SET name = ? WHERE login = ? AND iddashboard = ?', $this->table); + Db::query($query, $bind); + } + + /** + * Removes the dashboard with the given id + */ + public function deleteDashboardForUser($idDashboard, $login) + { + $query = sprintf('DELETE FROM %s WHERE iddashboard = ? AND login = ?', $this->table); + Db::query($query, array($idDashboard, $login)); + } + + /** + * Creates a new dashboard for the current user + * User needs to be logged in + */ + public function createNewDashboardForUser($login, $name, $layout) + { + $nextId = $this->getNextIdDashboard($login); + + $query = sprintf('INSERT INTO %s (login, iddashboard, name, layout) VALUES (?, ?, ?, ?)', $this->table); + $bind = array($login, $nextId, $name, $layout); + Db::query($query, $bind); + + return $nextId; + } + + /** + * Saves the layout as default + */ + public function createOrUpdateDashboard($login, $idDashboard, $layout) + { + $bind = array($login, $idDashboard, $layout, $layout); + $query = sprintf('INSERT INTO %s (login, iddashboard, layout) VALUES (?,?,?) ON DUPLICATE KEY UPDATE layout=?', + $this->table); + Db::query($query, $bind); + } + + private function getNextIdDashboard($login) + { + $nextIdQuery = sprintf('SELECT MAX(iddashboard)+1 FROM %s WHERE login = ?', $this->table); + $nextId = Db::fetchOne($nextIdQuery, array($login)); + + if (empty($nextId)) { + $nextId = 1; + } + + return $nextId; + } + + /** + * Records the layout in the DB for the given user. + * + * @param string $login + * @param int $idDashboard + * @param string $layout + */ + public function updateLayoutForUser($login, $idDashboard, $layout) + { + $bind = array($login, $idDashboard, $layout, $layout); + $query = sprintf('INSERT INTO %s (login, iddashboard, layout) VALUES (?,?,?) ON DUPLICATE KEY UPDATE layout=?', + $this->table); + Db::query($query, $bind); + } + + public static function install() + { + $dashboard = "login VARCHAR( 100 ) NOT NULL , + iddashboard INT NOT NULL , + name VARCHAR( 100 ) NULL DEFAULT NULL , + layout TEXT NOT NULL, + PRIMARY KEY ( login , iddashboard )"; + + DbHelper::createTable(self::$rawPrefix, $dashboard); + } + + public static function uninstall() + { + Db::dropTables(Common::prefixTable(self::$rawPrefix)); + } +} diff --git a/plugins/DevicesDetection/functions.php b/plugins/DevicesDetection/functions.php index af76162f01..0a3de1c367 100644 --- a/plugins/DevicesDetection/functions.php +++ b/plugins/DevicesDetection/functions.php @@ -179,7 +179,7 @@ function getOSFamilyFullNameExtended($label) return 'Bot'; } $label = OperatingSystemParser::getOsFamily($label); - if($label !== false) { + if ($label !== false) { return $label; } return Piwik::translate('General_Unknown'); diff --git a/plugins/Events/API.php b/plugins/Events/API.php index 361f0ef965..890979db2c 100644 --- a/plugins/Events/API.php +++ b/plugins/Events/API.php @@ -94,7 +94,7 @@ class API extends \Piwik\Plugin\API */ public function getDefaultSecondaryDimension($apiMethod) { - if(isset($this->defaultMappingApiToSecondaryDimension[$apiMethod])) { + if (isset($this->defaultMappingApiToSecondaryDimension[$apiMethod])) { return $this->defaultMappingApiToSecondaryDimension[$apiMethod]; } return false; @@ -106,11 +106,11 @@ class API extends \Piwik\Plugin\API $secondaryDimension = $this->getDefaultSecondaryDimension($apiMethod); } $record = $this->mappingApiToRecord[$apiMethod]; - if(!is_array($record)) { + if (!is_array($record)) { return $record; } // when secondaryDimension is incorrectly set - if(empty($record[$secondaryDimension])) { + if (empty($record[$secondaryDimension])) { return key($record); } return $record[$secondaryDimension]; @@ -124,7 +124,7 @@ class API extends \Piwik\Plugin\API public function getSecondaryDimensions($apiMethod) { $records = $this->mappingApiToRecord[$apiMethod]; - if(!is_array($records)) { + if (!is_array($records)) { return false; } return array_keys($records); diff --git a/plugins/Events/Archiver.php b/plugins/Events/Archiver.php index 02fe3a8d83..eb33d4899f 100644 --- a/plugins/Events/Archiver.php +++ b/plugins/Events/Archiver.php @@ -225,7 +225,7 @@ class Archiver extends \Piwik\Plugin\Archiver */ protected function getDataArray($name) { - if(empty($this->arrays[$name])) { + if (empty($this->arrays[$name])) { $this->arrays[$name] = new DataArray(); } return $this->arrays[$name]; diff --git a/plugins/Events/Events.php b/plugins/Events/Events.php index 3d335bd229..6a55588af4 100644 --- a/plugins/Events/Events.php +++ b/plugins/Events/Events.php @@ -184,7 +184,7 @@ class Events extends \Piwik\Plugin private function addRelatedReports($view, $secondaryDimension) { - if(empty($secondaryDimension)) { + if (empty($secondaryDimension)) { // eg. Row Evolution return; } @@ -194,7 +194,7 @@ class Events extends \Piwik\Plugin $apiMethod = $view->requestConfig->getApiMethodToRequest(); $secondaryDimensions = API::getInstance()->getSecondaryDimensions($apiMethod); - if(empty($secondaryDimensions)) { + if (empty($secondaryDimensions)) { return; } @@ -205,7 +205,7 @@ class Events extends \Piwik\Plugin . Piwik::translate('Events_SwitchToSecondaryDimension', ''); foreach($secondaryDimensions as $dimension) { - if($dimension == $secondaryDimension) { + if ($dimension == $secondaryDimension) { // don't show as related report the currently selected dimension continue; } diff --git a/plugins/ExampleRssWidget/RssRenderer.php b/plugins/ExampleRssWidget/RssRenderer.php index 254a30ce6f..7990b1acb8 100644 --- a/plugins/ExampleRssWidget/RssRenderer.php +++ b/plugins/ExampleRssWidget/RssRenderer.php @@ -54,7 +54,7 @@ class RssRenderer $i = 0; $items = array(); - if(!empty($rss->channel->item)) { + if (!empty($rss->channel->item)) { $items = $rss->channel->item; } foreach ($items as $post) { diff --git a/plugins/Goals/API.php b/plugins/Goals/API.php index 176cafad24..ffc5bfe467 100644 --- a/plugins/Goals/API.php +++ b/plugins/Goals/API.php @@ -54,14 +54,15 @@ class API extends \Piwik\Plugin\API //TODO calls to this function could be cached as static // would help UI at least, since some UI requests would call this 2-3 times.. $idSite = Site::getIdSitesFromIdSitesString($idSite); + if (empty($idSite)) { return array(); } + Piwik::checkUserHasViewAccess($idSite); - $goals = Db::fetchAll("SELECT * - FROM " . Common::prefixTable('goal') . " - WHERE idsite IN (" . implode(", ", $idSite) . ") - AND deleted = 0"); + + $goals = $this->getModel()->getActiveGoals($idSite); + $cleanedGoals = array(); foreach ($goals as &$goal) { if ($goal['match_attribute'] == 'manually') { @@ -71,6 +72,7 @@ class API extends \Piwik\Plugin\API } $cleanedGoals[$goal['idgoal']] = $goal; } + return $cleanedGoals; } @@ -91,35 +93,33 @@ class API extends \Piwik\Plugin\API public function addGoal($idSite, $name, $matchAttribute, $pattern, $patternType, $caseSensitive = false, $revenue = false, $allowMultipleConversionsPerVisit = false) { Piwik::checkUserHasAdminAccess($idSite); + $this->checkPatternIsValid($patternType, $pattern, $matchAttribute); - $name = $this->checkName($name); + $name = $this->checkName($name); $pattern = $this->checkPattern($pattern); - // save in db - $db = Db::get(); - $idGoal = $db->fetchOne("SELECT max(idgoal) + 1 - FROM " . Common::prefixTable('goal') . " - WHERE idsite = ?", $idSite); - if ($idGoal == false) { - $idGoal = 1; - } - $db->insert(Common::prefixTable('goal'), - array( - 'idsite' => $idSite, - 'idgoal' => $idGoal, - 'name' => $name, - 'match_attribute' => $matchAttribute, - 'pattern' => $pattern, - 'pattern_type' => $patternType, - 'case_sensitive' => (int)$caseSensitive, - 'allow_multiple' => (int)$allowMultipleConversionsPerVisit, - 'revenue' => (float)$revenue, - 'deleted' => 0, - )); + $goal = array( + 'name' => $name, + 'match_attribute' => $matchAttribute, + 'pattern' => $pattern, + 'pattern_type' => $patternType, + 'case_sensitive' => (int)$caseSensitive, + 'allow_multiple' => (int)$allowMultipleConversionsPerVisit, + 'revenue' => (float)$revenue, + 'deleted' => 0, + ); + + $idGoal = $this->getModel()->createGoalForSite($idSite, $goal); + Cache::regenerateCacheWebsiteAttributes($idSite); return $idGoal; } + private function getModel() + { + return new Model(); + } + /** * Updates a Goal description. * Will not update or re-process the conversions already recorded @@ -139,21 +139,21 @@ class API extends \Piwik\Plugin\API public function updateGoal($idSite, $idGoal, $name, $matchAttribute, $pattern, $patternType, $caseSensitive = false, $revenue = false, $allowMultipleConversionsPerVisit = false) { Piwik::checkUserHasAdminAccess($idSite); - $name = $this->checkName($name); + + $name = $this->checkName($name); $pattern = $this->checkPattern($pattern); $this->checkPatternIsValid($patternType, $pattern, $matchAttribute); - Db::get()->update(Common::prefixTable('goal'), - array( - 'name' => $name, - 'match_attribute' => $matchAttribute, - 'pattern' => $pattern, - 'pattern_type' => $patternType, - 'case_sensitive' => (int)$caseSensitive, - 'allow_multiple' => (int)$allowMultipleConversionsPerVisit, - 'revenue' => (float)$revenue, - ), - "idsite = '$idSite' AND idgoal = '$idGoal'" - ); + + $this->getModel()->updateGoal($idSite, $idGoal, array( + 'name' => $name, + 'match_attribute' => $matchAttribute, + 'pattern' => $pattern, + 'pattern_type' => $patternType, + 'case_sensitive' => (int) $caseSensitive, + 'allow_multiple' => (int) $allowMultipleConversionsPerVisit, + 'revenue' => (float) $revenue, + )); + Cache::regenerateCacheWebsiteAttributes($idSite); } @@ -188,11 +188,9 @@ class API extends \Piwik\Plugin\API public function deleteGoal($idSite, $idGoal) { Piwik::checkUserHasAdminAccess($idSite); - Db::query("UPDATE " . Common::prefixTable('goal') . " - SET deleted = 1 - WHERE idsite = ? - AND idgoal = ?", - array($idSite, $idGoal)); + + $this->getModel()->deleteGoal($idSite, $idGoal); + Db::deleteAllRows(Common::prefixTable("log_conversion"), "WHERE idgoal = ? AND idsite = ?", "idvisit", 100000, array($idGoal, $idSite)); Cache::regenerateCacheWebsiteAttributes($idSite); } @@ -204,11 +202,13 @@ class API extends \Piwik\Plugin\API protected function getItems($recordName, $idSite, $period, $date, $abandonedCarts, $segment) { Piwik::checkUserHasViewAccess($idSite); + $recordNameFinal = $recordName; if ($abandonedCarts) { $recordNameFinal = Archiver::getItemRecordNameAbandonedCart($recordName); } - $archive = Archive::build($idSite, $period, $date, $segment); + + $archive = Archive::build($idSite, $period, $date, $segment); $dataTable = $archive->getDataTable($recordNameFinal); $dataTable->filter('Sort', array(Metrics::INDEX_ECOMMERCE_ITEM_REVENUE)); @@ -250,6 +250,7 @@ class API extends \Piwik\Plugin\API } return; } + $rowNotDefined = $dataTable->getRowFromLabel(\Piwik\Plugins\CustomVariables\Archiver::LABEL_CUSTOM_VALUE_NOT_DEFINED); if ($rowNotDefined) { $rowNotDefined->setColumn('label', $notDefinedStringPretty); diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php index f5a3f1f735..e7af6d6243 100644 --- a/plugins/Goals/Controller.php +++ b/plugins/Goals/Controller.php @@ -98,7 +98,7 @@ class Controller extends \Piwik\Plugin\Controller { $saveGET = $_GET; $filterEcommerce = Common::getRequestVar('filterEcommerce', self::ECOMMERCE_LOG_SHOW_ORDERS, 'int'); - if($filterEcommerce == self::ECOMMERCE_LOG_SHOW_ORDERS) { + if ($filterEcommerce == self::ECOMMERCE_LOG_SHOW_ORDERS) { $segment = urlencode('visitEcommerceStatus==ordered,visitEcommerceStatus==orderedThenAbandonedCart'); } else { $segment = urlencode('visitEcommerceStatus==abandonedCart,visitEcommerceStatus==orderedThenAbandonedCart'); @@ -458,7 +458,7 @@ class Controller extends \Piwik\Plugin\Controller foreach ($allReports as $category => $reports) { $categoryText = Piwik::translate('Goals_ViewGoalsBy', $category); foreach ($reports as $report) { - if(empty($report['viewDataTable'])) { + if (empty($report['viewDataTable'])) { $report['viewDataTable'] = 'tableGoals'; } $customParams['viewDataTable'] = $report['viewDataTable']; diff --git a/plugins/Goals/Goals.php b/plugins/Goals/Goals.php index 39a7c0b2dc..381c37f7ee 100644 --- a/plugins/Goals/Goals.php +++ b/plugins/Goals/Goals.php @@ -135,7 +135,8 @@ class Goals extends \Piwik\Plugin */ public function deleteSiteGoals($idSite) { - Db::query("DELETE FROM " . Common::prefixTable('goal') . " WHERE idsite = ? ", array($idSite)); + $model = new Model(); + $model->deleteGoalsForSite($idSite); } /** diff --git a/plugins/Goals/Model.php b/plugins/Goals/Model.php new file mode 100644 index 0000000000..93a9e9fd40 --- /dev/null +++ b/plugins/Goals/Model.php @@ -0,0 +1,87 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\Goals; + +use Piwik\Common; +use Piwik\Db; + +class Model +{ + private static $rawPrefix = 'goal'; + private $table; + + public function __construct() + { + $this->table = Common::prefixTable(self::$rawPrefix); + } + + private function getNextIdGoal($idSite) + { + $db = $this->getDb(); + $idGoal = $db->fetchOne("SELECT max(idgoal) + 1 FROM " . $this->table . " + WHERE idsite = ?", $idSite); + + if (empty($idGoal)) { + $idGoal = 1; + } + + return $idGoal; + } + + public function createGoalForSite($idSite, $goal) + { + $db = $this->getDb(); + $goalId = $this->getNextIdGoal($idSite); + + $goal['idgoal'] = $goalId; + $goal['idsite'] = $idSite; + + $db->insert($this->table, $goal); + + return $goalId; + } + + public function updateGoal($idSite, $idGoal, $goal) + { + $idSite = (int) $idSite; + $idGoal = (int) $idGoal; + + $db = $this->getDb(); + $db->update($this->table, $goal, "idsite = '$idSite' AND idgoal = '$idGoal'"); + } + + public function getActiveGoals($idSite) + { + $idSite = array_map('intval', $idSite); + $goals = Db::fetchAll("SELECT * FROM " . $this->table . " + WHERE idsite IN (" . implode(", ", $idSite) . ") + AND deleted = 0"); + + return $goals; + } + + public function deleteGoalsForSite($idSite) + { + Db::query("DELETE FROM " . $this->table . " WHERE idsite = ? ", array($idSite)); + } + + public function deleteGoal($idSite, $idGoal) + { + $query = "UPDATE " . $this->table . " SET deleted = 1 + WHERE idsite = ? AND idgoal = ?"; + $bind = array($idSite, $idGoal); + + Db::query($query, $bind); + } + + private function getDb() + { + return Db::get(); + } +} diff --git a/plugins/Goals/Visualizations/Goals.php b/plugins/Goals/Visualizations/Goals.php index 0b8c2c5365..9808621b14 100644 --- a/plugins/Goals/Visualizations/Goals.php +++ b/plugins/Goals/Visualizations/Goals.php @@ -31,7 +31,7 @@ class Goals extends HtmlTable { parent::beforeLoadDataTable(); - if($this->config->disable_subtable_when_show_goals) { + if ($this->config->disable_subtable_when_show_goals) { $this->config->subtable_controller_action = null; } diff --git a/plugins/ImageGraph/StaticGraph/GridGraph.php b/plugins/ImageGraph/StaticGraph/GridGraph.php index 3eeb1393db..4ffde4c2c4 100644 --- a/plugins/ImageGraph/StaticGraph/GridGraph.php +++ b/plugins/ImageGraph/StaticGraph/GridGraph.php @@ -419,11 +419,11 @@ abstract class GridGraph extends StaticGraph // see https://github.com/piwik/piwik/issues/3396 // protected function displayMinMaxValues() // { -// if($displayMinMax) +// if ($displayMinMax) // { // // when plotting multiple metrics, display min & max on both series // // to fix: in vertical bars, labels are hidden when multiple metrics are plotted, hence the restriction on count($this->ordinateSeries) == 1 -// if($this->multipleMetrics && count($this->ordinateSeries) == 1) +// if ($this->multipleMetrics && count($this->ordinateSeries) == 1) // { // $colorIndex = 1; // foreach($this->ordinateSeries as $column => $data) @@ -467,13 +467,13 @@ abstract class GridGraph extends StaticGraph // $maxValueIndex = 0; // foreach($data as $index => $value) // { -// if($value > $maxValue) +// if ($value > $maxValue) // { // $maxValue = $value; // $maxValueIndex = $index; // } // -// if($value < $minValue) +// if ($value < $minValue) // { // $minValue = $value; // $minValueIndex = $index; diff --git a/plugins/Installation/Controller.php b/plugins/Installation/Controller.php index d3da5402f0..aaeb2a6b0e 100644 --- a/plugins/Installation/Controller.php +++ b/plugins/Installation/Controller.php @@ -84,7 +84,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin // Delete merged js/css files to force regenerations based on updated activated plugin list Filesystem::deleteAllCacheOnUpdate(); - if(empty($message)) { + if (empty($message)) { $this->checkPiwikIsNotInstalled(); } $view = new View( @@ -234,7 +234,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin ); $result = $this->updateComponents(); - if($result === false) { + if ($result === false) { $this->redirectToNextStep('tablesCreation'); } @@ -259,7 +259,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin $this->checkPiwikIsNotInstalled(); $this->initObjectsToCallAPI(); - if(count(APIUsersManager::getInstance()->getUsersHavingSuperUserAccess()) > 0) { + if (count(APIUsersManager::getInstance()->getUsersHavingSuperUserAccess()) > 0) { $this->redirectToNextStep('setupSuperUser'); } @@ -303,7 +303,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin $this->initObjectsToCallAPI(); - if(count(APISitesManager::getInstance()->getAllSitesId()) > 0) { + if (count(APISitesManager::getInstance()->getAllSitesId()) > 0) { // if there is a already a website, skip this step and trackingCode step $this->redirectToNextStep('trackingCode'); } @@ -336,7 +336,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin } // Display previous step success message, when current step form was not submitted yet - if(count($form->getErrorMessages()) == 0) { + if (count($form->getErrorMessages()) == 0) { $view->displayGeneralSetupSuccess = true; } @@ -513,7 +513,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin private function checkPiwikIsNotInstalled() { - if(!SettingsPiwik::isPiwikInstalled()) { + if (!SettingsPiwik::isPiwikInstalled()) { return; } \Piwik\Plugins\Login\Controller::clearSession(); @@ -658,7 +658,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin private function deleteConfigFileIfNeeded() { $config = Config::getInstance(); - if($config->existsLocalConfig()) { + if ($config->existsLocalConfig()) { $config->deleteLocalConfig(); } } diff --git a/plugins/Installation/FormFirstWebsiteSetup.php b/plugins/Installation/FormFirstWebsiteSetup.php index 83c68bea34..93eced71b4 100644 --- a/plugins/Installation/FormFirstWebsiteSetup.php +++ b/plugins/Installation/FormFirstWebsiteSetup.php @@ -31,7 +31,7 @@ class FormFirstWebsiteSetup extends QuickForm2 HTML_QuickForm2_Factory::registerRule('checkTimezone', 'Piwik\Plugins\Installation\Rule_isValidTimezone'); $urlExample = 'http://example.org'; - $javascriptOnClickUrlExample = "javascript:if(this.value=='$urlExample'){this.value='http://';} this.style.color='black';"; + $javascriptOnClickUrlExample = "javascript:if (this.value=='$urlExample'){this.value='http://';} this.style.color='black';"; $timezones = API::getInstance()->getTimezonesList(); $timezones = array_merge(array('No timezone' => Piwik::translate('SitesManager_SelectACity')), $timezones); diff --git a/plugins/Installation/ServerFilesGenerator.php b/plugins/Installation/ServerFilesGenerator.php index 5ce2abf844..9551340e4a 100644 --- a/plugins/Installation/ServerFilesGenerator.php +++ b/plugins/Installation/ServerFilesGenerator.php @@ -18,7 +18,7 @@ class ServerFilesGenerator */ public static function createHtAccessFiles() { - if(!SettingsServer::isApache()) { + if (!SettingsServer::isApache()) { return; } $denyAll = self::getDenyAllHtaccessContent(); diff --git a/plugins/Installation/SystemCheck.php b/plugins/Installation/SystemCheck.php index f6d8c42e02..29f87f2415 100644 --- a/plugins/Installation/SystemCheck.php +++ b/plugins/Installation/SystemCheck.php @@ -140,7 +140,7 @@ class SystemCheck } $sessionAutoStarted = (int)ini_get('session.auto_start'); - if($sessionAutoStarted) { + if ($sessionAutoStarted) { $infos['missing_desired_functions'][] = 'session.auto_start'; } diff --git a/plugins/LanguagesManager/API.php b/plugins/LanguagesManager/API.php index e95931ae87..e715770279 100644 --- a/plugins/LanguagesManager/API.php +++ b/plugins/LanguagesManager/API.php @@ -9,7 +9,6 @@ */ namespace Piwik\Plugins\LanguagesManager; -use Piwik\Common; use Piwik\Db; use Piwik\Filesystem; use Piwik\Piwik; @@ -229,12 +228,20 @@ class API extends \Piwik\Plugin\API */ public function getLanguageForUser($login) { - if($login == 'anonymous') { + if ($login == 'anonymous') { return false; } + Piwik::checkUserHasSuperUserAccessOrIsTheUser($login); - return Db::fetchOne('SELECT language FROM ' . Common::prefixTable('user_language') . - ' WHERE login = ? ', array($login)); + + $lang = $this->getModel()->getLanguageForUser($login); + + return $lang; + } + + private function getModel() + { + return new Model(); } /** @@ -248,15 +255,13 @@ class API extends \Piwik\Plugin\API { Piwik::checkUserHasSuperUserAccessOrIsTheUser($login); Piwik::checkUserIsNotAnonymous(); + if (!$this->isLanguageAvailable($languageCode)) { return false; } - $paramsBind = array($login, $languageCode, $languageCode); - Db::query('INSERT INTO ' . Common::prefixTable('user_language') . - ' (login, language) - VALUES (?,?) - ON DUPLICATE KEY UPDATE language=?', - $paramsBind); + + $this->getModel()->setLanguageForUser($login, $languageCode); + return true; } diff --git a/plugins/LanguagesManager/Commands/CompareKeys.php b/plugins/LanguagesManager/Commands/CompareKeys.php index 088bb492ae..821342a90c 100644 --- a/plugins/LanguagesManager/Commands/CompareKeys.php +++ b/plugins/LanguagesManager/Commands/CompareKeys.php @@ -62,7 +62,7 @@ class CompareKeys extends ConsoleCommand { if (!empty($englishFromOTrance[$category])) { foreach ($englishFromOTrance[$category] as $key => $value) { - if(!array_key_exists($category, $availableTranslations) || !array_key_exists($key, $availableTranslations[$category])) { + if (!array_key_exists($category, $availableTranslations) || !array_key_exists($key, $availableTranslations[$category])) { $unnecessary[] = sprintf('%s_%s', $category, $key); continue; } else if (html_entity_decode($availableTranslations[$category][$key]) != html_entity_decode($englishFromOTrance[$category][$key])) { @@ -73,7 +73,7 @@ class CompareKeys extends ConsoleCommand } if (!empty($availableTranslations[$category])) { foreach ($availableTranslations[$category] as $key => $value) { - if(!array_key_exists($category, $englishFromOTrance) || !array_key_exists($key, $englishFromOTrance[$category])) { + if (!array_key_exists($category, $englishFromOTrance) || !array_key_exists($key, $englishFromOTrance[$category])) { $missing[] = sprintf('%s_%s', $category, $key); continue; } diff --git a/plugins/LanguagesManager/LanguagesManager.php b/plugins/LanguagesManager/LanguagesManager.php index 66fba008e5..6a0fcf10e1 100644 --- a/plugins/LanguagesManager/LanguagesManager.php +++ b/plugins/LanguagesManager/LanguagesManager.php @@ -14,7 +14,6 @@ use Piwik\Common; use Piwik\Config; use Piwik\Cookie; use Piwik\Db; -use Piwik\DbHelper; use Piwik\Piwik; use Piwik\Translate; use Piwik\View; @@ -102,7 +101,8 @@ class LanguagesManager extends \Piwik\Plugin public function deleteUserLanguage($userLogin) { - Db::query('DELETE FROM ' . Common::prefixTable('user_language') . ' WHERE login = ?', $userLogin); + $model = new Model(); + $model->deleteUserLanguage($userLogin); } /** @@ -110,10 +110,7 @@ class LanguagesManager extends \Piwik\Plugin */ public function install() { - $userLanguage = "login VARCHAR( 100 ) NOT NULL , - language VARCHAR( 10 ) NOT NULL , - PRIMARY KEY ( login )"; - DbHelper::createTable('user_language', $userLanguage); + Model::install(); } /** @@ -121,7 +118,7 @@ class LanguagesManager extends \Piwik\Plugin */ public function uninstall() { - Db::dropTables(Common::prefixTable('user_language')); + Model::uninstall(); } /** diff --git a/plugins/LanguagesManager/Model.php b/plugins/LanguagesManager/Model.php new file mode 100644 index 0000000000..e40452c134 --- /dev/null +++ b/plugins/LanguagesManager/Model.php @@ -0,0 +1,72 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + * + */ +namespace Piwik\Plugins\LanguagesManager; + +use Piwik\Common; +use Piwik\Db; +use Piwik\DbHelper; + +class Model +{ + private static $rawPrefix = 'user_language'; + private $table; + + public function __construct() + { + $this->table = Common::prefixTable(self::$rawPrefix); + } + + public function deleteUserLanguage($userLogin) + { + Db::query('DELETE FROM ' . $this->table . ' WHERE login = ?', $userLogin); + } + + /** + * Returns the language for the user + * + * @param string $userLogin + * @return string + */ + public function getLanguageForUser($userLogin) + { + return Db::fetchOne('SELECT language FROM ' . $this->table . + ' WHERE login = ? ', array($userLogin)); + } + + /** + * Sets the language for the user + * + * @param string $login + * @param string $languageCode + * @return bool + */ + public function setLanguageForUser($login, $languageCode) + { + $query = 'INSERT INTO ' . $this->table . + ' (login, language) VALUES (?,?) ON DUPLICATE KEY UPDATE language=?'; + $bind = array($login, $languageCode, $languageCode); + Db::query($query, $bind); + + return true; + } + + public static function install() + { + $userLanguage = "login VARCHAR( 100 ) NOT NULL , + language VARCHAR( 10 ) NOT NULL , + PRIMARY KEY ( login )"; + DbHelper::createTable(self::$rawPrefix, $userLanguage); + } + + public static function uninstall() + { + Db::dropTables(Common::prefixTable(self::$rawPrefix)); + } +} diff --git a/plugins/Live/API.php b/plugins/Live/API.php index c2acabb619..d15cca9e36 100644 --- a/plugins/Live/API.php +++ b/plugins/Live/API.php @@ -306,7 +306,7 @@ class API extends \Piwik\Plugin\API $cities[$countryCode] = array(); } $city = $visit->getColumn('city'); - if(!empty($city)) { + if (!empty($city)) { $cities[$countryCode][] = $city; } } @@ -325,7 +325,7 @@ class API extends \Piwik\Plugin\API 'nb_visits' => $nbVisits, 'flag' => \Piwik\Plugins\UserCountry\getFlagFromCode($countryCode), 'prettyName' => \Piwik\Plugins\UserCountry\countryTranslate($countryCode)); - if(!empty($cities[$countryCode])) { + if (!empty($cities[$countryCode])) { $countryInfo['cities'] = array_unique($cities[$countryCode]); } $result['countries'][] = $countryInfo; @@ -476,8 +476,7 @@ class API extends \Piwik\Plugin\API $segment = new Segment($segment, $idSite); $queryInfo = $segment->getSelectQuery($select, $from, $where, $whereBind, $orderBy, $groupBy); - $sql = "SELECT sub.idvisitor, sub.visit_last_action_time - FROM ({$queryInfo['sql']}) as sub + $sql = "SELECT sub.idvisitor, sub.visit_last_action_time FROM ({$queryInfo['sql']}) as sub WHERE $visitLastActionTimeCondition LIMIT 1"; $bind = array_merge($queryInfo['bind'], array($visitLastActionTime)); @@ -589,7 +588,7 @@ class API extends \Piwik\Plugin\API $visitorDetailsArray['serverTimestamp'] = $visitorDetailsArray['lastActionTimestamp']; $dateTimeVisit = Date::factory($visitorDetailsArray['lastActionTimestamp'], $timezone); - if($dateTimeVisit) { + if ($dateTimeVisit) { $visitorDetailsArray['serverTimePretty'] = $dateTimeVisit->getLocalized('%time%'); $visitorDetailsArray['serverDatePretty'] = $dateTimeVisit->getLocalized(Piwik::translate('CoreHome_ShortDateFormat')); } @@ -703,8 +702,7 @@ class API extends \Piwik\Plugin\API // Group by idvisit so that a visitor converting 2 goals only appears once $sql = " - SELECT sub.* - FROM ( + SELECT sub.* FROM ( " . $subQuery['sql'] . " $sqlLimit ) AS sub diff --git a/plugins/Live/Visitor.php b/plugins/Live/Visitor.php index ae01ed4e18..55fd3fed83 100644 --- a/plugins/Live/Visitor.php +++ b/plugins/Live/Visitor.php @@ -309,7 +309,7 @@ class Visitor implements VisitorInterface } elseif ($actionDetail['type'] == Action::TYPE_EVENT_CATEGORY) { // Handle Event - if(strlen($actionDetail['pageTitle']) > 0) { + if (strlen($actionDetail['pageTitle']) > 0) { $actionDetail['eventName'] = $actionDetail['pageTitle']; } @@ -322,8 +322,8 @@ class Visitor implements VisitorInterface } // Event value / Generation time - if($actionDetail['type'] == Action::TYPE_EVENT_CATEGORY) { - if(strlen($actionDetail['custom_float']) > 0) { + if ($actionDetail['type'] == Action::TYPE_EVENT_CATEGORY) { + if (strlen($actionDetail['custom_float']) > 0) { $actionDetail['eventValue'] = round($actionDetail['custom_float'], self::EVENT_VALUE_PRECISION); } } elseif ($actionDetail['custom_float'] > 0) { diff --git a/plugins/Live/VisitorLog.php b/plugins/Live/VisitorLog.php index 2afc67349b..054b2f50ae 100644 --- a/plugins/Live/VisitorLog.php +++ b/plugins/Live/VisitorLog.php @@ -105,7 +105,7 @@ class VisitorLog extends Visualization && $filterEcommerce == \Piwik\Plugins\Goals\Controller::ECOMMERCE_LOG_SHOW_ORDERS; $isAbandonedCart = $action['type'] == 'ecommerceAbandonedCart' && $filterEcommerce == \Piwik\Plugins\Goals\Controller::ECOMMERCE_LOG_SHOW_ABANDONED_CARTS; - if($isAbandonedCart || $isEcommerceOrder) { + if ($isAbandonedCart || $isEcommerceOrder) { return true; } } diff --git a/plugins/Login/Controller.php b/plugins/Login/Controller.php index 82ae9ccab2..3831e89c79 100644 --- a/plugins/Login/Controller.php +++ b/plugins/Login/Controller.php @@ -330,4 +330,4 @@ class Controller extends \Piwik\Plugin\Controller Url::redirectToUrl($logoutUrl); } } -}
\ No newline at end of file +} diff --git a/plugins/Login/Login.php b/plugins/Login/Login.php index 4c33579176..8b65e2e175 100644 --- a/plugins/Login/Login.php +++ b/plugins/Login/Login.php @@ -85,7 +85,7 @@ class Login extends \Piwik\Plugin */ public static function initAuthenticationFromCookie(\Piwik\Auth $auth, $activateCookieAuth) { - if(self::isModuleIsAPI() && !$activateCookieAuth) { + if (self::isModuleIsAPI() && !$activateCookieAuth) { return; } diff --git a/plugins/MultiSites/API.php b/plugins/MultiSites/API.php index 41031fae8f..ea393414f7 100755 --- a/plugins/MultiSites/API.php +++ b/plugins/MultiSites/API.php @@ -346,7 +346,7 @@ class API extends \Piwik\Plugin\API { $metrics = self::$baseMetrics; - if(Common::isActionsPluginEnabled()) { + if (Common::isActionsPluginEnabled()) { $metrics[self::NB_PAGEVIEWS_LABEL] = array( self::METRIC_TRANSLATION_KEY => 'General_ColumnPageviews', self::METRIC_EVOLUTION_COL_NAME_KEY => 'pageviews_evolution', diff --git a/plugins/PrivacyManager/DoNotTrackHeaderChecker.php b/plugins/PrivacyManager/DoNotTrackHeaderChecker.php index b857debf85..14938f426e 100644 --- a/plugins/PrivacyManager/DoNotTrackHeaderChecker.php +++ b/plugins/PrivacyManager/DoNotTrackHeaderChecker.php @@ -26,7 +26,7 @@ class DoNotTrackHeaderChecker */ public function checkHeaderInTracker(&$exclude) { - if($exclude) { + if ($exclude) { Common::printDebug("Visit is already excluded, no need to check DoNotTrack support."); return; } diff --git a/plugins/PrivacyManager/LogDataPurger.php b/plugins/PrivacyManager/LogDataPurger.php index 2ec73deb81..6fe1381c50 100755 --- a/plugins/PrivacyManager/LogDataPurger.php +++ b/plugins/PrivacyManager/LogDataPurger.php @@ -173,7 +173,7 @@ class LogDataPurger private function getLogTableDeleteCount($table, $maxIdVisit) { $sql = "SELECT COUNT(*) FROM $table WHERE idvisit <= ?"; - return (int)Db::fetchOne($sql, array($maxIdVisit)); + return (int) Db::fetchOne($sql, array($maxIdVisit)); } private function createTempTable() diff --git a/plugins/PrivacyManager/ReportsPurger.php b/plugins/PrivacyManager/ReportsPurger.php index a35169e6ef..9889c00e9d 100755 --- a/plugins/PrivacyManager/ReportsPurger.php +++ b/plugins/PrivacyManager/ReportsPurger.php @@ -260,12 +260,11 @@ class ReportsPurger { $maxIdArchive = Db::fetchOne("SELECT MAX(idarchive) FROM $table"); - $sql = "SELECT COUNT(*) - FROM $table - WHERE name NOT IN ('" . implode("','", $this->metricsToKeep) . "') - AND name NOT LIKE 'done%' - AND idarchive >= ? - AND idarchive < ?"; + $sql = "SELECT COUNT(*) FROM $table + WHERE name NOT IN ('" . implode("','", $this->metricsToKeep) . "') + AND name NOT LIKE 'done%' + AND idarchive >= ? + AND idarchive < ?"; $segments = Db::segmentedFetchOne($sql, 0, $maxIdArchive, self::$selectSegmentSize); return array_sum($segments); @@ -275,11 +274,10 @@ class ReportsPurger { $maxIdArchive = Db::fetchOne("SELECT MAX(idarchive) FROM $table"); - $sql = "SELECT COUNT(*) - FROM $table - WHERE " . $this->getBlobTableWhereExpr($oldNumericTables, $table) . " - AND idarchive >= ? - AND idarchive < ?"; + $sql = "SELECT COUNT(*) FROM $table + WHERE " . $this->getBlobTableWhereExpr($oldNumericTables, $table) . " + AND idarchive >= ? + AND idarchive < ?"; $segments = Db::segmentedFetchOne($sql, 0, $maxIdArchive, self::$selectSegmentSize); return array_sum($segments); @@ -325,12 +323,11 @@ class ReportsPurger $maxIdArchive = Db::fetchOne("SELECT MAX(idarchive) FROM $table"); - $sql = "SELECT idarchive - FROM $table - WHERE name != 'done' - AND name LIKE 'done_%.%' - AND idarchive >= ? - AND idarchive < ?"; + $sql = "SELECT idarchive FROM $table + WHERE name != 'done' + AND name LIKE 'done_%.%' + AND idarchive >= ? + AND idarchive < ?"; if (is_null($this->segmentArchiveIds)) { $this->segmentArchiveIds = array(); diff --git a/plugins/Referrers/Columns/Base.php b/plugins/Referrers/Columns/Base.php index de871401b3..a69fcc54bf 100644 --- a/plugins/Referrers/Columns/Base.php +++ b/plugins/Referrers/Columns/Base.php @@ -244,14 +244,14 @@ abstract class Base extends VisitDimension protected function detectCampaignKeywordFromReferrerUrl() { - if(!empty($this->nameReferrerAnalyzed) + if (!empty($this->nameReferrerAnalyzed) && !empty($this->keywordReferrerAnalyzed)) { // keyword is already set, we skip return true; } // Set the Campaign keyword to the keyword found in the Referrer URL if any - if(!empty($this->nameReferrerAnalyzed)) { + if (!empty($this->nameReferrerAnalyzed)) { $referrerUrlInfo = UrlHelper::extractSearchEngineInformationFromUrl($this->referrerUrl); if (!empty($referrerUrlInfo['keywords'])) { $this->keywordReferrerAnalyzed = $referrerUrlInfo['keywords']; @@ -270,7 +270,7 @@ abstract class Base extends VisitDimension $parsedAdsenseReferrerUrl = parse_url($value); if (!empty($parsedAdsenseReferrerUrl['host'])) { - if(empty($this->nameReferrerAnalyzed)) { + if (empty($this->nameReferrerAnalyzed)) { $type = $this->getParameterValueFromReferrerUrl('ad_type'); $type = $type ? " ($type)" : ''; $this->nameReferrerAnalyzed = self::LABEL_ADWORDS_NAME . $type; @@ -304,7 +304,7 @@ abstract class Base extends VisitDimension return false; } // if we detected a campaign but there is still no keyword set, we set the keyword to the Referrer host - if(empty($this->keywordReferrerAnalyzed)) { + if (empty($this->keywordReferrerAnalyzed)) { $this->keywordReferrerAnalyzed = $this->referrerHost; } diff --git a/plugins/Referrers/Controller.php b/plugins/Referrers/Controller.php index e683cb7f9e..f01c61f647 100644 --- a/plugins/Referrers/Controller.php +++ b/plugins/Referrers/Controller.php @@ -332,7 +332,7 @@ function DisplayTopKeywords($url = "") $url = empty($url) ? "http://". $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] : $url; $api = "' . $api . '&url=" . urlencode($url); $keywords = @unserialize(file_get_contents($api)); - if($keywords === false || isset($keywords["result"])) { + if ($keywords === false || isset($keywords["result"])) { // DEBUG ONLY: uncomment for troubleshooting an empty output (the URL output reveals the token_auth) // echo "Error while fetching the <a href=\'$api\'>Top Keywords from Piwik</a>"; return; @@ -344,7 +344,7 @@ function DisplayTopKeywords($url = "") foreach($keywords as $keyword) { $output .= "<li>". $keyword . "</li>"; } - if(empty($keywords)) { $output .= "Nothing yet..."; } + if (empty($keywords)) { $output .= "Nothing yet..."; } $output .= "</ul>"; echo $output; } diff --git a/plugins/Referrers/functions.php b/plugins/Referrers/functions.php index 8f7a4023df..e0fee30833 100644 --- a/plugins/Referrers/functions.php +++ b/plugins/Referrers/functions.php @@ -39,7 +39,7 @@ function getSocialMainUrl($url) $social = getSocialNetworkFromDomain($url); foreach (Common::getSocialUrls() as $domain => $name) { - if($name == $social) { + if ($name == $social) { return $domain; } @@ -57,7 +57,7 @@ function getSocialNetworkFromDomain($url) { foreach (Common::getSocialUrls() as $domain => $name) { - if(preg_match('/(^|[\.\/])'.$domain.'([\.\/]|$)/', $url)) { + if (preg_match('/(^|[\.\/])'.$domain.'([\.\/]|$)/', $url)) { return $name; } diff --git a/plugins/ScheduledReports/API.php b/plugins/ScheduledReports/API.php index 3ea8a05c28..a42b5bb209 100644 --- a/plugins/ScheduledReports/API.php +++ b/plugins/ScheduledReports/API.php @@ -53,6 +53,9 @@ class API extends \Piwik\Plugin\API const REPORT_TRUNCATE = 23; + // static cache storing reports + public static $cache = array(); + /** * Creates a new report and schedules it. * @@ -84,29 +87,20 @@ class API extends \Piwik\Plugin\API // validation of requested reports $reports = self::validateRequestedReports($idSite, $reportType, $reports); - $db = Db::get(); - $idReport = $db->fetchOne("SELECT max(idreport) + 1 FROM " . Common::prefixTable('report')); - - if ($idReport == false) { - $idReport = 1; - } - - $db->insert(Common::prefixTable('report'), - array( - 'idreport' => $idReport, - 'idsite' => $idSite, - 'login' => $currentUser, - 'description' => $description, - 'idsegment' => $idSegment, - 'period' => $period, - 'hour' => $hour, - 'type' => $reportType, - 'format' => $reportFormat, - 'parameters' => $parameters, - 'reports' => $reports, - 'ts_created' => Date::now()->getDatetime(), - 'deleted' => 0, - )); + $idReport = $this->getModel()->createReport(array( + 'idsite' => $idSite, + 'login' => $currentUser, + 'description' => $description, + 'idsegment' => $idSegment, + 'period' => $period, + 'hour' => $hour, + 'type' => $reportType, + 'format' => $reportFormat, + 'parameters' => $parameters, + 'reports' => $reports, + 'ts_created' => Date::now()->getDatetime(), + 'deleted' => 0, + )); return $idReport; } @@ -130,7 +124,7 @@ class API extends \Piwik\Plugin\API Piwik::checkUserHasViewAccess($idSite); $scheduledReports = $this->getReports($idSite, $periodSearch = false, $idReport); - $report = reset($scheduledReports); + $report = reset($scheduledReports); $idReport = $report['idreport']; $currentUser = Piwik::getCurrentUserLogin(); @@ -144,19 +138,16 @@ class API extends \Piwik\Plugin\API // validation of requested reports $reports = self::validateRequestedReports($idSite, $reportType, $reports); - Db::get()->update(Common::prefixTable('report'), - array( - 'description' => $description, - 'idsegment' => $idSegment, - 'period' => $period, - 'hour' => $hour, - 'type' => $reportType, - 'format' => $reportFormat, - 'parameters' => $parameters, - 'reports' => $reports, - ), - "idreport = '$idReport'" - ); + $this->getModel()->updateReport($idReport, array( + 'description' => $description, + 'idsegment' => $idSegment, + 'period' => $period, + 'hour' => $hour, + 'type' => $reportType, + 'format' => $reportFormat, + 'parameters' => $parameters, + 'reports' => $reports, + )); self::$cache = array(); } @@ -172,18 +163,13 @@ class API extends \Piwik\Plugin\API $report = reset($APIScheduledReports); Piwik::checkUserHasSuperUserAccessOrIsTheUser($report['login']); - Db::get()->update(Common::prefixTable('report'), - array( - 'deleted' => 1, - ), - "idreport = '$idReport'" - ); + $this->getModel()->updateReport($idReport, array( + 'deleted' => 1, + )); + self::$cache = array(); } - // static cache storing reports - public static $cache = array(); - /** * Returns the list of reports matching the passed parameters * @@ -198,6 +184,7 @@ class API extends \Piwik\Plugin\API public function getReports($idSite = false, $period = false, $idReport = false, $ifSuperUserReturnOnlySuperUserReports = false, $idSegment = false) { Piwik::checkUserHasSomeViewAccess(); + $cacheKey = (int)$idSite . '.' . (string)$period . '.' . (int)$idReport . '.' . (int)$ifSuperUserReturnOnlySuperUserReports; if (isset(self::$cache[$cacheKey])) { return self::$cache[$cacheKey]; @@ -427,7 +414,7 @@ class API extends \Piwik\Plugin\API array(&$reportRenderer, $reportType, $outputType, $report) ); - if(is_null($reportRenderer)) { + if (is_null($reportRenderer)) { throw new Exception("A report renderer was not supplied in the event " . self::GET_RENDERER_INSTANCE_EVENT); } @@ -556,10 +543,8 @@ class API extends \Piwik\Plugin\API ); // Update flag in DB - Db::get()->update(Common::prefixTable('report'), - array('ts_last_sent' => Date::now()->getDatetime()), - "idreport = " . $report['idreport'] - ); + $now = Date::now()->getDatetime(); + $this->getModel()->updateReport($report['idreport'], array('ts_last_sent' => $now)); // If running from piwik.php with debug, do not delete the PDF after sending the email if (!isset($GLOBALS['PIWIK_TRACKER_DEBUG']) || !$GLOBALS['PIWIK_TRACKER_DEBUG']) { @@ -567,6 +552,11 @@ class API extends \Piwik\Plugin\API } } + private function getModel() + { + return new Model(); + } + private static function getReportSubjectAndReportTitle($websiteName, $reports) { // if the only report is "All websites", we don't display the site name diff --git a/plugins/ScheduledReports/Model.php b/plugins/ScheduledReports/Model.php new file mode 100644 index 0000000000..01507f65f9 --- /dev/null +++ b/plugins/ScheduledReports/Model.php @@ -0,0 +1,93 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik\Plugins\ScheduledReports; + +use Piwik\Common; +use Piwik\Db; +use Piwik\DbHelper; +use Piwik\ReportRenderer; +use Piwik\Translate; + +class Model +{ + private static $rawPrefix = 'report'; + private $table; + + public function __construct() + { + $this->table = Common::prefixTable(self::$rawPrefix); + } + + public function deleteUserReportForSite($userLogin, $idSite) + { + $query = 'DELETE FROM ' . $this->table . ' WHERE login = ? and idsite = ?'; + $bind = array($userLogin, $idSite); + Db::query($query, $bind); + } + + public function deleteAllReportForUser($userLogin) + { + Db::query('DELETE FROM ' . $this->table . ' WHERE login = ?', $userLogin); + } + + public function updateReport($idReport, $report) + { + $idReport = (int) $idReport; + + $this->getDb()->update($this->table, $report, "idreport = " . $idReport); + } + + public function createReport($report) + { + $nextId = $this->getNextReportId(); + $report['idreport'] = $nextId; + + $this->getDb()->insert($this->table, $report); + + return $nextId; + } + + private function getNextReportId() + { + $db = $this->getDb(); + $idReport = $db->fetchOne("SELECT max(idreport) + 1 FROM " . $this->table); + + if ($idReport == false) { + $idReport = 1; + } + + return $idReport; + } + + private function getDb() + { + return Db::get(); + } + + public static function install() + { + $reportTable = "`idreport` INT(11) NOT NULL AUTO_INCREMENT, + `idsite` INTEGER(11) NOT NULL, + `login` VARCHAR(100) NOT NULL, + `description` VARCHAR(255) NOT NULL, + `idsegment` INT(11), + `period` VARCHAR(10) NOT NULL, + `hour` tinyint NOT NULL default 0, + `type` VARCHAR(10) NOT NULL, + `format` VARCHAR(10) NOT NULL, + `reports` TEXT NOT NULL, + `parameters` TEXT NULL, + `ts_created` TIMESTAMP NULL, + `ts_last_sent` TIMESTAMP NULL, + `deleted` tinyint(4) NOT NULL default 0, + PRIMARY KEY (`idreport`)"; + + DbHelper::createTable(self::$rawPrefix, $reportTable); + } +} diff --git a/plugins/ScheduledReports/ScheduledReports.php b/plugins/ScheduledReports/ScheduledReports.php index ca5ebb9b41..e59e9140ab 100644 --- a/plugins/ScheduledReports/ScheduledReports.php +++ b/plugins/ScheduledReports/ScheduledReports.php @@ -9,9 +9,7 @@ namespace Piwik\Plugins\ScheduledReports; use Exception; -use Piwik\Common; use Piwik\Db; -use Piwik\DbHelper; use Piwik\Mail; use Piwik\Piwik; use Piwik\Plugins\MobileMessaging\MobileMessaging; @@ -469,27 +467,27 @@ class ScheduledReports extends \Piwik\Plugin $reportsNeedSegment = array(); - if(!$updatedSegment['enable_all_users']) { + if (!$updatedSegment['enable_all_users']) { // which reports would become invisible to other users? foreach($reportsUsingSegment as $report) { - if($report['login'] == Piwik::getCurrentUserLogin()) { + if ($report['login'] == Piwik::getCurrentUserLogin()) { continue; } $reportsNeedSegment[] = $report; } } - if($updatedSegment['enable_only_idsite']) { + if ($updatedSegment['enable_only_idsite']) { // which reports from other websites are set to use this segment restricted to one website? foreach($reportsUsingSegment as $report) { - if($report['idsite'] == $updatedSegment['enable_only_idsite']) { + if ($report['idsite'] == $updatedSegment['enable_only_idsite']) { continue; } $reportsNeedSegment[] = $report; } } - if(empty($reportsNeedSegment)) { + if (empty($reportsNeedSegment)) { return; } @@ -526,7 +524,7 @@ class ScheduledReports extends \Piwik\Plugin public function deleteUserReport($userLogin) { - Db::query('DELETE FROM ' . Common::prefixTable('report') . ' WHERE login = ?', $userLogin); + $this->getModel()->deleteAllReportForUser($userLogin); } public function deleteUserReportForSites($userLogin, $idSites) @@ -535,33 +533,21 @@ class ScheduledReports extends \Piwik\Plugin return; } - $table = Common::prefixTable('report'); + $model = $this->getModel(); foreach ($idSites as $idSite) { - Db::query('DELETE FROM ' . $table . ' WHERE login = ? and idsite = ?', - array($userLogin, $idSite)); + $model->deleteUserReportForSite($userLogin, $idSite); } } + private function getModel() + { + return new Model(); + } + public function install() { - $reportTable = "`idreport` INT(11) NOT NULL AUTO_INCREMENT, - `idsite` INTEGER(11) NOT NULL, - `login` VARCHAR(100) NOT NULL, - `description` VARCHAR(255) NOT NULL, - `idsegment` INT(11), - `period` VARCHAR(10) NOT NULL, - `hour` tinyint NOT NULL default 0, - `type` VARCHAR(10) NOT NULL, - `format` VARCHAR(10) NOT NULL, - `reports` TEXT NOT NULL, - `parameters` TEXT NULL, - `ts_created` TIMESTAMP NULL, - `ts_last_sent` TIMESTAMP NULL, - `deleted` tinyint(4) NOT NULL default 0, - PRIMARY KEY (`idreport`)"; - - DbHelper::createTable('report', $reportTable); + Model::install(); } private static function checkAdditionalEmails($additionalEmails) diff --git a/plugins/SegmentEditor/API.php b/plugins/SegmentEditor/API.php index 98b752cc2a..699ad3a4ea 100644 --- a/plugins/SegmentEditor/API.php +++ b/plugins/SegmentEditor/API.php @@ -103,6 +103,7 @@ class API extends \Piwik\Plugin\API if (empty($segment)) { throw new Exception("Requested segment not found"); } + return $segment; } @@ -128,7 +129,7 @@ class API extends \Piwik\Plugin\API public function isUserCanAddNewSegment($idSite) { - if(Piwik::isUserIsAnonymous()) { + if (Piwik::isUserIsAnonymous()) { return false; } @@ -145,13 +146,13 @@ class API extends \Piwik\Plugin\API protected function checkUserCanEditOrDeleteSegment($segment) { - if(Piwik::hasUserSuperUserAccess()) { + if (Piwik::hasUserSuperUserAccess()) { return; } $this->checkUserIsNotAnonymous(); - if($segment['login'] != Piwik::getCurrentUserLogin()) { + if ($segment['login'] != Piwik::getCurrentUserLogin()) { throw new Exception($this->getMessageCannotEditSegmentCreatedBySuperUser()); } } @@ -177,11 +178,16 @@ class API extends \Piwik\Plugin\API */ Piwik::postEvent('SegmentEditor.deactivate', array($idSegment)); - $db = Db::get(); - $db->delete(Common::prefixTable('segment'), 'idsegment = ' . $idSegment); + $this->getModel()->deleteSegment($idSegment); + return true; } + private function getModel() + { + return new Model(); + } + /** * Modifies an existing stored segment. * @@ -201,9 +207,9 @@ class API extends \Piwik\Plugin\API $idSite = $this->checkIdSite($idSite); $this->checkSegmentName($name); - $definition = $this->checkSegmentValue($definition, $idSite); + $definition = $this->checkSegmentValue($definition, $idSite); $enabledAllUsers = $this->checkEnabledAllUsers($enabledAllUsers); - $autoArchive = $this->checkAutoArchive($autoArchive, $idSite); + $autoArchive = $this->checkAutoArchive($autoArchive, $idSite); $bind = array( 'name' => $name, @@ -224,11 +230,8 @@ class API extends \Piwik\Plugin\API */ Piwik::postEvent('SegmentEditor.update', array($idSegment, $bind)); - $db = Db::get(); - $db->update(Common::prefixTable("segment"), - $bind, - "idsegment = $idSegment" - ); + $this->getModel()->updateSegment($idSegment, $bind); + return true; } @@ -252,7 +255,6 @@ class API extends \Piwik\Plugin\API $enabledAllUsers = $this->checkEnabledAllUsers($enabledAllUsers); $autoArchive = $this->checkAutoArchive($autoArchive, $idSite); - $db = Db::get(); $bind = array( 'name' => $name, 'definition' => $definition, @@ -263,8 +265,10 @@ class API extends \Piwik\Plugin\API 'ts_created' => Date::now()->getDatetime(), 'deleted' => 0, ); - $db->insert(Common::prefixTable("segment"), $bind); - return $db->lastInsertId(); + + $id = $this->getModel()->createSegment($bind); + + return $id; } /** @@ -277,12 +281,12 @@ class API extends \Piwik\Plugin\API public function get($idSegment) { Piwik::checkUserHasSomeViewAccess(); + if (!is_numeric($idSegment)) { throw new Exception("idSegment should be numeric."); } - $segment = Db::get()->fetchRow("SELECT * " . - " FROM " . Common::prefixTable("segment") . - " WHERE idsegment = ?", $idSegment); + + $segment = $this->getModel()->getSegment($idSegment); if (empty($segment)) { return false; @@ -300,6 +304,7 @@ class API extends \Piwik\Plugin\API if ($segment['deleted']) { throw new Exception("This segment is marked as deleted. "); } + return $segment; } @@ -319,7 +324,7 @@ class API extends \Piwik\Plugin\API $userLogin = Piwik::getCurrentUserLogin(); - $model = new Model(); + $model = $this->getModel(); if (empty($idSite)) { $segments = $model->getAllSegments($userLogin); } else { diff --git a/plugins/SegmentEditor/Model.php b/plugins/SegmentEditor/Model.php index 54c0e07ddf..8bfcc957ae 100644 --- a/plugins/SegmentEditor/Model.php +++ b/plugins/SegmentEditor/Model.php @@ -10,12 +10,21 @@ namespace Piwik\Plugins\SegmentEditor; use Piwik\Common; use Piwik\Db; +use Piwik\DbHelper; /** * The SegmentEditor Model lets you persist and read custom Segments from the backend without handling any logic. */ class Model { + private static $rawPrefix = 'segment'; + private $table; + + public function __construct() + { + $this->table = Common::prefixTable(self::$rawPrefix); + } + /** * Returns all stored segments. * @@ -36,7 +45,7 @@ class Model $sql = $this->buildQuerySortedByName("($whereIdSite enable_only_idsite = 0) AND deleted = 0 AND auto_archive = 1"); - $segments = Db::get()->fetchAll($sql, $bind); + $segments = $this->getDb()->fetchAll($sql, $bind); return $segments; } @@ -52,7 +61,7 @@ class Model $bind = array($userLogin); $sql = $this->buildQuerySortedByName('deleted = 0 AND (enable_all_users = 1 OR login = ?)'); - $segments = Db::get()->fetchAll($sql, $bind); + $segments = $this->getDb()->fetchAll($sql, $bind); return $segments; } @@ -70,16 +79,69 @@ class Model $sql = $this->buildQuerySortedByName('(enable_only_idsite = ? OR enable_only_idsite = 0) AND deleted = 0 AND (enable_all_users = 1 OR login = ?)'); - $segments = Db::get()->fetchAll($sql, $bind); + $segments = $this->getDb()->fetchAll($sql, $bind); return $segments; } + public function deleteSegment($idSegment) + { + $db = $this->getDb(); + $db->delete($this->table, 'idsegment = ' . (int) $idSegment); + } + + public function updateSegment($idSegment, $segment) + { + $idSegment = (int) $idSegment; + + $db = $this->getDb(); + $db->update($this->table, $segment, "idsegment = $idSegment"); + + return true; + } + + public function createSegment($segment) + { + $db = $this->getDb(); + $db->insert($this->table, $segment); + $id = $db->lastInsertId(); + + return $id; + } + + public function getSegment($idSegment) + { + $db = $this->getDb(); + $segment = $db->fetchRow("SELECT * FROM " . $this->table . " WHERE idsegment = ?", $idSegment); + + return $segment; + } + + private function getDb() + { + return Db::get(); + } + private function buildQuerySortedByName($where) { - $sql = "SELECT * FROM " . Common::prefixTable("segment") . - " WHERE $where ORDER BY name ASC"; + return "SELECT * FROM " . $this->table . " WHERE $where ORDER BY name ASC"; + } + + public static function install() + { + $segmentTable = "`idsegment` INT(11) NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `definition` TEXT NOT NULL, + `login` VARCHAR(100) NOT NULL, + `enable_all_users` tinyint(4) NOT NULL default 0, + `enable_only_idsite` INTEGER(11) NULL, + `auto_archive` tinyint(4) NOT NULL default 0, + `ts_created` TIMESTAMP NULL, + `ts_last_edit` TIMESTAMP NULL, + `deleted` tinyint(4) NOT NULL default 0, + PRIMARY KEY (`idsegment`)"; - return $sql; + DbHelper::createTable(self::$rawPrefix, $segmentTable); } + } diff --git a/plugins/SegmentEditor/SegmentEditor.php b/plugins/SegmentEditor/SegmentEditor.php index bd957c54c0..aef619156d 100644 --- a/plugins/SegmentEditor/SegmentEditor.php +++ b/plugins/SegmentEditor/SegmentEditor.php @@ -67,27 +67,17 @@ class SegmentEditor extends \Piwik\Plugin { $model = new Model(); $segmentToAutoArchive = $model->getSegmentsToAutoArchive($idSite); + foreach ($segmentToAutoArchive as $segmentInfo) { $segments[] = $segmentInfo['definition']; } + $segments = array_unique($segments); } public function install() { - $segmentTable = "`idsegment` INT(11) NOT NULL AUTO_INCREMENT, - `name` VARCHAR(255) NOT NULL, - `definition` TEXT NOT NULL, - `login` VARCHAR(100) NOT NULL, - `enable_all_users` tinyint(4) NOT NULL default 0, - `enable_only_idsite` INTEGER(11) NULL, - `auto_archive` tinyint(4) NOT NULL default 0, - `ts_created` TIMESTAMP NULL, - `ts_last_edit` TIMESTAMP NULL, - `deleted` tinyint(4) NOT NULL default 0, - PRIMARY KEY (`idsegment`)"; - - DbHelper::createTable('segment', $segmentTable); + Model::install(); } public function getJsFiles(&$jsFiles) diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php index 5b856cd862..0d8a85c11c 100644 --- a/plugins/SitesManager/API.php +++ b/plugins/SitesManager/API.php @@ -143,11 +143,9 @@ class API extends \Piwik\Plugin\API public function getSitesFromGroup($group) { Piwik::checkUserHasSuperUserAccess(); - $group = trim($group); - $sites = Db::get()->fetchAll("SELECT * - FROM " . Common::prefixTable("site") . " - WHERE `group` = ?", $group); + $group = trim($group); + $sites = $this->getModel()->getSitesFromGroup($group); Site::setSitesFromArray($sites); return $sites; @@ -162,12 +160,10 @@ class API extends \Piwik\Plugin\API public function getSitesGroups() { Piwik::checkUserHasSuperUserAccess(); - $groups = Db::get()->fetchAll("SELECT DISTINCT `group` FROM " . Common::prefixTable("site")); - $cleanedGroups = array(); - foreach ($groups as $group) { - $cleanedGroups[] = $group['group']; - } - $cleanedGroups = array_map('trim', $cleanedGroups); + + $groups = $this->getModel()->getSitesGroups(); + $cleanedGroups = array_map('trim', $groups); + return $cleanedGroups; } @@ -219,12 +215,15 @@ class API extends \Piwik\Plugin\API public function getAllSites() { Piwik::checkUserHasSuperUserAccess(); - $sites = Db::get()->fetchAll("SELECT * FROM " . Common::prefixTable("site") . " ORDER BY idsite ASC"); + + $sites = $this->getModel()->getAllSites(); $return = array(); foreach ($sites as $site) { $return[$site['idsite']] = $site; } + Site::setSitesFromArray($return); + return $return; } @@ -258,24 +257,16 @@ class API extends \Piwik\Plugin\API if (empty($timestamp)) $timestamp = time(); - $time = Date::factory((int)$timestamp)->getDatetime(); - $result = Db::fetchAll(" - SELECT - idsite - FROM - " . Common::prefixTable('site') . " s - WHERE EXISTS ( - SELECT 1 - FROM " . Common::prefixTable('log_visit') . " v - WHERE v.idsite = s.idsite - AND visit_last_action_time > ? - AND visit_last_action_time <= ? - LIMIT 1) - ", array($time, $now = Date::now()->addHour(1)->getDatetime())); + $time = Date::factory((int)$timestamp)->getDatetime(); + $now = Date::now()->addHour(1)->getDatetime(); + + $result = $this->getModel()->getSitesWithVisits($time, $now); + $idSites = array(); foreach ($result as $idSite) { $idSites[] = $idSite['idsite']; } + return $idSites; } @@ -291,9 +282,11 @@ class API extends \Piwik\Plugin\API $sitesId = $this->getSitesIdWithAdminAccess(); $sites = $this->getSitesFromIds($sitesId); - if ($fetchAliasUrls) - foreach ($sites as &$site) + if ($fetchAliasUrls) { + foreach ($sites as &$site) { $site['alias_urls'] = API::getInstance()->getSiteUrlsFromId($site['idsite']); + } + } return $sites; } @@ -373,10 +366,12 @@ class API extends \Piwik\Plugin\API } $accessRaw = Access::getInstance()->getRawSitesWithSomeViewAccess($_restrictSitesToLogin); - $sitesId = array(); + $sitesId = array(); + foreach ($accessRaw as $access) { $sitesId[] = $access['idsite']; } + return $sitesId; } else { return Access::getInstance()->getSitesIdWithAtLeastViewAccess(); @@ -407,6 +402,7 @@ class API extends \Piwik\Plugin\API } else { $urlBis = str_replace('://', '://www.', $url); } + return array($url, $urlBis); } @@ -420,28 +416,12 @@ class API extends \Piwik\Plugin\API { $url = $this->removeTrailingSlash($url); list($url, $urlBis) = $this->getNormalizedUrls($url); + if (Piwik::hasUserSuperUserAccess()) { - $ids = Db::get()->fetchAll( - 'SELECT idsite - FROM ' . Common::prefixTable('site') . ' - WHERE (main_url = ? OR main_url = ?) ' . - 'UNION - SELECT idsite - FROM ' . Common::prefixTable('site_url') . ' - WHERE (url = ? OR url = ?) ', array($url, $urlBis, $url, $urlBis)); + $ids = $this->getModel()->getAllSitesIdFromSiteUrl($url, $urlBis); } else { $login = Piwik::getCurrentUserLogin(); - $ids = Db::get()->fetchAll( - 'SELECT idsite - FROM ' . Common::prefixTable('site') . ' - WHERE (main_url = ? OR main_url = ?)' . - 'AND idsite IN (' . Access::getSqlAccessSite('idsite') . ') ' . - 'UNION - SELECT idsite - FROM ' . Common::prefixTable('site_url') . ' - WHERE (url = ? OR url = ?)' . - 'AND idsite IN (' . Access::getSqlAccessSite('idsite') . ')', - array($url, $urlBis, $login, $url, $urlBis, $login)); + $ids = $this->getModel()->getSitesIdFromSiteUrlHavingAccess($url, $urlBis, $login); } return $ids; @@ -457,18 +437,17 @@ class API extends \Piwik\Plugin\API public function getSitesIdFromTimezones($timezones) { Piwik::checkUserHasSuperUserAccess(); + $timezones = Piwik::getArrayFromApiParameter($timezones); $timezones = array_unique($timezones); - $ids = Db::get()->fetchAll( - 'SELECT idsite - FROM ' . Common::prefixTable('site') . ' - WHERE timezone IN (' . Common::getSqlStringFieldsArray($timezones) . ') - ORDER BY idsite ASC', - $timezones); + + $ids = $this->getModel()->getSitesFromTimezones($timezones); + $return = array(); foreach ($ids as $id) { $return[] = $id['idsite']; } + return $return; } @@ -540,7 +519,7 @@ class API extends \Piwik\Plugin\API $db = Db::get(); - $url = $urls[0]; + $url = $urls[0]; $urls = array_slice($urls, 1); $bind = array('name' => $siteName, @@ -619,16 +598,7 @@ class API extends \Piwik\Plugin\API throw new Exception(Piwik::translate("SitesManager_ExceptionDeleteSite")); } - $db = Db::get(); - - $db->query("DELETE FROM " . Common::prefixTable("site") . " - WHERE idsite = ?", $idSite); - - $db->query("DELETE FROM " . Common::prefixTable("site_url") . " - WHERE idsite = ?", $idSite); - - $db->query("DELETE FROM " . Common::prefixTable("access") . " - WHERE idsite = ?", $idSite); + $this->getModel()->deleteSite($idSite); // we do not delete logs here on purpose (you can run these queries on the log_ tables to delete all data) Cache::deleteCacheWebsiteAttributes($idSite); @@ -682,12 +652,14 @@ class API extends \Piwik\Plugin\API private function checkAndReturnType($type) { - if(empty($type)) { + if (empty($type)) { $type = Site::DEFAULT_SITE_TYPE; } - if(!is_string($type)) { + + if (!is_string($type)) { throw new Exception("Invalid website type $type"); } + return $type; } @@ -704,14 +676,17 @@ class API extends \Piwik\Plugin\API if (empty($excludedIps)) { return ''; } + $ips = explode(',', $excludedIps); $ips = array_map('trim', $ips); $ips = array_filter($ips, 'strlen'); + foreach ($ips as $ip) { if (!$this->isValidIp($ip)) { throw new Exception(Piwik::translate('SitesManager_ExceptionInvalidIPFormat', array($ip, "1.2.3.4, 1.2.3.*, or 1.2.3.4/5"))); } } + $ips = implode(',', $ips); return $ips; } @@ -756,7 +731,7 @@ class API extends \Piwik\Plugin\API $urls = $this->cleanParameterUrls($urls); $this->checkUrls($urls); - $this->deleteSiteAliasUrls($idSite); + $this->getModel()->deleteSiteAliasUrls($idSite); $this->insertSiteUrls($idSite, $urls); $this->postUpdateWebsite($idSite); @@ -1131,17 +1106,15 @@ class API extends \Piwik\Plugin\API $bind['sitesearch_category_parameters'] = $searchCategoryParameters; $bind['type'] = $this->checkAndReturnType($type); - $db = Db::get(); - $db->update(Common::prefixTable("site"), - $bind, - "idsite = $idSite" - ); + $this->getModel()->updateSite($bind, $idSite); // we now update the main + alias URLs - $this->deleteSiteAliasUrls($idSite); + $this->getModel()->deleteSiteAliasUrls($idSite); + if (count($urls) > 1) { $this->addSiteAliasUrls($idSite, array_slice($urls, 1)); } + $this->postUpdateWebsite($idSite); } @@ -1158,14 +1131,9 @@ class API extends \Piwik\Plugin\API $idSites = Site::getIdSitesFromIdSitesString($idSites); Piwik::checkUserHasAdminAccess($idSites); - // Update piwik_site.ts_created - $query = "UPDATE " . Common::prefixTable("site") . - " SET ts_created = ?" . - " WHERE idsite IN ( " . implode(",", $idSites) . " ) - AND ts_created > ?"; $minDateSql = $minDate->subDay(1)->getDatetime(); - $bind = array($minDateSql, $minDateSql); - Db::query($query, $bind); + + $this->getModel()->updateSiteCreatedTime($idSites, $minDateSql); } private function checkAndReturnCommaSeparatedStringList($parameters) @@ -1296,12 +1264,8 @@ class API extends \Piwik\Plugin\API public function getUniqueSiteTimezones() { Piwik::checkUserHasSuperUserAccess(); - $results = Db::fetchAll("SELECT distinct timezone FROM " . Common::prefixTable('site')); - $timezones = array(); - foreach ($results as $result) { - $timezones[] = $result['timezone']; - } - return $timezones; + + return $this->getModel()->getUniqueSiteTimezones(); } /** @@ -1311,14 +1275,9 @@ class API extends \Piwik\Plugin\API private function insertSiteUrls($idSite, $urls) { if (count($urls) != 0) { - $db = Db::get(); foreach ($urls as $url) { try { - $db->insert(Common::prefixTable("site_url"), array( - 'idsite' => $idSite, - 'url' => $url - ) - ); + $this->getModel()->insertSiteUrl($idSite, $url); } catch(Exception $e) { // See bug #4149 } @@ -1327,16 +1286,6 @@ class API extends \Piwik\Plugin\API } /** - * Delete all the alias URLs for the given idSite. - */ - private function deleteSiteAliasUrls($idsite) - { - $db = Db::get(); - $db->query("DELETE FROM " . Common::prefixTable("site_url") . " - WHERE idsite = ?", $idsite); - } - - /** * Remove the final slash in the URLs if found * * @param string $url @@ -1350,6 +1299,7 @@ class API extends \Piwik\Plugin\API ) { $url = substr($url, 0, strlen($url) - 1); } + return $url; } @@ -1404,6 +1354,7 @@ class API extends \Piwik\Plugin\API if (empty($searchKeywordParameters)) { $searchKeywordParameters = ''; } + if (empty($searchCategoryParameters)) { $searchCategoryParameters = ''; } @@ -1439,9 +1390,10 @@ class API extends \Piwik\Plugin\API if (!is_array($urls)) { $urls = array($urls); } - $urls = array_filter($urls); + $urls = array_filter($urls); $urls = array_map('urldecode', $urls); + foreach ($urls as &$url) { $url = $this->removeTrailingSlash($url); if (strpos($url, 'http') !== 0) { @@ -1450,6 +1402,7 @@ class API extends \Piwik\Plugin\API $url = trim($url); $url = Common::sanitizeInputValue($url); } + $urls = array_unique($urls); return $urls; } @@ -1489,30 +1442,9 @@ class API extends \Piwik\Plugin\API return array(); } - $ids_str = ''; - foreach ($ids as $id_val) { - $ids_str .= $id_val . ' , '; - } - $ids_str .= $id_val; - - $db = Db::get(); - $bind = array('%' . $pattern . '%', 'http%' . $pattern . '%', '%' . $pattern . '%'); + $limit = SettingsPiwik::getWebsitesCountToDisplay(); + $sites = $this->getModel()->getPatternMatchSites($ids, $pattern, $limit); - // Also match the idsite - $where = ''; - if (is_numeric($pattern)) { - $bind[] = $pattern; - $where = 'OR s.idsite = ?'; - } - $sites = $db->fetchAll("SELECT idsite, name, main_url, `group` - FROM " . Common::prefixTable('site') . " s - WHERE ( s.name like ? - OR s.main_url like ? - OR s.`group` like ? - $where ) - AND idsite in ($ids_str) - LIMIT " . SettingsPiwik::getWebsitesCountToDisplay(), - $bind); return $sites; } diff --git a/plugins/SitesManager/Model.php b/plugins/SitesManager/Model.php index 207f59bdfd..7aa779b530 100644 --- a/plugins/SitesManager/Model.php +++ b/plugins/SitesManager/Model.php @@ -8,13 +8,162 @@ */ namespace Piwik\Plugins\SitesManager; +use Piwik\Access; +use Piwik\Date; use Piwik\Db; use Piwik\Common; use Exception; -use Piwik\Site; class Model { + private static $rawPrefix = 'site'; + private $table; + + public function __construct() + { + $this->table = Common::prefixTable(self::$rawPrefix); + } + + /** + * Returns all websites belonging to the specified group + * @param string $group Group name + * @return array of sites + */ + public function getSitesFromGroup($group) + { + $sites = $this->getDb()->fetchAll("SELECT * FROM " . $this->table . " + WHERE `group` = ?", $group); + + return $sites; + } + + /** + * Returns the list of website groups, including the empty group + * if no group were specified for some websites + * + * @return array of group names strings + */ + public function getSitesGroups() + { + $groups = $this->getDb()->fetchAll("SELECT DISTINCT `group` FROM " . $this->table); + + $cleanedGroups = array(); + foreach ($groups as $group) { + $cleanedGroups[] = $group['group']; + } + + return $cleanedGroups; + } + + /** + * Returns all websites + * + * @return array The list of websites, indexed by idsite + */ + public function getAllSites() + { + $sites = $this->getDb()->fetchAll("SELECT * FROM " . $this->table . " ORDER BY idsite ASC"); + + return $sites; + } + + /** + * Returns the list of the website IDs that received some visits since the specified timestamp. + * + * @param \Piwik\Date $time + * @param \Piwik\Date $now + * @return array The list of website IDs + */ + public function getSitesWithVisits($time, $now) + { + $sites = Db::fetchAll(" + SELECT idsite FROM " . $this->table . " s + WHERE EXISTS ( + SELECT 1 + FROM " . Common::prefixTable('log_visit') . " v + WHERE v.idsite = s.idsite + AND visit_last_action_time > ? + AND visit_last_action_time <= ? + LIMIT 1) + ", array($time, $now)); + + return $sites; + } + + + /** + * Returns the list of websites ID associated with a URL. + * + * @param string $url + * @param string $urlBis + * @return array list of websites ID + */ + public function getAllSitesIdFromSiteUrl($url, $urlBis) + { + $siteUrlTable = Common::prefixTable('site_url'); + + $ids = $this->getDb()->fetchAll( + 'SELECT idsite FROM ' . $this->table . ' + WHERE (main_url = ? OR main_url = ?) ' . + 'UNION + SELECT idsite FROM ' . $siteUrlTable . ' + WHERE (url = ? OR url = ?) ', array($url, $urlBis, $url, $urlBis)); + + return $ids; + } + + /** + * Returns the list of websites ID associated with a URL. + * + * @param string $url + * @return array list of websites ID + */ + public function getSitesIdFromSiteUrlHavingAccess($url, $urlBis, $login) + { + $siteUrlTable = Common::prefixTable('site_url'); + $sqlAccessSite = Access::getSqlAccessSite('idsite'); + + $ids = $this->getDb()->fetchAll( + 'SELECT idsite + FROM ' . $this->table . ' + WHERE (main_url = ? OR main_url = ?)' . + 'AND idsite IN (' . $sqlAccessSite . ') ' . + 'UNION + SELECT idsite + FROM ' . $siteUrlTable . ' + WHERE (url = ? OR url = ?)' . + 'AND idsite IN (' . $sqlAccessSite . ')', + array($url, $urlBis, $login, $url, $urlBis, $login)); + + return $ids; + } + + /** + * Returns all websites with a timezone matching one the specified timezones + * + * @param array $timezones + * @return array + * @ignore + */ + public function getSitesFromTimezones($timezones) + { + $query = 'SELECT idsite FROM ' . $this->table . ' + WHERE timezone IN (' . Common::getSqlStringFieldsArray($timezones) . ') + ORDER BY idsite ASC'; + $sites = $this->getDb()->fetchAll($query, $timezones); + + return $sites; + } + + public function deleteSite($idSite) + { + $db = $this->getDb(); + + $db->query("DELETE FROM " . $this->table . " WHERE idsite = ?", $idSite); + $db->query("DELETE FROM " . Common::prefixTable("site_url") . " WHERE idsite = ?", $idSite); + $db->query("DELETE FROM " . Common::prefixTable("access") . " WHERE idsite = ?", $idSite); + } + /** * Returns the list of websites from the ID array in parameters. * @@ -36,11 +185,10 @@ class Model $idSites = array_map('intval', $idSites); - $db = Db::get(); - $sites = $db->fetchAll("SELECT * - FROM " . Common::prefixTable("site") . " - WHERE idsite IN (" . implode(", ", $idSites) . ") - ORDER BY idsite ASC $limit"); + $db = $this->getDb(); + $sites = $db->fetchAll("SELECT * FROM " . $this->table . " + WHERE idsite IN (" . implode(", ", $idSites) . ") + ORDER BY idsite ASC $limit"); return $sites; } @@ -54,9 +202,8 @@ class Model */ public function getSiteFromId($idSite) { - $site = Db::get()->fetchRow("SELECT * - FROM " . Common::prefixTable("site") . " - WHERE idsite = ?", $idSite); + $site = Db::get()->fetchRow("SELECT * FROM " . $this->table . " + WHERE idsite = ?", $idSite); return $site; } @@ -69,11 +216,13 @@ class Model */ public function getSitesId() { - $result = Db::fetchAll("SELECT idsite FROM " . Common::prefixTable('site')); + $result = Db::fetchAll("SELECT idsite FROM " . Common::prefixTable('site')); + $idSites = array(); foreach ($result as $idSite) { $idSites[] = $idSite['idsite']; } + return $idSites; } @@ -87,7 +236,6 @@ class Model public function getSiteUrlsFromId($idSite) { $urls = $this->getAliasSiteUrlsFromId($idSite); - $site = $this->getSiteFromId($idSite); if (empty($site)) { @@ -106,14 +254,119 @@ class Model */ public function getAliasSiteUrlsFromId($idSite) { - $db = Db::get(); - $result = $db->fetchAll("SELECT url - FROM " . Common::prefixTable("site_url") . " - WHERE idsite = ?", $idSite); + $db = $this->getDb(); + $result = $db->fetchAll("SELECT url FROM " . Common::prefixTable("site_url") . " + WHERE idsite = ?", $idSite); $urls = array(); foreach ($result as $url) { $urls[] = $url['url']; } + return $urls; } + + public function updateSite($site, $idSite) + { + $idSite = (int) $idSite; + + $db = $this->getDb(); + $db->update($this->table, $site, "idsite = $idSite"); + } + + /** + * Returns the list of unique timezones from all configured sites. + * + * @return array ( string ) + */ + public function getUniqueSiteTimezones() + { + $results = Db::fetchAll("SELECT distinct timezone FROM " . $this->table); + + $timezones = array(); + foreach ($results as $result) { + $timezones[] = $result['timezone']; + } + + return $timezones; + } + + /** + * Updates the field ts_created for the specified websites. + * + * @param $idSites int Id Site to update ts_created + * @param string Date to set as creation date. + * + * @ignore + */ + public function updateSiteCreatedTime($idSites, $minDateSql) + { + $idSites = array_map('intval', $idSites); + + $query = "UPDATE " . $this->table . " SET ts_created = ?" . + " WHERE idsite IN ( " . implode(",", $idSites) . " ) AND ts_created > ?"; + + $bind = array($minDateSql, $minDateSql); + + Db::query($query, $bind); + } + + /** + * Insert the list of alias URLs for the website. + * The URLs must not exist already for this website! + */ + public function insertSiteUrl($idSite, $url) + { + $db = $this->getDb(); + $db->insert(Common::prefixTable("site_url"), array( + 'idsite' => (int) $idSite, + 'url' => $url + ) + ); + } + + public function getPatternMatchSites($ids, $pattern, $limit) + { + $ids_str = ''; + foreach ($ids as $id_val) { + $ids_str .= (int) $id_val . ' , '; + } + $ids_str .= (int) $id_val; + + $bind = array('%' . $pattern . '%', 'http%' . $pattern . '%', '%' . $pattern . '%'); + + // Also match the idsite + $where = ''; + if (is_numeric($pattern)) { + $bind[] = $pattern; + $where = 'ORs s.idsite = ?'; + } + + $query = "SELECT idsite, name, main_url, `group` + FROM " . $this->table . " s + WHERE ( s.name like ? + OR s.main_url like ? + OR s.`group` like ? + $where ) + AND idsite in ($ids_str) + LIMIT " . (int) $limit; + + $db = $this->getDb(); + $sites = $db->fetchAll($query, $bind); + + return $sites; + } + + /** + * Delete all the alias URLs for the given idSite. + */ + public function deleteSiteAliasUrls($idsite) + { + $db = $this->getDb(); + $db->query("DELETE FROM " . Common::prefixTable("site_url") . " WHERE idsite = ?", $idsite); + } + + private function getDb() + { + return Db::get(); + } } diff --git a/plugins/Transitions/API.php b/plugins/Transitions/API.php index faeddf9f0b..32abffdc06 100644 --- a/plugins/Transitions/API.php +++ b/plugins/Transitions/API.php @@ -172,7 +172,6 @@ class API extends \Piwik\Plugin\API */ private function addInternalReferrers($logAggregator, &$report, $idaction, $actionType, $limitBeforeGrouping) { - $data = $this->queryInternalReferrers($idaction, $actionType, $logAggregator, $limitBeforeGrouping); if ($data['pageviews'] == 0) { @@ -198,7 +197,6 @@ class API extends \Piwik\Plugin\API */ private function addFollowingActions($logAggregator, &$report, $idaction, $actionType, $limitBeforeGrouping, $includeLoops = false) { - $data = $this->queryFollowingActions( $idaction, $actionType, $logAggregator, $limitBeforeGrouping, $includeLoops); @@ -225,7 +223,7 @@ class API extends \Piwik\Plugin\API if ($actionType != 'title') { // specific setup for page urls $types[Action::TYPE_PAGE_URL] = 'followingPages'; - $dimension = 'IF( idaction_url IS NULL, idaction_name, idaction_url )'; + $dimension = 'if ( idaction_url IS NULL, idaction_name, idaction_url )'; // site search referrers are logged with url=NULL // when we find one, we have to join on name $joinLogActionColumn = $dimension; @@ -408,7 +406,7 @@ class API extends \Piwik\Plugin\API if ($dimension == 'idaction_url_ref') { // site search referrers are logged with url_ref=NULL // when we find one, we have to join on name_ref - $dimension = 'IF( idaction_url_ref IS NULL, idaction_name_ref, idaction_url_ref )'; + $dimension = 'if ( idaction_url_ref IS NULL, idaction_name_ref, idaction_url_ref )'; $joinLogActionOn = $dimension; } else { $joinLogActionOn = $dimension; @@ -514,7 +512,6 @@ class API extends \Piwik\Plugin\API */ private function addExternalReferrers($logAggregator, &$report, $idaction, $actionType, $limitBeforeGrouping) { - $data = $this->queryExternalReferrers( $idaction, $actionType, $logAggregator, $limitBeforeGrouping); diff --git a/plugins/UserCountry/Controller.php b/plugins/UserCountry/Controller.php index 483b2d844f..a6ed712dbe 100644 --- a/plugins/UserCountry/Controller.php +++ b/plugins/UserCountry/Controller.php @@ -369,7 +369,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin private function dieIfGeolocationAdminIsDisabled() { - if(!UserCountry::isGeoLocationAdminEnabled()) { + if (!UserCountry::isGeoLocationAdminEnabled()) { throw new \Exception('Geo location setting page has been disabled.'); } } diff --git a/plugins/UsersManager/API.php b/plugins/UsersManager/API.php index 61b26323da..79587e37b2 100644 --- a/plugins/UsersManager/API.php +++ b/plugins/UsersManager/API.php @@ -435,7 +435,7 @@ class API extends \Piwik\Plugin\API $this->checkEmail($email); } - $alias = $this->getCleanAlias($alias, $userLogin); + $alias = $this->getCleanAlias($alias, $userLogin); $token_auth = $this->getTokenAuth($userLogin, $password); $this->model->updateUser($userLogin, $password, $email, $alias, $token_auth); diff --git a/plugins/UsersManager/Controller.php b/plugins/UsersManager/Controller.php index 56974b1efc..d22240b977 100644 --- a/plugins/UsersManager/Controller.php +++ b/plugins/UsersManager/Controller.php @@ -177,7 +177,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin ); // assertion - if(count($dates) != count($mappingDatesToPeriods)) { + if (count($dates) != count($mappingDatesToPeriods)) { throw new Exception("some metadata is missing in getDefaultDates()"); } @@ -251,7 +251,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin Piwik::checkUserIsNotAnonymous(); $salt = Common::getRequestVar('ignoreSalt', false, 'string'); - if($salt !== $this->getIgnoreCookieSalt()) { + if ($salt !== $this->getIgnoreCookieSalt()) { throw new Exception("Not authorized"); } diff --git a/plugins/UsersManager/Model.php b/plugins/UsersManager/Model.php index 872d693ee6..3c39516cb5 100644 --- a/plugins/UsersManager/Model.php +++ b/plugins/UsersManager/Model.php @@ -26,6 +26,14 @@ use Piwik\Piwik; */ class Model { + private static $rawPrefix = 'user'; + private $table; + + public function __construct() + { + $this->table = Common::prefixTable(self::$rawPrefix); + } + /** * Returns the list of all the users * @@ -39,11 +47,10 @@ class Model if (!empty($userLogins)) { $where = 'WHERE login IN (' . Common::getSqlStringFieldsArray($userLogins) . ')'; - $bind = $userLogins; + $bind = $userLogins; } - $users = Db::get()->fetchAll("SELECT * - FROM " . Common::prefixTable("user") . " + $users = Db::get()->fetchAll("SELECT * FROM " . $this->table . " $where ORDER BY login ASC", $bind); @@ -57,9 +64,8 @@ class Model */ public function getUsersLogin() { - $users = Db::get()->fetchAll("SELECT login - FROM " . Common::prefixTable("user") . " - ORDER BY login ASC"); + $users = Db::get()->fetchAll("SELECT login FROM " . $this->table . " ORDER BY login ASC"); + $return = array(); foreach ($users as $login) { $return[] = $login['login']; @@ -70,10 +76,9 @@ class Model public function getUsersSitesFromAccess($access) { - $users = Db::get()->fetchAll("SELECT login,idsite - FROM " . Common::prefixTable("access") - . " WHERE access = ? - ORDER BY login, idsite", $access); + $users = $this->getDb()->fetchAll("SELECT login,idsite FROM " . Common::prefixTable("access") + . " WHERE access = ? + ORDER BY login, idsite", $access); $return = array(); foreach ($users as $user) { @@ -85,9 +90,8 @@ class Model public function getUsersAccessFromSite($idSite) { - $users = Db::get()->fetchAll("SELECT login,access - FROM " . Common::prefixTable("access") - . " WHERE idsite = ?", $idSite); + $users = $this->getDb()->fetchAll("SELECT login,access FROM " . Common::prefixTable("access") + . " WHERE idsite = ?", $idSite); $return = array(); foreach ($users as $user) { @@ -99,9 +103,9 @@ class Model public function getUsersLoginWithSiteAccess($idSite, $access) { - $users = Db::get()->fetchAll("SELECT login - FROM " . Common::prefixTable("access") - . " WHERE idsite = ? AND access = ?", array($idSite, $access)); + $users = $this->getDb()->fetchAll("SELECT login + FROM " . Common::prefixTable("access") + . " WHERE idsite = ? AND access = ?", array($idSite, $access)); $logins = array(); foreach ($users as $user) { @@ -129,9 +133,8 @@ class Model */ public function getSitesAccessFromUser($userLogin) { - $users = Db::get()->fetchAll("SELECT idsite,access - FROM " . Common::prefixTable("access") - . " WHERE login = ?", $userLogin); + $users = $this->getDb()->fetchAll("SELECT idsite,access FROM " . Common::prefixTable("access") + . " WHERE login = ?", $userLogin); $return = array(); foreach ($users as $user) { @@ -146,23 +149,20 @@ class Model public function getUser($userLogin) { - return Db::get()->fetchRow("SELECT * - FROM " . Common::prefixTable("user") - . " WHERE login = ?", $userLogin); + return $this->getDb()->fetchRow("SELECT * FROM " . $this->table + . " WHERE login = ?", $userLogin); } public function getUserByEmail($userEmail) { - return Db::get()->fetchRow("SELECT * - FROM " . Common::prefixTable("user") - . " WHERE email = ?", $userEmail); + return $this->getDb()->fetchRow("SELECT * FROM " . $this->table + . " WHERE email = ?", $userEmail); } public function getUserByTokenAuth($tokenAuth) { - return Db::get()->fetchRow('SELECT * - FROM ' . Common::prefixTable('user') . ' - WHERE token_auth = ?', $tokenAuth); + return $this->getDb()->fetchRow('SELECT * FROM ' . $this->table . ' + WHERE token_auth = ?', $tokenAuth); } public function addUser($userLogin, $passwordTransformed, $email, $alias, $tokenAuth, $dateRegistered) @@ -177,12 +177,12 @@ class Model 'superuser_access' => 0 ); - Db::get()->insert(Common::prefixTable("user"), $user); + $this->getDb()->insert($this->table, $user); } public function setSuperUserAccess($userLogin, $hasSuperUserAccess) { - Db::get()->update(Common::prefixTable("user"), + $this->getDb()->update($this->table, array( 'superuser_access' => $hasSuperUserAccess ? 1 : 0 ), @@ -192,17 +192,17 @@ class Model public function getUsersHavingSuperUserAccess() { - $users = Db::get()->fetchAll("SELECT login, email - FROM " . Common::prefixTable("user") . " - WHERE superuser_access = 1 - ORDER BY date_registered ASC"); + $users = $this->getDb()->fetchAll("SELECT login, email + FROM " . Common::prefixTable("user") . " + WHERE superuser_access = 1 + ORDER BY date_registered ASC"); return $users; } public function updateUser($userLogin, $password, $email, $alias, $tokenAuth) { - Db::get()->update(Common::prefixTable("user"), + $this->getDb()->update($this->table, array( 'password' => $password, 'alias' => $alias, @@ -215,24 +215,22 @@ class Model public function userExists($userLogin) { - $count = Db::get()->fetchOne("SELECT count(*) - FROM " . Common::prefixTable("user") . " - WHERE login = ?", $userLogin); + $count = $this->getDb()->fetchOne("SELECT count(*) FROM " . $this->table . " + WHERE login = ?", $userLogin); return $count != 0; } public function userEmailExists($userEmail) { - $count = Db::get()->fetchOne("SELECT count(*) - FROM " . Common::prefixTable("user") . " - WHERE email = ?", $userEmail); + $count = $this->getDb()->fetchOne("SELECT count(*) FROM " . $this->table . " + WHERE email = ?", $userEmail); return $count != 0; } public function addUserAccess($userLogin, $access, $idSites) { foreach ($idSites as $idsite) { - Db::get()->insert(Common::prefixTable("access"), + $this->getDb()->insert(Common::prefixTable("access"), array("idsite" => $idsite, "login" => $userLogin, "access" => $access) @@ -242,7 +240,7 @@ class Model public function deleteUserOnly($userLogin) { - Db::get()->query("DELETE FROM " . Common::prefixTable("user") . " WHERE login = ?", $userLogin); + $this->getDb()->query("DELETE FROM " . $this->table . " WHERE login = ?", $userLogin); /** * Triggered after a user has been deleted. @@ -258,12 +256,12 @@ class Model public function deleteUserAccess($userLogin, $idSites = null) { if (is_null($idSites)) { - Db::get()->query("DELETE FROM " . Common::prefixTable("access") . + $this->getDb()->query("DELETE FROM " . Common::prefixTable("access") . " WHERE login = ?", array($userLogin)); } else { foreach ($idSites as $idsite) { - Db::get()->query("DELETE FROM " . Common::prefixTable("access") . + $this->getDb()->query("DELETE FROM " . Common::prefixTable("access") . " WHERE idsite = ? AND login = ?", array($idsite, $userLogin) ); @@ -271,4 +269,9 @@ class Model } } + private function getDb() + { + return Db::get(); + } + } diff --git a/plugins/VisitsSummary/Controller.php b/plugins/VisitsSummary/Controller.php index 903b2477cf..63fe8ef205 100644 --- a/plugins/VisitsSummary/Controller.php +++ b/plugins/VisitsSummary/Controller.php @@ -159,7 +159,7 @@ class Controller extends \Piwik\Plugin\Controller $view->maxActions = (int)$dataRow->getColumn('max_actions'); $view->nbActionsPerVisit = $dataRow->getColumn('nb_actions_per_visit'); - if(Common::isActionsPluginEnabled()) { + if (Common::isActionsPluginEnabled()) { $view->showActionsPluginReports = true; $dataTableActions = APIActions::getInstance()->get($idSite, Common::getRequestVar('period'), Common::getRequestVar('date'), \Piwik\API\Request::getRawSegmentFromRequest()); diff --git a/tests/PHPUnit/Core/AssetManagerTest.php b/tests/PHPUnit/Core/AssetManagerTest.php index 2e2f27f498..85fc6d9764 100644 --- a/tests/PHPUnit/Core/AssetManagerTest.php +++ b/tests/PHPUnit/Core/AssetManagerTest.php @@ -420,7 +420,7 @@ class AssetManagerTest extends PHPUnit_Framework_TestCase return '<script type="text/javascript">' . PHP_EOL . 'var translations = [];' . PHP_EOL . - 'if(typeof(piwik_translations) == \'undefined\') { var piwik_translations = new Object; }for(var i in translations) { piwik_translations[i] = translations[i];} ' . PHP_EOL . + 'if (typeof(piwik_translations) == \'undefined\') { var piwik_translations = new Object; }for(var i in translations) { piwik_translations[i] = translations[i];} ' . PHP_EOL . '</script>'; } diff --git a/tests/PHPUnit/Integration/ArchiveInvalidationTest.php b/tests/PHPUnit/Integration/ArchiveInvalidationTest.php index a45aaac72c..1d04920a8c 100644 --- a/tests/PHPUnit/Integration/ArchiveInvalidationTest.php +++ b/tests/PHPUnit/Integration/ArchiveInvalidationTest.php @@ -86,7 +86,6 @@ class ArchiveInvalidationTest extends IntegrationTestCase $this->invalidateTestArchives(); $this->runApiTests($api, $params); - } /** diff --git a/tests/resources/staticFileServer.php b/tests/resources/staticFileServer.php index 5907c169e3..6ad277863e 100644 --- a/tests/resources/staticFileServer.php +++ b/tests/resources/staticFileServer.php @@ -15,7 +15,7 @@ use Piwik\ProxyHttp; define('PIWIK_DOCUMENT_ROOT', dirname(__FILE__).'/../../'); if(file_exists(PIWIK_DOCUMENT_ROOT . '/bootstrap.php')) { - require_once PIWIK_DOCUMENT_ROOT . '/bootstrap.php'; + require_once PIWIK_DOCUMENT_ROOT . '/bootstrap.php'; } error_reporting(E_ALL|E_NOTICE); @@ -25,11 +25,11 @@ error_reporting(E_ALL|E_NOTICE); if(!defined('PIWIK_USER_PATH')) { - define('PIWIK_USER_PATH', PIWIK_DOCUMENT_ROOT); + define('PIWIK_USER_PATH', PIWIK_DOCUMENT_ROOT); } if(!defined('PIWIK_INCLUDE_PATH')) { - define('PIWIK_INCLUDE_PATH', PIWIK_DOCUMENT_ROOT); + define('PIWIK_INCLUDE_PATH', PIWIK_DOCUMENT_ROOT); } require_once PIWIK_INCLUDE_PATH . '/libs/upgradephp/upgrade.php'; |