diff options
Diffstat (limited to 'plugins')
48 files changed, 792 insertions, 141 deletions
diff --git a/plugins/API/API.php b/plugins/API/API.php index e5d9fbcd2a..2f609b5e8b 100644 --- a/plugins/API/API.php +++ b/plugins/API/API.php @@ -22,7 +22,6 @@ use Piwik\Metrics; use Piwik\Period; use Piwik\Period\Range; use Piwik\Piwik; -use Piwik\Plugin\Dimension\VisitDimension; use Piwik\Plugins\API\DataTable\MergeDataTables; use Piwik\Plugins\CoreAdminHome\CustomLogo; use Piwik\Translation\Translator; @@ -88,8 +87,9 @@ class API extends \Piwik\Plugin\API * are not visible in the UI and not present in the API meta data. These columns are * translated here. * @return array + * @deprecated since Piwik 2.15.1 */ - public static function getDefaultMetricTranslations() + public function getDefaultMetricTranslations() { return Metrics::getDefaultMetricTranslations(); } @@ -102,6 +102,8 @@ class API extends \Piwik\Plugin\API */ public function getAvailableMeasurableTypes() { + Piwik::checkUserHasSomeViewAccess(); + $typeManager = new TypeManager(); $types = $typeManager->getAllTypes(); @@ -120,13 +122,19 @@ class API extends \Piwik\Plugin\API public function getSegmentsMetadata($idSites = array(), $_hideImplementationData = true) { - $isAuthenticatedWithViewAccess = Piwik::isUserHasViewAccess($idSites) && !Piwik::isUserIsAnonymous(); + if (empty($idSites)) { + Piwik::checkUserHasSomeViewAccess(); + } else { + Piwik::checkUserHasViewAccess($idSites); + } + + $isNotAnonymous = !Piwik::isUserIsAnonymous(); $segments = array(); foreach (Dimension::getAllDimensions() as $dimension) { foreach ($dimension->getSegments() as $segment) { if ($segment->isRequiresAtLeastViewAccess()) { - $segment->setPermission($isAuthenticatedWithViewAccess); + $segment->setPermission($isNotAnonymous); } $segments[] = $segment->toArray(); @@ -250,6 +258,7 @@ class API extends \Piwik\Plugin\API * * @param bool $pathOnly If true, returns path relative to doc root. Otherwise, returns a URL. * @return string + * @deprecated since Piwik 2.15.1 */ public function getLogoUrl($pathOnly = false) { @@ -262,6 +271,7 @@ class API extends \Piwik\Plugin\API * * @param bool $pathOnly If true, returns path relative to doc root. Otherwise, returns a URL. * @return string + * @deprecated since Piwik 2.15.1 */ public function getHeaderLogoUrl($pathOnly = false) { @@ -300,6 +310,8 @@ class API extends \Piwik\Plugin\API public function getMetadata($idSite, $apiModule, $apiAction, $apiParameters = array(), $language = false, $period = false, $date = false, $hideMetricsDoc = false, $showSubtableReports = false) { + Piwik::checkUserHasViewAccess($idSite); + if ($language) { /** @var Translator $translator */ $translator = StaticContainer::get('Piwik\Translation\Translator'); @@ -325,6 +337,8 @@ class API extends \Piwik\Plugin\API public function getReportMetadata($idSites = '', $period = false, $date = false, $hideMetricsDoc = false, $showSubtableReports = false) { + Piwik::checkUserHasViewAccess($idSites); + $reporter = new ProcessedReport(); $metadata = $reporter->getReportMetadata($idSites, $period, $date, $hideMetricsDoc, $showSubtableReports); return $metadata; @@ -333,11 +347,13 @@ class API extends \Piwik\Plugin\API public function getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment = false, $apiParameters = false, $idGoal = false, $language = false, $showTimer = true, $hideMetricsDoc = false, $idSubtable = false, $showRawMetrics = false, - $format_metrics = null) + $format_metrics = null, $idDimension = false) { + Piwik::checkUserHasViewAccess($idSite); + $reporter = new ProcessedReport(); $processed = $reporter->getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment, - $apiParameters, $idGoal, $language, $showTimer, $hideMetricsDoc, $idSubtable, $showRawMetrics, $format_metrics); + $apiParameters, $idGoal, $language, $showTimer, $hideMetricsDoc, $idSubtable, $showRawMetrics, $format_metrics, $idDimension); return $processed; } @@ -347,6 +363,8 @@ class API extends \Piwik\Plugin\API */ public function get($idSite, $period, $date, $segment = false, $columns = false) { + Piwik::checkUserHasViewAccess($idSite); + $columns = Piwik::getArrayFromApiParameter($columns); // build columns map for faster checks later on @@ -427,13 +445,16 @@ class API extends \Piwik\Plugin\API * @param bool|int $idGoal * @param bool|string $legendAppendMetric * @param bool|string $labelUseAbsoluteUrl + * @param bool|int $idDimension * @return array */ - public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true) + public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true, $idDimension = false) { + Piwik::checkUserHasViewAccess($idSite); + $rowEvolution = new RowEvolution(); return $rowEvolution->getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label, $segment, $column, - $language, $idGoal, $legendAppendMetric, $labelUseAbsoluteUrl); + $language, $idGoal, $legendAppendMetric, $labelUseAbsoluteUrl, $idDimension); } /** diff --git a/plugins/API/ProcessedReport.php b/plugins/API/ProcessedReport.php index db87cd19c7..9c6893057d 100644 --- a/plugins/API/ProcessedReport.php +++ b/plugins/API/ProcessedReport.php @@ -380,17 +380,25 @@ class ProcessedReport public function getProcessedReport($idSite, $period, $date, $apiModule, $apiAction, $segment = false, $apiParameters = false, $idGoal = false, $language = false, $showTimer = true, $hideMetricsDoc = false, $idSubtable = false, $showRawMetrics = false, - $formatMetrics = null) + $formatMetrics = null, $idDimension = false) { $timer = new Timer(); if (empty($apiParameters)) { $apiParameters = array(); } + if (!empty($idGoal) && empty($apiParameters['idGoal']) ) { $apiParameters['idGoal'] = $idGoal; } + + if (!empty($idDimension) + && empty($apiParameters['idDimension']) + ) { + $apiParameters['idDimension'] = (int) $idDimension; + } + // Is this report found in the Metadata available reports? $reportMetadata = $this->getMetadata($idSite, $apiModule, $apiAction, $apiParameters, $language, $period, $date, $hideMetricsDoc, $showSubtableReports = true); diff --git a/plugins/API/RowEvolution.php b/plugins/API/RowEvolution.php index c708608089..711a48316c 100644 --- a/plugins/API/RowEvolution.php +++ b/plugins/API/RowEvolution.php @@ -37,7 +37,7 @@ class RowEvolution 'getPageUrl' ); - public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true) + public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true, $idDimension = false) { // validation of requested $period & $date if ($period == 'range') { @@ -52,9 +52,9 @@ class RowEvolution $label = DataTablePostProcessor::unsanitizeLabelParameter($label); $labels = Piwik::getArrayFromApiParameter($label); - $metadata = $this->getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $idGoal); + $metadata = $this->getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $idGoal, $idDimension); - $dataTable = $this->loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $idGoal); + $dataTable = $this->loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $idGoal, $idDimension); if (empty($labels)) { $labels = $this->getLabelsFromDataTable($dataTable, $labels); @@ -249,7 +249,7 @@ class RowEvolution * @throws Exception * @return DataTable\Map|DataTable */ - private function loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $idGoal = false) + private function loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $idGoal = false, $idDimension = false) { if (!is_array($label)) { $label = array($label); @@ -266,6 +266,7 @@ class RowEvolution 'serialize' => '0', 'segment' => $segment, 'idGoal' => $idGoal, + 'idDimension' => $idDimension, // data for row evolution should NOT be limited 'filter_limit' => -1, @@ -310,12 +311,15 @@ class RowEvolution * @throws Exception * @return array */ - private function getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $idGoal = false) + private function getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $idGoal = false, $idDimension = false) { $apiParameters = array(); if (!empty($idGoal) && $idGoal > 0) { $apiParameters = array('idGoal' => $idGoal); } + if (!empty($idDimension) && $idDimension > 0) { + $apiParameters = array('idDimension' => (int) $idDimension); + } $reportMetadata = API::getInstance()->getMetadata($idSite, $apiModule, $apiAction, $apiParameters, $language, $period, $date, $hideMetricsDoc = false, $showSubtableReports = true); diff --git a/plugins/Actions/Archiver.php b/plugins/Actions/Archiver.php index 5110130b84..7610e973ef 100644 --- a/plugins/Actions/Archiver.php +++ b/plugins/Actions/Archiver.php @@ -149,10 +149,7 @@ class Archiver extends \Piwik\Plugin\Archiver $select = "log_action.name, log_action.type, log_action.idaction, - log_action.url_prefix, - count(distinct log_link_visit_action.idvisit) as `" . PiwikMetrics::INDEX_NB_VISITS . "`, - count(distinct log_link_visit_action.idvisitor) as `" . PiwikMetrics::INDEX_NB_UNIQ_VISITORS . "`, - count(*) as `" . PiwikMetrics::INDEX_PAGE_NB_HITS . "`"; + log_action.url_prefix"; $select = $this->addMetricsToSelect($select, $metricsConfig); @@ -178,8 +175,7 @@ class Archiver extends \Piwik\Plugin\Archiver $rankingQuery = new RankingQuery($rankingQueryLimit); $rankingQuery->setOthersLabel(DataTable::LABEL_SUMMARY_ROW); $rankingQuery->addLabelColumn(array('idaction', 'name')); - $rankingQuery->addColumn(array('url_prefix', PiwikMetrics::INDEX_NB_UNIQ_VISITORS)); - $rankingQuery->addColumn(array(PiwikMetrics::INDEX_PAGE_NB_HITS, PiwikMetrics::INDEX_NB_VISITS), 'sum'); + $rankingQuery->addColumn('url_prefix'); if ($this->isSiteSearchEnabled()) { $rankingQuery->addColumn(PiwikMetrics::INDEX_SITE_SEARCH_HAS_NO_RESULT, 'min'); diff --git a/plugins/Actions/Metrics.php b/plugins/Actions/Metrics.php index 83b1c7370a..006fd6043d 100644 --- a/plugins/Actions/Metrics.php +++ b/plugins/Actions/Metrics.php @@ -50,6 +50,18 @@ class Metrics public static function getActionMetrics() { $metricsConfig = array( + PiwikMetrics::INDEX_NB_VISITS => array( + 'aggregation' => 'sum', + 'query' => "count(distinct log_link_visit_action.idvisit)" + ), + PiwikMetrics::INDEX_NB_UNIQ_VISITORS => array( + 'aggregation' => false, + 'query' => "count(distinct log_link_visit_action.idvisitor)" + ), + PiwikMetrics::INDEX_PAGE_NB_HITS => array( + 'aggregation' => 'sum', + 'query' => "count(*)" + ), PiwikMetrics::INDEX_PAGE_SUM_TIME_GENERATION => array( 'aggregation' => 'sum', 'query' => "sum( diff --git a/plugins/CoreHome/Columns/UserId.php b/plugins/CoreHome/Columns/UserId.php index bbe7e44c8f..a611ca8def 100644 --- a/plugins/CoreHome/Columns/UserId.php +++ b/plugins/CoreHome/Columns/UserId.php @@ -11,6 +11,7 @@ namespace Piwik\Plugins\CoreHome\Columns; use Piwik\Cache; use Piwik\DataTable; use Piwik\DataTable\Map; +use Piwik\Metrics; use Piwik\Period\Range; use Piwik\Piwik; use Piwik\Plugin\Dimension\VisitDimension; @@ -124,7 +125,14 @@ class UserId extends VisitDimension return false; } - $numUsers = $result->getColumn('nb_users'); + $firstRow = $result->getFirstRow(); + if ($firstRow instanceof DataTable\Row && $firstRow->hasColumn(Metrics::INDEX_NB_USERS)) { + $metric = Metrics::INDEX_NB_USERS; + } else { + $metric = 'nb_users'; + } + + $numUsers = $result->getColumn($metric); $numUsers = array_sum($numUsers); return !empty($numUsers); diff --git a/plugins/CoreHome/javascripts/broadcast.js b/plugins/CoreHome/javascripts/broadcast.js index 706a8e59d5..c0cc7d81c4 100644 --- a/plugins/CoreHome/javascripts/broadcast.js +++ b/plugins/CoreHome/javascripts/broadcast.js @@ -214,6 +214,10 @@ var broadcast = { currentHashStr = broadcast.updateParamValue('idDashboard=', currentHashStr); } + if (module != 'CustomDimensions') { + currentHashStr = broadcast.updateParamValue('idDimension=', currentHashStr); + } + if (disableHistory) { var newLocation = window.location.href.split('#')[0] + '#?' + currentHashStr; // window.location.replace changes the current url without pushing it on the browser's history stack @@ -420,7 +424,8 @@ var broadcast = { broadcast.getParamValue('action', urlAjax), { idGoal: broadcast.getParamValue('idGoal', urlAjax), - idDashboard: broadcast.getParamValue('idDashboard', urlAjax) + idDashboard: broadcast.getParamValue('idDashboard', urlAjax), + idDimension: broadcast.getParamValue('idDimension', urlAjax) } ); }); diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 0561185de8..0232d91ec6 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -1069,6 +1069,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { var segment = self.param.segment; var label = self.param.label; var idGoal = self.param.idGoal; + var idDimension = self.param.idDimension; var param_date = self.param.date; var date = $(this).attr('date'); if (typeof date != 'undefined') { @@ -1137,6 +1138,11 @@ $.extend(DataTable.prototype, UIControl.prototype, { && idGoal != '-1') { str += '&idGoal=' + idGoal; } + // Export Dimension specific reports + if (typeof idDimension != 'undefined' + && idDimension != '-1') { + str += '&idDimension=' + idDimension; + } if (label) { label = label.split(','); diff --git a/plugins/CoreHome/javascripts/dataTable_rowactions.js b/plugins/CoreHome/javascripts/dataTable_rowactions.js index 004e27e3b6..ab07537e2f 100644 --- a/plugins/CoreHome/javascripts/dataTable_rowactions.js +++ b/plugins/CoreHome/javascripts/dataTable_rowactions.js @@ -386,6 +386,11 @@ DataTable_RowActions_RowEvolution.prototype.showRowEvolution = function (apiMeth requestParams.action = 'getRowEvolutionPopover'; requestParams.colors = JSON.stringify(piwik.getSparklineColors()); + var idDimension = broadcast.getValueFromHash('idDimension'); + if (idDimension) { + requestParams.idDimension = parseInt(idDimension, 10); + } + $.extend(requestParams, extraParams); var ajaxRequest = new ajaxHelper(); diff --git a/plugins/CoreHome/javascripts/notification.js b/plugins/CoreHome/javascripts/notification.js index e6c3f017f2..527c845d87 100644 --- a/plugins/CoreHome/javascripts/notification.js +++ b/plugins/CoreHome/javascripts/notification.js @@ -54,6 +54,16 @@ this.$node = placeNotification(template, options); }; + /** + * Removes a previously shown notification having the given notification id. + * + * + * @param {string} notificationId The id of a notification that was previously registered. + */ + Notification.prototype.remove = function (notificationId) { + $('[piwik-notification][notification-id=' + notificationId + ']').remove(); + }; + Notification.prototype.scrollToNotification = function () { if (this.$node) { piwikHelper.lazyScrollTo(this.$node, 250); diff --git a/plugins/CoreHome/templates/_menu.twig b/plugins/CoreHome/templates/_menu.twig index 4c4643723d..baaa8ab8ca 100644 --- a/plugins/CoreHome/templates/_menu.twig +++ b/plugins/CoreHome/templates/_menu.twig @@ -1,6 +1,6 @@ -{% macro submenuItem(name, url, anchorlink) %} +{% macro submenuItem(name, url, anchorlink, tooltip) %} {% if name|slice(0,1) != '_' %} - <li role="menuitem" title="{{ name|translate|e('html_attr') }}"> + <li role="menuitem" title="{{ tooltip|default(name)|translate|e('html_attr') }}"> <a class="item" href="{% if anchorlink %}#{% else %}index.php?{% endif %}{{ url|urlRewriteWithParameters|slice(1) }}"> {{ name|translate }} </a> @@ -14,7 +14,7 @@ {% for item in group.getItems %} <a class="item menuItem" href='{% if anchorlink %}#?{% else %}index.php?{% endif %}{{ item.url|urlRewriteWithParameters|slice(1) }}' - {% if item.tooltip %}title="{{ item.tooltip|e('html_attr') }}"{% endif %}> + title="{% if item.tooltip %}{{ item.tooltip|e('html_attr') }}{% else %}{{ item.name|e('html_attr') }}{% endif %}"> {{ item.name|translate }} </a> {% endfor %} @@ -55,7 +55,7 @@ {% if urlParameters._url is defined and urlParameters._url is not iterable %} {{ _self.groupedItem(name,urlParameters._url, anchorlink) }} {% elseif name|slice(0,1) != '_' %} - {{ _self.submenuItem(name,urlParameters._url, anchorlink) }} + {{ _self.submenuItem(name,urlParameters._url, anchorlink, urlParameters._tooltip) }} {% endif %} {% endfor %} </ul> diff --git a/plugins/CoreHome/tests/Integration/Column/UserIdTest.php b/plugins/CoreHome/tests/Integration/Column/UserIdTest.php index 33c268afae..70715a4dc2 100644 --- a/plugins/CoreHome/tests/Integration/Column/UserIdTest.php +++ b/plugins/CoreHome/tests/Integration/Column/UserIdTest.php @@ -12,6 +12,7 @@ use Piwik\Access; use Piwik\Cache; use Piwik\DataAccess\ArchiveTableCreator; use Piwik\Db; +use Piwik\Metrics; use Piwik\Plugin\Manager; use Piwik\Plugins\CoreHome\Columns\UserId; use Piwik\Tests\Framework\Fixture; @@ -164,6 +165,17 @@ class UserIdTest extends IntegrationTestCase $this->assertDataTableHasUsers($this->getDataTableWithUsers()); } + public function test_hasDataTableUsers_shouldBeAbleToDetectIfNbUsersMetricIdIsused() + { + $table = $this->getDataTableWithZeroUsers(); + $table->renameColumn('nb_users', Metrics::INDEX_NB_USERS); + $this->assertNotDataTableHasUsers($table); + + $table = $this->getDataTableWithUsers(); + $table->renameColumn('nb_users', Metrics::INDEX_NB_USERS); + $this->assertDataTableHasUsers($this->getDataTableWithUsers()); + } + private function getDataTableWithoutUsersColumn() { $tableWithoutUsers = new DataTable(); diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php b/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php index 1a41a07df3..5acf9b50be 100644 --- a/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php +++ b/plugins/CoreVisualizations/Visualizations/HtmlTable/AllColumns.php @@ -10,6 +10,7 @@ namespace Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; use Piwik\DataTable; +use Piwik\Metrics; use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; use Piwik\View; @@ -40,11 +41,13 @@ class AllColumns extends HtmlTable $this->dataTable->filter(function (DataTable $dataTable) use ($properties) { $columnsToDisplay = array('label', 'nb_visits'); - if (in_array('nb_uniq_visitors', $dataTable->getColumns())) { + $columns = $dataTable->getColumns(); + + if (in_array('nb_uniq_visitors', $columns)) { $columnsToDisplay[] = 'nb_uniq_visitors'; } - if (in_array('nb_users', $dataTable->getColumns())) { + if (in_array('nb_users', $columns)) { $columnsToDisplay[] = 'nb_users'; } diff --git a/plugins/CoreVisualizations/javascripts/jqplotEvolutionGraph.js b/plugins/CoreVisualizations/javascripts/jqplotEvolutionGraph.js index 3b62e9197e..2fa3cee126 100644 --- a/plugins/CoreVisualizations/javascripts/jqplotEvolutionGraph.js +++ b/plugins/CoreVisualizations/javascripts/jqplotEvolutionGraph.js @@ -94,6 +94,7 @@ var module = broadcast.getValueFromHash('module'); var action = broadcast.getValueFromHash('action'); var idGoal = broadcast.getValueFromHash('idGoal'); + var idDimension = broadcast.getValueFromHash('idDimension'); var idSite = broadcast.getValueFromUrl('idSite', url); var period = broadcast.getValueFromUrl('period', url); var date = broadcast.getValueFromUrl('date', url); @@ -109,6 +110,10 @@ url += '&idGoal=' + idGoal; } + if (idDimension) { + url += '&idDimension=' + idDimension; + } + if (period) { url += '&period=' + period; } diff --git a/plugins/CustomDimensions b/plugins/CustomDimensions new file mode 160000 +Subproject 32dc6a3ed363af0ed96cd7d1379f210333cbb03 diff --git a/plugins/CustomVariables/CustomVariables.php b/plugins/CustomVariables/CustomVariables.php index 6f4796b7aa..9059482c33 100644 --- a/plugins/CustomVariables/CustomVariables.php +++ b/plugins/CustomVariables/CustomVariables.php @@ -162,6 +162,8 @@ class CustomVariables extends \Piwik\Plugin $translationKeys[] = 'CustomVariables_CreatingCustomVariableTakesTime'; $translationKeys[] = 'CustomVariables_SlotsReportIsGeneratedOverTime'; $translationKeys[] = 'General_Loading'; + $translationKeys[] = 'General_TrackingScopeVisit'; + $translationKeys[] = 'General_TrackingScopePage'; } public function getStylesheetFiles(&$stylesheets) diff --git a/plugins/CustomVariables/Tracker/CustomVariablesRequestProcessor.php b/plugins/CustomVariables/Tracker/CustomVariablesRequestProcessor.php index de1688d3ed..2b068ba03e 100644 --- a/plugins/CustomVariables/Tracker/CustomVariablesRequestProcessor.php +++ b/plugins/CustomVariables/Tracker/CustomVariablesRequestProcessor.php @@ -10,6 +10,7 @@ namespace Piwik\Plugins\CustomVariables\Tracker; use Piwik\Common; use Piwik\Plugins\CustomVariables\Model; +use Piwik\Tracker\Action; use Piwik\Tracker\Request; use Piwik\Tracker\RequestProcessor; use Piwik\Tracker\Visit\VisitProperties; @@ -63,4 +64,25 @@ class CustomVariablesRequestProcessor extends RequestProcessor $valuesToUpdate = array_merge($valuesToUpdate, $visitCustomVariables); } } + + public function afterRequestProcessed(VisitProperties $visitProperties, Request $request) + { + $action = $request->getMetadata('Actions', 'action'); + + if (empty($action) || !($action instanceof Action)) { + return; + } + + $customVariables = $action->getCustomVariables(); + + if (!empty($customVariables)) { + Common::printDebug("Page level Custom Variables: "); + Common::printDebug($customVariables); + + foreach ($customVariables as $field => $value) { + $action->setCustomField($field, $value); + } + } + + } } diff --git a/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.controller.js b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.controller.js index 4cbc8dc3e8..f8098eb114 100644 --- a/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.controller.js +++ b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.controller.js @@ -14,6 +14,9 @@ this.model = manageCustomVarsModel; this.siteName = piwik.siteName; - this.scopes = ['visit', 'page']; + this.scopes = [ + {value: 'visit', name: _pk_translate('General_TrackingScopeVisit')}, + {value: 'page', name: _pk_translate('General_TrackingScopePage')} + ]; } })();
\ No newline at end of file diff --git a/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.html b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.html index ccba542a87..6ab9ea6ba6 100644 --- a/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.html +++ b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.html @@ -10,7 +10,7 @@ </div> <div ng-repeat="scope in manageCustomVars.scopes"> - <h2 class="secondary">{{ 'CustomVariables_ScopeX'|translate:(scope|ucfirst) }}</h2> + <h2 class="secondary">{{ 'CustomVariables_ScopeX'|translate:(scope.name) }}</h2> <table class="dataTable entityTable"> <thead> <tr> @@ -22,7 +22,7 @@ <tr> <td colspan="3" ng-show="manageCustomVars.model.isLoading">{{ 'General_Loading'|translate }}</td> </tr> - <tr ng-repeat="customVariables in manageCustomVars.model.customVariables|filter:{scope: scope}"> + <tr ng-repeat="customVariables in manageCustomVars.model.customVariables|filter:{scope: scope.value}"> <td class="index">{{ customVariables.index }}</td> <td> <span ng-show="(customVariables.usages|length) === 0" diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php index 15f7b40aab..7a66581c69 100644 --- a/plugins/Goals/Controller.php +++ b/plugins/Goals/Controller.php @@ -459,8 +459,14 @@ class Controller extends \Piwik\Plugin\Controller } $customParams['viewDataTable'] = $report['viewDataTable']; + if (!empty($report['parameters'])) { + $params = array_merge($customParams, $report['parameters']); + } else { + $params = $customParams; + } + $goalReportsByDimension->addReport( - $categoryText, $report['name'], $report['module'] . '.' . $report['action'], $customParams); + $categoryText, $report['name'], $report['module'] . '.' . $report['action'], $params); } } } diff --git a/plugins/Goals/Reports/Base.php b/plugins/Goals/Reports/Base.php index fd732035d3..3db8c4446b 100644 --- a/plugins/Goals/Reports/Base.php +++ b/plugins/Goals/Reports/Base.php @@ -33,7 +33,7 @@ abstract class Base extends \Piwik\Plugin\Report $this->parameters = array('idGoal' => $goal['idgoal']); $this->order = $this->orderGoal + $goal['idgoal'] * 3; - $availableReports[] = $this->buildReportMetadata($availableReports, $infos); + $availableReports[] = $this->buildReportMetadata(); } $this->init(); diff --git a/plugins/ImageGraph/API.php b/plugins/ImageGraph/API.php index 4e7b466b21..ffdd223d46 100644 --- a/plugins/ImageGraph/API.php +++ b/plugins/ImageGraph/API.php @@ -122,7 +122,8 @@ class API extends \Piwik\Plugin\API $gridColor = API::DEFAULT_GRID_COLOR, $idSubtable = false, $legendAppendMetric = true, - $segment = false + $segment = false, + $idDimension = false ) { Piwik::checkUserHasViewAccess($idSite); @@ -151,6 +152,9 @@ class API extends \Piwik\Plugin\API if (!empty($idGoal)) { $apiParameters = array('idGoal' => $idGoal); } + if (!empty($idDimension)) { + $apiParameters = array('idDimension' => $idDimension); + } // Fetch the metadata for given api-action $parameters = array( 'idSite' => $idSite, @@ -305,6 +309,7 @@ class API extends \Piwik\Plugin\API 'column' => $plottedMetric, 'language' => $languageLoaded, 'idGoal' => $idGoal, + 'idDimension' => $idDimension, 'legendAppendMetric' => $legendAppendMetric, 'labelUseAbsoluteUrl' => false ); @@ -361,6 +366,7 @@ class API extends \Piwik\Plugin\API 'segment' => $segment, 'apiParameters' => false, 'idGoal' => $idGoal, + 'idDimension' => $idDimension, 'language' => $languageLoaded, 'showTimer' => true, 'hideMetricsDoc' => false, @@ -506,7 +512,10 @@ class API extends \Piwik\Plugin\API if ($idGoal != '') { $idGoal = '_' . $idGoal; } - $fileName = self::$DEFAULT_PARAMETERS[$graphType][self::FILENAME_KEY] . '_' . $apiModule . '_' . $apiAction . $idGoal . ' ' . str_replace(',', '-', $date) . ' ' . $idSite . '.png'; + if ($idDimension != '') { + $idDimension = '__' . $idDimension; + } + $fileName = self::$DEFAULT_PARAMETERS[$graphType][self::FILENAME_KEY] . '_' . $apiModule . '_' . $apiAction . $idGoal . $idDimension . ' ' . str_replace(',', '-', $date) . ' ' . $idSite . '.png'; $fileName = str_replace(array(' ', '/'), '_', $fileName); if (!Filesystem::isValidFilename($fileName)) { diff --git a/plugins/Insights/Visualizations/Insight.php b/plugins/Insights/Visualizations/Insight.php index 7fe304e5be..91d2c90b63 100644 --- a/plugins/Insights/Visualizations/Insight.php +++ b/plugins/Insights/Visualizations/Insight.php @@ -40,6 +40,10 @@ class Insight extends Visualization $report = $this->requestConfig->apiMethodToRequestDataTable; $report = str_replace('.', '_', $report); + if (!empty($this->requestConfig->request_parameters_to_modify['reportUniqueId'])) { + $report = $this->requestConfig->request_parameters_to_modify['reportUniqueId']; + } + $this->requestConfig->apiMethodToRequestDataTable = 'Insights.getInsights'; $this->requestConfig->request_parameters_to_modify = array( diff --git a/plugins/Live/Live.php b/plugins/Live/Live.php index 93e8d67881..1a71aa7b83 100644 --- a/plugins/Live/Live.php +++ b/plugins/Live/Live.php @@ -54,5 +54,7 @@ class Live extends \Piwik\Plugin $translationKeys[] = "Live_RowActionTooltipDefault"; $translationKeys[] = "Live_RowActionTooltipWithDimension"; $translationKeys[] = "Live_SegmentedVisitorLogTitle"; + $translationKeys[] = "General_Segment"; + $translationKeys[] = "General_And"; } }
\ No newline at end of file diff --git a/plugins/Live/javascripts/rowaction.js b/plugins/Live/javascripts/rowaction.js index 8baba18a2d..5c54e961b5 100644 --- a/plugins/Live/javascripts/rowaction.js +++ b/plugins/Live/javascripts/rowaction.js @@ -150,6 +150,12 @@ var segmentName = getDimensionFromApiMethod(apiMethod); var segmentValue = findTitleOfRowHavingRawSegmentValue(apiMethod, segment); + if (!segmentName || (segment && segment.indexOf(';') > 0)) { + segmentName = _pk_translate('General_Segment'); + var segmentParts = segment.split(';'); + segmentValue = segmentParts.join(' ' + _pk_translate('General_And') + ' '); + } + segmentName = piwikHelper.escape(segmentName); segmentName = piwikHelper.htmlEntities(segmentName); segmentValue = piwikHelper.escape(segmentValue); diff --git a/plugins/Monolog/tests/System/TrackerLoggingTest.php b/plugins/Monolog/tests/System/TrackerLoggingTest.php index 70c933d13f..8716229116 100644 --- a/plugins/Monolog/tests/System/TrackerLoggingTest.php +++ b/plugins/Monolog/tests/System/TrackerLoggingTest.php @@ -83,10 +83,8 @@ DEBUG: 'apiv' => '1',", $response); private function setTrackerConfig($trackerConfig) { $testingEnvironment = self::$fixture->getTestEnvironment(); - $configOverride = $testingEnvironment->configOverride; - $configOverride['Tracker'] = $trackerConfig; - $configOverride['log']['log_writers'] = array('screen'); - $testingEnvironment->configOverride = $configOverride; + $testingEnvironment->overrideConfig('Tracker', $trackerConfig); + $testingEnvironment->overrideConfig('log', 'log_writers', array('screen')); $testingEnvironment->save(); } diff --git a/plugins/Overlay/Controller.php b/plugins/Overlay/Controller.php index 795d7b991d..2ed50641c5 100644 --- a/plugins/Overlay/Controller.php +++ b/plugins/Overlay/Controller.php @@ -16,14 +16,26 @@ use Piwik\Metrics; use Piwik\Piwik; use Piwik\Plugin\Report; use Piwik\Plugins\Actions\ArchivingHelper; +use Piwik\Plugins\SegmentEditor\SegmentFormatter; use Piwik\Plugins\SitesManager\API as APISitesManager; use Piwik\ProxyHttp; +use Piwik\Segment; use Piwik\Tracker\Action; use Piwik\Tracker\PageUrl; use Piwik\View; class Controller extends \Piwik\Plugin\Controller { + /** + * @var SegmentFormatter + */ + private $segmentFormatter; + + public function __construct(SegmentFormatter $segmentFormatter) + { + $this->segmentFormatter = $segmentFormatter; + parent::__construct(); + } /** The index of the plugin */ public function index() @@ -38,6 +50,7 @@ class Controller extends \Piwik\Plugin\Controller $view = new View($template); $this->setGeneralVariablesView($view); + $view->segment = Request::getRawSegmentFromRequest(); $view->ssl = ProxyHttp::isHttps(); @@ -52,8 +65,9 @@ class Controller extends \Piwik\Plugin\Controller $period = Common::getRequestVar('period'); $date = Common::getRequestVar('date'); $currentUrl = Common::getRequestVar('currentUrl'); + $segment = Request::getRawSegmentFromRequest(); $currentUrl = Common::unsanitizeInputValue($currentUrl); - $segment = ''; + $segmentSidebar = ''; $normalizedCurrentUrl = PageUrl::excludeQueryParametersFromUrl($currentUrl, $idSite); $normalizedCurrentUrl = Common::unsanitizeInputValue($normalizedCurrentUrl); @@ -63,16 +77,22 @@ class Controller extends \Piwik\Plugin\Controller $path = ArchivingHelper::getActionExplodedNames($normalizedCurrentUrl, Action::TYPE_PAGE_URL); $path = array_map('urlencode', $path); $label = implode('>', $path); - $request = new Request( - 'method=Actions.getPageUrls' - . '&idSite=' . urlencode($idSite) - . '&date=' . urlencode($date) - . '&period=' . urlencode($period) - . '&label=' . urlencode($label) - . '&format=original' - . '&format_metrics=0' + + $params = array( + 'idSite' => $idSite, + 'date' => $date, + 'period' => $period, + 'label' => $label, + 'format' => 'original', + 'format_metrics' => 0, + 'serialize' => '0' ); - $dataTable = $request->process(); + + if (!empty($segment)) { + $params['segment'] = $segment; + } + + $dataTable = Request::processRequest('Actions.getPageUrls', $params); $formatter = new Metrics\Formatter\Html(); @@ -84,7 +104,10 @@ class Controller extends \Piwik\Plugin\Controller $showMetrics = array('nb_hits', 'nb_visits', 'nb_users', 'nb_uniq_visitors', 'bounce_rate', 'exit_rate', 'avg_time_on_page'); - $segment = $row->getMetadata('segment'); + $segmentSidebar = $row->getMetadata('segment'); + if (!empty($segmentSidebar) && !empty($segment)) { + $segmentSidebar = $segment . ';' . $segmentSidebar; + } foreach ($showMetrics as $metric) { $value = $row->getColumn($metric); @@ -127,7 +150,8 @@ class Controller extends \Piwik\Plugin\Controller $view->idSite = $idSite; $view->period = $period; $view->date = $date; - $view->segment = $segment; + $view->segment = $segmentSidebar; + $view->segmentDescription = $this->segmentFormatter->getHumanReadable($segment, $idSite); $this->outputCORSHeaders(); return $view->render(); @@ -142,64 +166,20 @@ class Controller extends \Piwik\Plugin\Controller $idSite = Common::getRequestVar('idSite', 0, 'int'); Piwik::checkUserHasViewAccess($idSite); + $view = new View('@Overlay/startOverlaySession'); + $sitesManager = APISitesManager::getInstance(); $site = $sitesManager->getSiteFromId($idSite); $urls = $sitesManager->getSiteUrlsFromId($idSite); + $view->isHttps = ProxyHttp::isHttps(); + $view->knownUrls = json_encode($urls); + $view->mainUrl = $site['main_url']; + $this->outputCORSHeaders(); Common::sendHeader('Content-Type: text/html; charset=UTF-8'); - return ' - <html><head><title></title></head><body> - <script type="text/javascript"> - function handleProtocol(url) { - if (' . (ProxyHttp::isHttps() ? 'true' : 'false') . ') { - return url.replace(/http:\/\//i, "https://"); - } else { - return url.replace(/https:\/\//i, "http://"); - } - } - - function removeUrlPrefix(url) { - return url.replace(/http(s)?:\/\/(www\.)?/i, ""); - } - - if (window.location.hash) { - var match = false; - - var urlToRedirect = window.location.hash.substr(1); - var urlToRedirectWithoutPrefix = removeUrlPrefix(urlToRedirect); - - var knownUrls = ' . json_encode($urls) . '; - for (var i = 0; i < knownUrls.length; i++) { - var testUrl = removeUrlPrefix(knownUrls[i]); - if (urlToRedirectWithoutPrefix.substr(0, testUrl.length) == testUrl) { - match = true; - if (navigator.appName == "Microsoft Internet Explorer") { - // internet explorer loses the referrer if we use window.location.href=X - var referLink = document.createElement("a"); - referLink.href = handleProtocol(urlToRedirect); - document.body.appendChild(referLink); - referLink.click(); - } else { - window.location.href = handleProtocol(urlToRedirect); - } - break; - } - } - - if (!match) { - var idSite = window.location.href.match(/idSite=([0-9]+)/i)[1]; - window.location.href = "index.php?module=Overlay&action=showErrorWrongDomain" - + "&idSite=" + idSite - + "&url=" + encodeURIComponent(urlToRedirect); - } - } - else { - window.location.href = handleProtocol("' . $site['main_url'] . '"); - }; - </script> - </body></html> - '; + + return $view->render(); } /** diff --git a/plugins/Overlay/client/client.js b/plugins/Overlay/client/client.js index 04b1f88f13..f37b9a0cd3 100644 --- a/plugins/Overlay/client/client.js +++ b/plugins/Overlay/client/client.js @@ -10,7 +10,7 @@ var Piwik_Overlay_Client = (function () { var idSite; /** The current period and date */ - var period, date; + var period, date, segment; /** Reference to the status bar DOM element */ var statusBar; @@ -131,11 +131,12 @@ var Piwik_Overlay_Client = (function () { return { /** Initialize in-site analytics */ - initialize: function (pPiwikRoot, pIdSite, pPeriod, pDate) { + initialize: function (pPiwikRoot, pIdSite, pPeriod, pDate, pSegment) { piwikRoot = pPiwikRoot; idSite = pIdSite; period = pPeriod; date = pDate; + segment = pSegment; var load = this.loadScript; var loading = this.loadingNotification; @@ -193,6 +194,10 @@ var Piwik_Overlay_Client = (function () { var url = piwikRoot + 'index.php?module=API&method=Overlay.' + method + '&idSite=' + idSite + '&period=' + period + '&date=' + date + '&format=JSON&filter_limit=-1'; + if (segment) { + url += '&segment=' + segment; + } + if (additionalParams) { url += '&' + additionalParams; } diff --git a/plugins/Overlay/javascripts/Overlay_Helper.js b/plugins/Overlay/javascripts/Overlay_Helper.js index e0681e7b45..42ff388d81 100644 --- a/plugins/Overlay/javascripts/Overlay_Helper.js +++ b/plugins/Overlay/javascripts/Overlay_Helper.js @@ -20,11 +20,17 @@ var Overlay_Helper = { }, /** Get the url to launch overlay */ - getOverlayLink: function (idSite, period, date, link) { + getOverlayLink: function (idSite, period, date, segment, link) { var url = 'index.php?module=Overlay&period=' + encodeURIComponent(period) + '&date=' + encodeURIComponent(date) + '&idSite=' + encodeURIComponent(idSite); + + if (segment) { + url += '&segment=' + encodeURIComponent(segment); + } + if (link) { url += '#?l=' + Overlay_Helper.encodeFrameUrl(link); } + return url; } diff --git a/plugins/Overlay/javascripts/Piwik_Overlay.js b/plugins/Overlay/javascripts/Piwik_Overlay.js index 4c78080806..d04f8e5fbe 100644 --- a/plugins/Overlay/javascripts/Piwik_Overlay.js +++ b/plugins/Overlay/javascripts/Piwik_Overlay.js @@ -10,7 +10,7 @@ var Piwik_Overlay = (function () { var $body, $iframe, $sidebar, $main, $location, $loading, $errorNotLoading; var $rowEvolutionLink, $transitionsLink, $fullScreenLink, $visitorLogLink; - var idSite, period, date; + var idSite, period, date, segment; var iframeSrcBase; var iframeDomain = ''; @@ -28,13 +28,19 @@ var Piwik_Overlay = (function () { iframeCurrentPage = currentUrl; iframeDomain = currentUrl.match(/http(s)?:\/\/(www\.)?([^\/]*)/i)[3]; - globalAjaxQueue.abort(); - var ajaxRequest = new ajaxHelper(); - ajaxRequest.addParams({ + var params = { module: 'Overlay', action: 'renderSidebar', currentUrl: currentUrl - }, 'get'); + }; + + if (segment) { + params.segment = segment; + } + + globalAjaxQueue.abort(); + var ajaxRequest = new ajaxHelper(); + ajaxRequest.addParams(params, 'get'); ajaxRequest.setCallback( function (response) { hideLoading(); @@ -111,6 +117,16 @@ var Piwik_Overlay = (function () { $fullScreenLink.show(); } + function getOverlaySegment(url) { + var location = broadcast.getParamValue('segment', url); + + // angular will encode the value again since it is added as the fragment path, not the fragment query parameter, + // so we have to decode it again after getParamValue + location = decodeURIComponent(location); + + return location; + } + function getOverlayLocationFromHash(urlHash) { var location = broadcast.getParamValue('l', urlHash); @@ -143,11 +159,12 @@ var Piwik_Overlay = (function () { return { /** This method is called when Overlay loads */ - init: function (iframeSrc, pIdSite, pPeriod, pDate) { + init: function (iframeSrc, pIdSite, pPeriod, pDate, pSegment) { iframeSrcBase = iframeSrc; idSite = pIdSite; period = pPeriod; date = pDate; + segment = pSegment; $body = $('body'); $iframe = $('#overlayIframe'); @@ -201,7 +218,7 @@ var Piwik_Overlay = (function () { if (parts.length == 2) { period = parts[0]; date = parts[1]; - window.location.href = Overlay_Helper.getOverlayLink(idSite, period, date, iframeCurrentPage); + window.location.href = Overlay_Helper.getOverlayLink(idSite, period, date, segment, iframeCurrentPage); } }); diff --git a/plugins/Overlay/javascripts/rowaction.js b/plugins/Overlay/javascripts/rowaction.js index c84e60a33b..8f11c736d0 100644 --- a/plugins/Overlay/javascripts/rowaction.js +++ b/plugins/Overlay/javascripts/rowaction.js @@ -19,12 +19,34 @@ DataTable_RowActions_Overlay.prototype.onClick = function (actionA, tr, e) { if (!actionA.data('overlay-manipulated')) { actionA.data('overlay-manipulated', 1); - var link = tr.find('> td:first > a').attr('href'); - link = $('<textarea>').html(link).val(); // remove html entities + var segment, link; + + if (DataTable_RowActions_Transitions.isActionCustomDimensionReport(this.dataTable.param)) { + + link = this.getLabelFromTr(tr); + if (link && link.substr(0, 1) === '@') { + link = link.substr(1); + } + + link = 'http://' + unescape(link); + + var subtable = tr.closest('table'); + if (subtable.is('.subDataTable')) { + var prev = subtable.closest('tr').prev(); + segment = prev.attr('data-segment-filter'); + } + } else { + + link = tr.find('> td:first > a').attr('href'); + link = $('<textarea>').html(link).val(); // remove html entities + } + + + var href = Overlay_Helper.getOverlayLink(this.dataTable.param.idSite, 'month', 'today', segment, link); actionA.attr({ target: '_blank', - href: Overlay_Helper.getOverlayLink(this.dataTable.param.idSite, 'month', 'today', link) + href: href }); } @@ -54,6 +76,11 @@ DataTable_RowActions_Registry.register({ if (!window.DataTable_RowActions_Transitions) { return false; } + + if (DataTable_RowActions_Transitions.isActionCustomDimensionReport(dataTableParams)) { + return true; + } + return DataTable_RowActions_Transitions.isPageUrlReport(dataTableParams.module, dataTableParams.action); }, diff --git a/plugins/Overlay/stylesheets/overlay.css b/plugins/Overlay/stylesheets/overlay.css index 4e30660775..a13dd67a46 100644 --- a/plugins/Overlay/stylesheets/overlay.css +++ b/plugins/Overlay/stylesheets/overlay.css @@ -35,12 +35,20 @@ a#overlayTitle .icon-help { margin: 20px 10px; } -#overlayLocation { +#overlayLocation, .overlaySegment { width: 200px; - margin: 0 0 30px 10px; font-size: 12px; } +#overlayLocation { + margin: 0 0 10px 10px; +} + +.overlaySegment { + margin: 0 0 30px 0; + word-break: break-all; +} + #overlayLoading { background: url(../../Morpheus/images/loading-blue.gif) no-repeat center 10px; width: 190px; diff --git a/plugins/Overlay/templates/index.twig b/plugins/Overlay/templates/index.twig index 10a0b40d76..effe5fbade 100644 --- a/plugins/Overlay/templates/index.twig +++ b/plugins/Overlay/templates/index.twig @@ -61,8 +61,8 @@ <script type="text/javascript"> broadcast._isInit = true; $(function () { - var iframeSrc = 'index.php?module=Overlay&action=startOverlaySession&idSite={{ idSite }}&period={{ period }}&date={{ rawDate }}'; - Piwik_Overlay.init(iframeSrc, '{{ idSite }}', '{{ period }}', '{{ rawDate }}'); + var iframeSrc = 'index.php?module=Overlay&action=startOverlaySession&idSite={{ idSite }}&period={{ period }}&date={{ rawDate }}&segment={{ segment }}'; + Piwik_Overlay.init(iframeSrc, '{{ idSite }}', '{{ period }}', '{{ rawDate }}', '{{ segment }}'); window.Piwik_Overlay_Translations = { domain: "{{ 'Overlay_Domain'|translate }}" diff --git a/plugins/Overlay/templates/index_noframe.twig b/plugins/Overlay/templates/index_noframe.twig index 0478715edb..f3c9e61579 100644 --- a/plugins/Overlay/templates/index_noframe.twig +++ b/plugins/Overlay/templates/index_noframe.twig @@ -6,7 +6,7 @@ <div id="overlayNoFrame"> <script type="text/javascript"> - var newLocation = 'index.php?module=Overlay&action=startOverlaySession&idSite={{ idSite }}&period={{ period }}&date={{ date }}'; + var newLocation = 'index.php?module=Overlay&action=startOverlaySession&idSite={{ idSite }}&period={{ period }}&date={{ date }}&segment={{ segment }}'; var locationParts = window.location.href.split('#'); if (locationParts.length > 1) { diff --git a/plugins/Overlay/templates/renderSidebar.twig b/plugins/Overlay/templates/renderSidebar.twig index 09d8cf0d40..36ff9c8ba1 100644 --- a/plugins/Overlay/templates/renderSidebar.twig +++ b/plugins/Overlay/templates/renderSidebar.twig @@ -8,6 +8,11 @@ </span> </div> + <div class="overlaySegment"> + <strong>{{ 'General_Segment'|translate }}:</strong> + <span>{{ segmentDescription }}</span> + </div> + {% if data|length > 0 %} <h2 class="overlayMainMetrics">{{ 'General_MainMetrics'|translate }}</h2> <ul class="overlayMetrics"> diff --git a/plugins/Overlay/templates/startOverlaySession.twig b/plugins/Overlay/templates/startOverlaySession.twig new file mode 100644 index 0000000000..b1db8ce5b2 --- /dev/null +++ b/plugins/Overlay/templates/startOverlaySession.twig @@ -0,0 +1,50 @@ +<html><head><title></title></head><body> +<script type="text/javascript"> + function handleProtocol(url) { + if ({% if isHttps %}true{% else %}false{% endif %}) { + return url.replace(/http:\/\//i, "https://"); + } else { + return url.replace(/https:\/\//i, "http://"); + } + } + + function removeUrlPrefix(url) { + return url.replace(/http(s)?:\/\/(www\.)?/i, ""); + } + + if (window.location.hash) { + var match = false; + + var urlToRedirect = window.location.hash.substr(1); + var urlToRedirectWithoutPrefix = removeUrlPrefix(urlToRedirect); + + var knownUrls = {{ knownUrls|raw }}; + for (var i = 0; i < knownUrls.length; i++) { + var testUrl = removeUrlPrefix(knownUrls[i]); + if (urlToRedirectWithoutPrefix.substr(0, testUrl.length) == testUrl) { + match = true; + if (navigator.appName == "Microsoft Internet Explorer") { + // internet explorer loses the referrer if we use window.location.href=X + var referLink = document.createElement("a"); + referLink.href = handleProtocol(urlToRedirect); + document.body.appendChild(referLink); + referLink.click(); + } else { + window.location.href = handleProtocol(urlToRedirect); + } + break; + } + } + + if (!match) { + var idSite = window.location.href.match(/idSite=([0-9]+)/i)[1]; + window.location.href = "index.php?module=Overlay&action=showErrorWrongDomain" + + "&idSite=" + idSite + + "&url=" + encodeURIComponent(urlToRedirect); + } + } + else { + window.location.href = handleProtocol("{{ mainUrl|e('js') }}"); + }; +</script> +</body></html>
\ No newline at end of file diff --git a/plugins/SegmentEditor/SegmentEditor.php b/plugins/SegmentEditor/SegmentEditor.php index 9107935e73..a46be068bc 100644 --- a/plugins/SegmentEditor/SegmentEditor.php +++ b/plugins/SegmentEditor/SegmentEditor.php @@ -28,6 +28,7 @@ class SegmentEditor extends \Piwik\Plugin 'AssetManager.getJavaScriptFiles' => 'getJsFiles', 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', 'Template.nextToCalendar' => 'getSegmentEditorHtml', + 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', ); } @@ -85,4 +86,9 @@ class SegmentEditor extends \Piwik\Plugin { return Config::getInstance()->General['allow_adding_segments_for_all_websites'] == 1; } + + public function getClientSideTranslationKeys(&$translationKeys) + { + $translationKeys[] = 'SegmentEditor_CustomSegment'; + } } diff --git a/plugins/SegmentEditor/SegmentFormatter.php b/plugins/SegmentEditor/SegmentFormatter.php new file mode 100644 index 0000000000..54dcc20c99 --- /dev/null +++ b/plugins/SegmentEditor/SegmentFormatter.php @@ -0,0 +1,142 @@ +<?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\SegmentEditor; + +use Exception; +use Piwik\Config; +use Piwik\Db; +use Piwik\Piwik; +use Piwik\Segment; +use Piwik\Segment\SegmentExpression; + +/** + */ +class SegmentFormatter +{ + /** + * @var SegmentList + */ + private $segmentList; + + private $matchesMetric = array( + SegmentExpression::MATCH_EQUAL => 'General_OperationEquals', + SegmentExpression::MATCH_NOT_EQUAL => 'General_OperationNotEquals', + SegmentExpression::MATCH_LESS_OR_EQUAL => 'General_OperationAtMost', + SegmentExpression::MATCH_GREATER_OR_EQUAL => 'General_OperationAtLeast', + SegmentExpression::MATCH_LESS => 'General_OperationLessThan', + SegmentExpression::MATCH_GREATER => 'General_OperationGreaterThan', + ); + + private $matchesDimension = array( + SegmentExpression::MATCH_EQUAL => 'General_OperationIs', + SegmentExpression::MATCH_NOT_EQUAL => 'General_OperationIsNot', + SegmentExpression::MATCH_CONTAINS => 'General_OperationContains', + SegmentExpression::MATCH_DOES_NOT_CONTAIN => 'General_OperationDoesNotContain', + SegmentExpression::MATCH_STARTS_WITH => 'General_OperationStartsWith', + SegmentExpression::MATCH_ENDS_WITH => 'General_OperationEndsWith' + ); + + private $operators = array( + SegmentExpression::BOOL_OPERATOR_AND => 'General_And', + SegmentExpression::BOOL_OPERATOR_OR => 'General_Or', + SegmentExpression::BOOL_OPERATOR_END => '', + ); + + public function __construct(SegmentList $segmentList) + { + $this->segmentList = $segmentList; + } + + public function getHumanReadable($segmentString, $idSite) + { + if (empty($segmentString)) { + return Piwik::translate('SegmentEditor_DefaultAllVisits'); + } + + $segment = new SegmentExpression($segmentString); + $expressions = $segment->parseSubExpressions(); + + $readable = ''; + foreach ($expressions as $expression) { + $operator = $expression[SegmentExpression::INDEX_BOOL_OPERATOR]; + $operand = $expression[SegmentExpression::INDEX_OPERAND]; + $name = $operand[SegmentExpression::INDEX_OPERAND_NAME]; + + $segment = $this->segmentList->findSegment($name, $idSite); + + if (empty($segment)) { + throw new Exception(sprintf("The segment '%s' does not exist.", $name)); + } + + $readable .= $segment['name'] . ' '; + $readable .= $this->getTranslationForComparison($operand, $segment['type']) . ' '; + $readable .= $this->getFormattedValue($operand); + $readable .= $this->getTranslationForBoolOperator($operator) . ' '; + } + + $readable = trim($readable); + + return $readable; + } + + private function getTranslationForComparison($operand, $segmentType) + { + $operator = $operand[SegmentExpression::INDEX_OPERAND_OPERATOR]; + + $translation = $operator; + + if ($operator === SegmentExpression::MATCH_IS_NULL_OR_EMPTY) { + return Piwik::translate('SegmentEditor_SegmentOperatorIsNullOrEmpty'); + } + + if ($operator === SegmentExpression::MATCH_IS_NOT_NULL_NOR_EMPTY) { + return Piwik::translate('SegmentEditor_SegmentOperatorIsNotNullNorEmpty'); + } + + if ($segmentType === 'dimension' && !empty($this->matchesDimension[$operator])) { + $translation = Piwik::translate($this->matchesDimension[$operator]); + } + if ($segmentType === 'metric' && !empty($this->matchesMetric[$operator])) { + $translation = Piwik::translate($this->matchesMetric[$operator]); + } + + return strtolower($translation); + } + + private function getFormattedValue($operand) + { + $operator = $operand[SegmentExpression::INDEX_OPERAND_OPERATOR]; + + if ($operator === SegmentExpression::MATCH_IS_NULL_OR_EMPTY + || $operator === SegmentExpression::MATCH_IS_NOT_NULL_NOR_EMPTY) { + return ''; + } + + $value = $operand[SegmentExpression::INDEX_OPERAND_VALUE]; + + if (empty($value)) { + $value = ''; + } + + return '"' . $value . '" '; + } + + private function getTranslationForBoolOperator($operator) + { + $translation = ''; + + if (!empty($this->operators[$operator])) { + $translation = Piwik::translate($this->operators[$operator]); + } elseif (!empty($operator)) { + $translation = $operator; + } + + return $translation; + } +} diff --git a/plugins/SegmentEditor/SegmentList.php b/plugins/SegmentEditor/SegmentList.php new file mode 100644 index 0000000000..e7094d4793 --- /dev/null +++ b/plugins/SegmentEditor/SegmentList.php @@ -0,0 +1,32 @@ +<?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\SegmentEditor; + +use Piwik\API\Request; +use Piwik\Config; +use Piwik\Db; + +/** + */ +class SegmentList +{ + public function findSegment($segmentName, $idSite) + { + $segments = Request::processRequest('API.getSegmentsMetadata', array( + 'idSites' => array($idSite), + )); + + foreach ($segments as $segment) { + if ($segment['segment'] == $segmentName && !empty($segmentName)) { + return $segment; + } + } + } + +} diff --git a/plugins/SegmentEditor/SegmentSelectorControl.php b/plugins/SegmentEditor/SegmentSelectorControl.php index 9dc2659660..b01018dbcf 100644 --- a/plugins/SegmentEditor/SegmentSelectorControl.php +++ b/plugins/SegmentEditor/SegmentSelectorControl.php @@ -8,8 +8,10 @@ */ namespace Piwik\Plugins\SegmentEditor; +use Piwik\API\Request; use Piwik\Common; use Piwik\Config; +use Piwik\Container\StaticContainer; use Piwik\Piwik; use Piwik\Plugins\API\API as APIMetadata; use Piwik\View\UIControl; @@ -37,6 +39,9 @@ class SegmentSelectorControl extends UIControl $this->selectedSegment = Common::getRequestVar('segment', false, 'string'); + $formatter = StaticContainer::get('Piwik\Plugins\SegmentEditor\SegmentFormatter'); + $this->segmentDescription = $formatter->getHumanReadable(Request::getRawSegmentFromRequest(), $this->idSite); + $this->isAddingSegmentsForAllWebsitesEnabled = SegmentEditor::isAddingSegmentsForAllWebsitesEnabled(); $segments = APIMetadata::getInstance()->getSegmentsMetadata($this->idSite); diff --git a/plugins/SegmentEditor/javascripts/Segmentation.js b/plugins/SegmentEditor/javascripts/Segmentation.js index ec1e8f23b8..2ffd7dac57 100644 --- a/plugins/SegmentEditor/javascripts/Segmentation.js +++ b/plugins/SegmentEditor/javascripts/Segmentation.js @@ -85,7 +85,7 @@ Segmentation = (function($) { var name = $(foundItems).first().find("span.segname").text(); title.text(name); } else { - title.text("Custom Segment"); + title.text(_pk_translate('SegmentEditor_CustomSegment')); } segmentationTitle.html(title); } diff --git a/plugins/SegmentEditor/lang/en.json b/plugins/SegmentEditor/lang/en.json index 933ac73884..a9ba4382e0 100644 --- a/plugins/SegmentEditor/lang/en.json +++ b/plugins/SegmentEditor/lang/en.json @@ -6,7 +6,7 @@ "AreYouSureDeleteSegment": "Are you sure you want to delete this segment?", "AutoArchivePreProcessed": "segmented reports are pre-processed (faster, requires cron)", "AutoArchiveRealTime": "segmented reports are processed in real time", - "ChooseASegment": "Choose a segment", + "ChooseASegment": "Choose a segment, currently selected segment: %s", "DataAvailableAtLaterDate": "Your segmented analytics reports will be available later. We apologize for the inconvenience.", "DefaultAllVisits": "All visits", "DragDropCondition": "Drag & Drop condition", @@ -27,6 +27,9 @@ "YouMustBeLoggedInToCreateSegments": "You must be logged in to create and edit custom visitor segments.", "YouDontHaveAccessToCreateSegments": "You don't have the required access level to create and edit segments.", "AddingSegmentForAllWebsitesDisabled": "Adding segments for all websites has been disabled.", - "SegmentXIsAUnionOf": "%s is a union of these segments:" + "SegmentXIsAUnionOf": "%s is a union of these segments:", + "CustomSegment": "Custom Segment", + "SegmentOperatorIsNullOrEmpty": "is null or empty", + "SegmentOperatorIsNotNullNorEmpty": "is not null nor empty" } }
\ No newline at end of file diff --git a/plugins/SegmentEditor/templates/_segmentSelector.twig b/plugins/SegmentEditor/templates/_segmentSelector.twig index f2d53b60c7..c14921a046 100644 --- a/plugins/SegmentEditor/templates/_segmentSelector.twig +++ b/plugins/SegmentEditor/templates/_segmentSelector.twig @@ -1,5 +1,5 @@ <div class="SegmentEditor" style="display:none;"> - <div class="segmentationContainer listHtml" title="{{ 'SegmentEditor_ChooseASegment'|translate|e('html_attr') }}"> + <div class="segmentationContainer listHtml" title="{{ 'SegmentEditor_ChooseASegment'|translate(segmentDescription)|e('html_attr') }}"> <a class="title"><span class="icon icon-segment"></span><span class="segmentationTitle"></span></a> <div class="dropdown dropdown-body"> <div class="segmentFilterContainer"> diff --git a/plugins/SegmentEditor/tests/Integration/SegmentFormatterTest.php b/plugins/SegmentEditor/tests/Integration/SegmentFormatterTest.php new file mode 100644 index 0000000000..bc0f206784 --- /dev/null +++ b/plugins/SegmentEditor/tests/Integration/SegmentFormatterTest.php @@ -0,0 +1,110 @@ +<?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\SegmentEditor\tests\Integration; + +use Piwik\Plugins\SegmentEditor\SegmentFormatter; +use Piwik\Plugins\SegmentEditor\SegmentList; +use Piwik\Tests\Framework\Fixture; +use Piwik\Tests\Framework\Mock\FakeAccess; +use Piwik\Tests\Framework\TestCase\IntegrationTestCase; +use Piwik\Translate; +use Exception; + +/** + * @group SegmentFormatterTest + * @group SegmentFormatter + * @group SegmentEditor + * @group Plugins + */ +class SegmentFormatterTest extends IntegrationTestCase +{ + /** + * @var SegmentFormatter + */ + private $formatter; + + private $idSite; + + public function setUp() + { + parent::setUp(); + + $this->idSite = Fixture::createWebsite('2012-01-01 00:00:00'); + $this->formatter = new SegmentFormatter(new SegmentList()); + + Translate::loadAllTranslations(); + } + + public function tearDown() + { + Translate::reset(); + } + + public function test_getHumanReadable_noSegmentGiven_ShouldReturnDefaultSegment() + { + $readable = $this->formatter->getHumanReadable($segment = '', $this->idSite); + $this->assertSame('All visits', $readable); + } + + public function test_getHumanReadable_ShouldTranslateAMetric() + { + $readable = $this->formatter->getHumanReadable($segment = 'visitCount>5', $this->idSite); + $this->assertSame('Number of visits greater than "5"', $readable); + + $readable = $this->formatter->getHumanReadable($segment = 'visitCount==5', $this->idSite); + $this->assertSame('Number of visits equals "5"', $readable); + } + + public function test_getHumanReadable_ShouldTranslateADimension() + { + $readable = $this->formatter->getHumanReadable($segment = 'resolution=@1024', $this->idSite); + $this->assertSame('Resolution contains "1024"', $readable); + + $readable = $this->formatter->getHumanReadable($segment = 'resolution==1024x768', $this->idSite); + $this->assertSame('Resolution is "1024x768"', $readable); + } + + public function test_getHumanReadable_ShouldCombineMultipleSegmentDefinitionsWithBooleanOperator() + { + $readable = $this->formatter->getHumanReadable($segment = 'browserVersion!=1.0;browserEngine=$Trident', $this->idSite); + $this->assertSame('Browser version is not "1.0" and Browser engine ends with "Trident"', $readable); + + $readable = $this->formatter->getHumanReadable($segment = 'browserVersion!=1.0,browserEngine=$Trident', $this->idSite); + $this->assertSame('Browser version is not "1.0" or Browser engine ends with "Trident"', $readable); + } + + public function test_getHumanReadable_ShouldHandleAMissingValue() + { + $readable = $this->formatter->getHumanReadable($segment = 'browserVersion==', $this->idSite); + $this->assertSame('Browser version is null or empty', $readable); + + $readable = $this->formatter->getHumanReadable($segment = 'browserVersion!=', $this->idSite); + $this->assertSame('Browser version is not null nor empty', $readable); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage The segment 'noTexisTinG' does not exist + */ + public function test_getHumanReadable_ShouldThrowAnException_IfTheGivenSegmentNameDoesNotExist() + { + $this->formatter->getHumanReadable($segment = 'noTexisTinG==1.0', $this->idSite); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage The segment 'pageUrl=!1.0' is not valid. + */ + public function test_getHumanReadable_ShouldThrowAnException_IfSegmentCannotBeParsedBecauseOfInvalidFormat() + { + $invalidOperator = '=!'; + $this->formatter->getHumanReadable($segment = 'pageUrl' . $invalidOperator . '1.0', $this->idSite); + } + +} diff --git a/plugins/SegmentEditor/tests/Integration/SegmentListTest.php b/plugins/SegmentEditor/tests/Integration/SegmentListTest.php new file mode 100644 index 0000000000..3a90bb95ee --- /dev/null +++ b/plugins/SegmentEditor/tests/Integration/SegmentListTest.php @@ -0,0 +1,74 @@ +<?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\SegmentEditor\tests\Integration; + +use Piwik\Plugins\SegmentEditor\SegmentList; +use Piwik\Tests\Framework\Fixture; +use Piwik\Tests\Framework\Mock\FakeAccess; +use Piwik\Tests\Framework\TestCase\IntegrationTestCase; +use Exception; + +/** + * @group SegmentListTest + * @group SegmentList + * @group SegmentEditor + * @group Plugins + */ +class SegmentListTest extends IntegrationTestCase +{ + /** + * @var SegmentList + */ + private $list; + + private $idSite; + + public function setUp() + { + parent::setUp(); + + $this->idSite = Fixture::createWebsite('2012-01-01 00:00:00'); + $this->list = new SegmentList(); + } + + public function test_findSegment_shouldFindSegmentByName_IfNameExists() + { + $segmentName = 'pageUrl'; + + $segment = $this->list->findSegment($segmentName, $this->idSite); + $this->assertInternalType('array', $segment); + $this->assertSame($segmentName, $segment['segment']); + } + + public function test_findSegment_shouldNotFindSegmentByName_IfNameDoesNotExist() + { + $segment = $this->list->findSegment('aNyNotExisTinGSegmEnt', $this->idSite); + $this->assertNull($segment); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage checkUserHasViewAccess + */ + public function test_findSegment_ShouldThrowException_IfNotEnoughPermission() + { + FakeAccess::clearAccess($superUser = false, array(1)); + + $segment = $this->list->findSegment('pageUrl', 999); + $this->assertNull($segment); + } + + public function provideContainerConfig() + { + return array( + 'Piwik\Access' => new FakeAccess() + ); + } + +} diff --git a/plugins/TestRunner/Commands/TestsRunUI.php b/plugins/TestRunner/Commands/TestsRunUI.php index 4ca7285c1d..3a9a06c080 100644 --- a/plugins/TestRunner/Commands/TestsRunUI.php +++ b/plugins/TestRunner/Commands/TestsRunUI.php @@ -26,7 +26,7 @@ class TestsRunUI extends ConsoleCommand \nRun one spec: \n./console tests:run-ui UIIntegrationTest "); - $this->addArgument('specs', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Run only a specific test spec. Separate multiple specs by comma, for instance UIIntegrationTest ', array()); + $this->addArgument('specs', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Run only a specific test spec. Separate multiple specs by a space, for instance UIIntegrationTest ', array()); $this->addOption("persist-fixture-data", null, InputOption::VALUE_NONE, "Persist test data in a database and do not execute tear down."); $this->addOption('keep-symlinks', null, InputOption::VALUE_NONE, "Keep recursive directory symlinks so test pages can be viewed in a browser."); $this->addOption('print-logs', null, InputOption::VALUE_NONE, "Print webpage logs even if tests succeed."); diff --git a/plugins/TestRunner/Commands/TestsSetupFixture.php b/plugins/TestRunner/Commands/TestsSetupFixture.php index baea8f70ff..565a81122a 100644 --- a/plugins/TestRunner/Commands/TestsSetupFixture.php +++ b/plugins/TestRunner/Commands/TestsSetupFixture.php @@ -192,10 +192,7 @@ class TestsSetupFixture extends ConsoleCommand ); foreach ($optionsToOverride as $configOption => $value) { if ($value) { - $configOverride = $testingEnvironment->configOverride; - $configOverride['database_tests'][$configOption] = $configOverride['database'][$configOption] = $value; - $testingEnvironment->configOverride = $configOverride; - + $testingEnvironment->overrideConfig('database_tests', $configOption, $value); Config::getInstance()->database[$configOption] = $value; } } diff --git a/plugins/Transitions/javascripts/transitions.js b/plugins/Transitions/javascripts/transitions.js index cb98e3d045..a11f6860c6 100644 --- a/plugins/Transitions/javascripts/transitions.js +++ b/plugins/Transitions/javascripts/transitions.js @@ -30,6 +30,10 @@ DataTable_RowActions_Transitions.isPageTitleReport = function (module, action) { return module == 'Actions' && (action == 'getPageTitles' || action == 'getPageTitlesFollowingSiteSearch'); }; +DataTable_RowActions_Transitions.isActionCustomDimensionReport = function (params) { + return params.module == 'CustomDimensions' && params.action == 'getCustomDimension' && params.scopeOfDimension && params.scopeOfDimension === 'action'; +}; + DataTable_RowActions_Transitions.prototype.trigger = function (tr, e, subTableLabel) { var link = tr.find('> td:first > a').attr('href'); link = $('<textarea>').html(link).val(); // remove html entities @@ -40,6 +44,27 @@ DataTable_RowActions_Transitions.prototype.trigger = function (tr, e, subTableLa this.openPopover('url:' + link); } else if (DataTable_RowActions_Transitions.isPageTitleReport(module, action)) { DataTable_RowAction.prototype.trigger.apply(this, [tr, e, subTableLabel]); + } else if (DataTable_RowActions_Transitions.isActionCustomDimensionReport(this.dataTable.param)) { + + var label = this.getLabelFromTr(tr); + if (label && label.substr(0, 1) === '@') { + label = label.substr(1); + } + + var subtable = tr.closest('table'); + if (subtable.is('.subDataTable')) { + var prev = subtable.closest('tr').prev(); + var segment = prev.attr('data-segment-filter'); + if (segment) { + label = unescape(label); + if (this.transitions === null) { + this.transitions = new Piwik_Transitions('url', label, this, segment); + } else { + this.transitions.reset('url', label, segment); + } + this.transitions.showPopover(); + } + } } else { alert('Transitions can\'t be used on this report.'); } @@ -95,7 +120,8 @@ DataTable_RowActions_Registry.register({ isAvailableOnReport: function (dataTableParams) { return ( DataTable_RowActions_Transitions.isPageUrlReport(dataTableParams.module, dataTableParams.action) || - DataTable_RowActions_Transitions.isPageTitleReport(dataTableParams.module, dataTableParams.action) + DataTable_RowActions_Transitions.isPageTitleReport(dataTableParams.module, dataTableParams.action) || + DataTable_RowActions_Transitions.isActionCustomDimensionReport(dataTableParams) ); }, @@ -109,6 +135,11 @@ DataTable_RowActions_Registry.register({ // not on page url without link (i.e. "Page URL not defined") return false; } + if (DataTable_RowActions_Transitions.isActionCustomDimensionReport(dataTableParams) + && !tr.parents('table').first().hasClass('subDataTable')) { + // only show it in subtables of custom dimensions + return false; + } return true; } @@ -118,8 +149,8 @@ DataTable_RowActions_Registry.register({ // TRANSITIONS IMPLEMENTATION // -function Piwik_Transitions(actionType, actionName, rowAction) { - this.reset(actionType, actionName); +function Piwik_Transitions(actionType, actionName, rowAction, segment) { + this.reset(actionType, actionName, segment); this.rowAction = rowAction; this.ajax = new Piwik_Transitions_Ajax(); @@ -129,9 +160,10 @@ function Piwik_Transitions(actionType, actionName, rowAction) { this.rightGroups = ['followingPages', 'followingSiteSearches', 'downloads', 'outlinks']; } -Piwik_Transitions.prototype.reset = function (actionType, actionName) { +Piwik_Transitions.prototype.reset = function (actionType, actionName, segment) { this.actionType = actionType; this.actionName = actionName; + this.segment = segment; this.popover = null; this.canvas = null; @@ -179,7 +211,7 @@ Piwik_Transitions.prototype.showPopover = function () { } // load the data - self.model.loadData(self.actionType, self.actionName, function () { + self.model.loadData(self.actionType, self.actionName, self.segment, function () { if (typeof Piwik_Transitions.popoverHtml == 'undefined') { // html not there yet callbackForHtml = bothLoaded; @@ -1249,7 +1281,7 @@ Piwik_Transitions_Model.prototype.htmlLoaded = function () { }; }; -Piwik_Transitions_Model.prototype.loadData = function (actionType, actionName, callback) { +Piwik_Transitions_Model.prototype.loadData = function (actionType, actionName, segment, callback) { var self = this; this.pageviews = 0; @@ -1287,11 +1319,16 @@ Piwik_Transitions_Model.prototype.loadData = function (actionType, actionName, c this.date = ''; - this.ajax.callApi('Transitions.getTransitionsForAction', { - actionType: actionType, - actionName: actionName, - expanded: 1 - }, + var params = { + actionType: actionType, + actionName: actionName, + expanded: 1 + }; + if (segment) { + params.segment = segment; + } + + this.ajax.callApi('Transitions.getTransitionsForAction', params, function (report) { self.date = report.date; |