From 89eb98b2fdaf3fa72a4a038daa050764f904ecc6 Mon Sep 17 00:00:00 2001 From: Thomas Steur <thomas.steur@gmail.com> Date: Fri, 30 Oct 2015 20:09:19 +0000 Subject: [PATCH] added screen to see custom variable usages --- core/DataTable/Renderer/Csv.php | 32 ++++- plugins/CoreHome/CoreHome.php | 1 + .../angularjs/common/filters/ucfirst.js | 21 ++++ plugins/CustomVariables/API.php | 56 +++++++++ plugins/CustomVariables/Archiver.php | 35 +++++- plugins/CustomVariables/Controller.php | 13 ++ plugins/CustomVariables/CustomVariables.php | 33 ++++- plugins/CustomVariables/Menu.php | 33 +++++ plugins/CustomVariables/Model.php | 44 +++---- .../CustomVariablesRequestProcessor.php | 4 +- .../manage-custom-vars.controller.js | 35 ++++++ .../manage-custom-vars.directive.html | 41 +++++++ .../manage-custom-vars.directive.js | 26 ++++ .../manage-custom-vars.directive.less | 10 ++ .../manage-custom-vars.model.js | 36 ++++++ plugins/CustomVariables/lang/en.json | 12 +- plugins/CustomVariables/templates/manage.twig | 11 ++ .../tests/Integration/ModelTest.php | 2 +- ...CustomVariables.getCustomVariables_day.xml | 96 +++++++++++++++ plugins/CustomVariables/tests/UI/.gitignore | 2 + .../tests/UI/CustomVariables_spec.js | 31 +++++ .../CustomVariables_create.png | Bin 0 -> 19928 bytes .../CustomVariables_link_in_menu.png | Bin 0 -> 5143 bytes .../CustomVariables_manage.png | Bin 0 -> 44125 bytes ...CustomVariables.getCustomVariables_day.xml | 24 ++++ ...stomVariables.getCustomVariables_month.xml | 48 ++++++++ ...Logs__CustomVariables.getUsagesOfSlots.xml | 113 ++++++++++++++++++ ...sits__CustomVariables.getUsagesOfSlots.xml | 63 ++++++++++ ...port__CustomVariables.getUsagesOfSlots.xml | 63 ++++++++++ ...CustomVariables.getCustomVariables_day.xml | 42 +++++++ ...stomVariables.getCustomVariables_month.xml | 30 +++++ ...Site_lastN__API.getProcessedReport_day.xml | 24 ++++ ...te_lastN__API.getProcessedReport_month.xml | 12 ++ ...CustomVariables.getCustomVariables_day.xml | 42 +++++++ ...Last__CustomVariables.getUsagesOfSlots.xml | 63 ++++++++++ ...isit__CustomVariables.getUsagesOfSlots.xml | 63 ++++++++++ ...stomVariables.getCustomVariables_range.xml | 46 +++++++ ...stomVariables.getCustomVariables_range.xml | 46 +++++++ ...CustomVariables.getCustomVariables_day.xml | 12 ++ ...CustomVariables.getCustomVariables_day.xml | 12 ++ ...CustomVariables.getCustomVariables_day.xml | 64 ++++++++++ ...ustomVariables.getCustomVariables_week.xml | 64 ++++++++++ ...CustomVariables.getCustomVariables_day.xml | 46 +++++++ ...ustomVariables.getCustomVariables_week.xml | 46 +++++++ ...CustomVariables.getCustomVariables_day.xml | 40 +++++++ ...ustomVariables.getCustomVariables_week.xml | 40 +++++++ .../Unit/DataTable/Renderer/CSVTest.php | 35 ++++++ 47 files changed, 1583 insertions(+), 29 deletions(-) create mode 100644 plugins/CoreHome/angularjs/common/filters/ucfirst.js create mode 100644 plugins/CustomVariables/Menu.php create mode 100644 plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.controller.js create mode 100644 plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.html create mode 100644 plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.js create mode 100644 plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.less create mode 100644 plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.model.js create mode 100644 plugins/CustomVariables/templates/manage.twig create mode 100644 plugins/CustomVariables/tests/UI/.gitignore create mode 100644 plugins/CustomVariables/tests/UI/CustomVariables_spec.js create mode 100644 plugins/CustomVariables/tests/UI/expected-ui-screenshots/CustomVariables_create.png create mode 100644 plugins/CustomVariables/tests/UI/expected-ui-screenshots/CustomVariables_link_in_menu.png create mode 100644 plugins/CustomVariables/tests/UI/expected-ui-screenshots/CustomVariables_manage.png create mode 100644 tests/PHPUnit/System/expected/test_ImportLogs__CustomVariables.getUsagesOfSlots.xml create mode 100644 tests/PHPUnit/System/expected/test_OneVisitorTwoVisits__CustomVariables.getUsagesOfSlots.xml create mode 100644 tests/PHPUnit/System/expected/test_OneVisitorTwoVisits_withCookieSupport__CustomVariables.getUsagesOfSlots.xml create mode 100644 tests/PHPUnit/System/expected/test_noVisit_PeriodIsLast__CustomVariables.getUsagesOfSlots.xml create mode 100644 tests/PHPUnit/System/expected/test_noVisit__CustomVariables.getUsagesOfSlots.xml diff --git a/core/DataTable/Renderer/Csv.php b/core/DataTable/Renderer/Csv.php index 4eee1949b7..c3fb08b15a 100644 --- a/core/DataTable/Renderer/Csv.php +++ b/core/DataTable/Renderer/Csv.php @@ -70,6 +70,8 @@ class Csv extends Renderer */ const NO_DATA_AVAILABLE = 'No data available'; + private $unsupportedColumns = array(); + /** * Computes the dataTable output and returns the string/binary * @@ -213,6 +215,12 @@ class Csv extends Renderer */ private function getHeaderLine($columnMetrics) { + foreach ($columnMetrics as $index => $value) { + if (in_array($value, $this->unsupportedColumns)) { + unset($columnMetrics[$index]); + } + } + if ($this->translateColumnNames) { $columnMetrics = $this->translateColumnNames($columnMetrics); } @@ -391,12 +399,23 @@ class Csv extends Renderer $name = 'metadata_' . $name; } - $csvRow[$name] = $value; + if (is_array($value)) { + if (!in_array($name, $this->unsupportedColumns)) { + $this->unsupportedColumns[] = $name; + } + } else { + $csvRow[$name] = $value; + } + } } foreach ($csvRow as $name => $value) { - $allColumns[$name] = true; + if (in_array($name, $this->unsupportedColumns)) { + unset($allColumns[$name]); + } else { + $allColumns[$name] = true; + } } if ($this->exportIdSubtable) { @@ -410,6 +429,15 @@ class Csv extends Renderer $csv[] = $csvRow; } + + if (!empty($this->unsupportedColumns)) { + foreach ($this->unsupportedColumns as $unsupportedColumn) { + foreach ($csv as $index => $row) { + unset($row[$index][$unsupportedColumn]); + } + } + } + return $csv; } diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php index f2d788cd54..7cf82cfd3b 100644 --- a/plugins/CoreHome/CoreHome.php +++ b/plugins/CoreHome/CoreHome.php @@ -134,6 +134,7 @@ class CoreHome extends \Piwik\Plugin $jsFiles[] = "plugins/CoreHome/angularjs/common/filters/trim.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/filters/pretty-url.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/filters/htmldecode.js"; + $jsFiles[] = "plugins/CoreHome/angularjs/common/filters/ucfirst.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/directive.module.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js"; diff --git a/plugins/CoreHome/angularjs/common/filters/ucfirst.js b/plugins/CoreHome/angularjs/common/filters/ucfirst.js new file mode 100644 index 0000000000..34b3460be8 --- /dev/null +++ b/plugins/CoreHome/angularjs/common/filters/ucfirst.js @@ -0,0 +1,21 @@ +/*! + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +(function () { + angular.module('piwikApp.filter').filter('ucfirst', ucfirst); + + function ucfirst() { + + return function(value) { + if (!value) { + return value; + } + + var firstLetter = (value + '').charAt(0).toUpperCase(); + return firstLetter + value.substr(1); + }; + } +})(); diff --git a/plugins/CustomVariables/API.php b/plugins/CustomVariables/API.php index fa3a99dbca..57832927e5 100644 --- a/plugins/CustomVariables/API.php +++ b/plugins/CustomVariables/API.php @@ -8,10 +8,12 @@ */ namespace Piwik\Plugins\CustomVariables; +use Piwik\API\Request; use Piwik\Archive; use Piwik\DataTable; use Piwik\Date; use Piwik\Metrics; +use Piwik\Piwik; use Piwik\Plugins\Actions\Actions\ActionSiteSearch; /** @@ -71,6 +73,7 @@ class API extends \Piwik\Plugin\API } } + if ($flat) { $dataTable->filterSubtables('Piwik\Plugins\CustomVariables\DataTable\Filter\CustomVariablesValuesFromNameId'); } else { @@ -109,9 +112,62 @@ class API extends \Piwik\Plugin\API // Hack Ecommerce product price tracking to display correctly $dataTable->renameColumn('price_viewed', 'price'); } + $dataTable->filter('Piwik\Plugins\CustomVariables\DataTable\Filter\CustomVariablesValuesFromNameId'); return $dataTable; } + + /** + * Get a list of all available custom variable slots (scope + index) and which names have been used so far in + * each slot since the beginning of the website. + * + * @param int $idSite + * @return array + */ + public function getUsagesOfSlots($idSite) + { + Piwik::checkUserHasAdminAccess($idSite); + + $numVars = CustomVariables::getNumUsableCustomVariables(); + + $usedCustomVariables = array( + 'visit' => array_fill(1, $numVars, array()), + 'page' => array_fill(1, $numVars, array()), + ); + + /** @var DataTable $customVarUsages */ + $customVarUsages = Request::processRequest('CustomVariables.getCustomVariables', + array('idSite' => $idSite, 'period' => 'range', 'date' => '2008-12-12,today', + 'format' => 'original', 'serialize' => '0') + ); + + foreach ($customVarUsages->getRows() as $row) { + $slots = $row->getMetadata('slots'); + + if (!empty($slots)) { + foreach ($slots as $slot) { + $usedCustomVariables[$slot['scope']][$slot['index']][] = array( + 'name' => $row->getColumn('label'), + 'nb_visits' => $row->getColumn('nb_visits'), + 'nb_actions' => $row->getColumn('nb_actions'), + ); + } + } + } + + $grouped = array(); + foreach ($usedCustomVariables as $scope => $scopes) { + foreach ($scopes as $index => $cvars) { + $grouped[] = array( + 'scope' => $scope, + 'index' => $index, + 'usages' => $cvars + ); + } + } + + return $grouped; + } } diff --git a/plugins/CustomVariables/Archiver.php b/plugins/CustomVariables/Archiver.php index bc43cbc8dd..4a53ab78df 100644 --- a/plugins/CustomVariables/Archiver.php +++ b/plugins/CustomVariables/Archiver.php @@ -8,7 +8,6 @@ */ namespace Piwik\Plugins\CustomVariables; -use Piwik\Common; use Piwik\Config; use Piwik\DataAccess\LogAggregator; use Piwik\DataArray; @@ -35,6 +34,9 @@ class Archiver extends \Piwik\Plugin\Archiver protected $maximumRowsInSubDataTable; protected $newEmptyRow; + private $metadata = array(); + private $metadataFlat = array(); + function __construct($processor) { parent::__construct($processor); @@ -74,6 +76,16 @@ class Archiver extends \Piwik\Plugin\Archiver $this->removeVisitsMetricsFromActionsAggregate(); $this->dataArray->enrichMetricsWithConversions(); $table = $this->dataArray->asDataTable(); + + foreach ($table->getRows() as $row) { + $label = $row->getColumn('label'); + if (!empty($this->metadata[$label])) { + foreach ($this->metadata[$label] as $name => $value) { + $row->addMetadata($name, $value); + } + } + } + $blob = $table->getSerialized( $this->maximumRowsInDataTableLevelZero, $this->maximumRowsInSubDataTable, $columnToSort = Metrics::INDEX_NB_VISITS @@ -118,6 +130,8 @@ class Archiver extends \Piwik\Plugin\Archiver $key = $row[$keyField]; $value = $this->cleanCustomVarValue($row[$valueField]); + $this->addMetadata($keyField, $key, Model::SCOPE_VISIT); + $this->dataArray->sumMetricsVisits($key, $row); $this->dataArray->sumMetricsVisitsPivot($key, $value, $row); } @@ -137,6 +151,8 @@ class Archiver extends \Piwik\Plugin\Archiver $key = $row[$keyField]; $value = $this->cleanCustomVarValue($row[$valueField]); + $this->addMetadata($keyField, $key, Model::SCOPE_PAGE); + $alreadyAggregated = $this->aggregateEcommerceCategories($key, $value, $row); if (!$alreadyAggregated) { $this->aggregateActionByKeyAndValue($key, $value, $row); @@ -145,6 +161,22 @@ class Archiver extends \Piwik\Plugin\Archiver } } + private function addMetadata($keyField, $label, $scope) + { + $index = (int) str_replace('custom_var_k', '', $keyField); + + if (!array_key_exists($label, $this->metadata)) { + $this->metadata[$label] = array('slots' => array()); + } + + $uniqueId = $label . 'scope' . $scope . 'index' . $index; + + if (!isset($this->metadataFlat[$uniqueId])) { + $this->metadata[$label]['slots'][] = array('scope' => $scope, 'index' => $index); + $this->metadataFlat[$uniqueId] = true; + } + } + /** * @param string $key * @param string $value @@ -205,6 +237,7 @@ class Archiver extends \Piwik\Plugin\Archiver } while ($row = $query->fetch()) { $key = $row[$keyField]; + $value = $this->cleanCustomVarValue($row[$valueField]); $this->dataArray->sumMetricsGoals($key, $row); $this->dataArray->sumMetricsGoalsPivot($key, $value, $row); diff --git a/plugins/CustomVariables/Controller.php b/plugins/CustomVariables/Controller.php index 59a4a949de..e73e58b257 100644 --- a/plugins/CustomVariables/Controller.php +++ b/plugins/CustomVariables/Controller.php @@ -8,7 +8,20 @@ */ namespace Piwik\Plugins\CustomVariables; +use Piwik\Common; +use Piwik\DataTable; +use Piwik\Piwik; + class Controller extends \Piwik\Plugin\Controller { + public function manage() + { + $idSite = Common::getRequestVar('idSite'); + + Piwik::checkUserHasAdminAccess($idSite); + + return $this->renderTemplate('manage', array()); + } + } diff --git a/plugins/CustomVariables/CustomVariables.php b/plugins/CustomVariables/CustomVariables.php index b8a57ad6a6..03238212f1 100644 --- a/plugins/CustomVariables/CustomVariables.php +++ b/plugins/CustomVariables/CustomVariables.php @@ -22,7 +22,10 @@ class CustomVariables extends \Piwik\Plugin { return array( 'API.getSegmentDimensionMetadata' => 'getSegmentsMetadata', - 'Live.getAllVisitorDetails' => 'extendVisitorDetails' + 'Live.getAllVisitorDetails' => 'extendVisitorDetails', + 'AssetManager.getJavaScriptFiles' => 'getJsFiles', + 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', + 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', ); } @@ -144,4 +147,32 @@ class CustomVariables extends \Piwik\Plugin } } + public function getClientSideTranslationKeys(&$translationKeys) + { + $translationKeys[] = 'CustomVariables_CustomVariables'; + $translationKeys[] = 'CustomVariables_ManageDescription'; + $translationKeys[] = 'CustomVariables_Scope'; + $translationKeys[] = 'CustomVariables_Index'; + $translationKeys[] = 'CustomVariables_Usages'; + $translationKeys[] = 'CustomVariables_Unused'; + $translationKeys[] = 'CustomVariables_CreateNewSlot'; + $translationKeys[] = 'CustomVariables_UsageDetails'; + $translationKeys[] = 'CustomVariables_CurrentAvailableCustomVariables'; + $translationKeys[] = 'CustomVariables_ToCreateCustomVarExecute'; + $translationKeys[] = 'CustomVariables_CreatingCustomVariableTakesTime'; + $translationKeys[] = 'General_Loading'; + } + + public function getStylesheetFiles(&$stylesheets) + { + $stylesheets[] = "plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.less"; + } + + public function getJsFiles(&$jsFiles) + { + $jsFiles[] = "plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.model.js"; + $jsFiles[] = "plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.controller.js"; + $jsFiles[] = "plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.js"; + } + } diff --git a/plugins/CustomVariables/Menu.php b/plugins/CustomVariables/Menu.php new file mode 100644 index 0000000000..80e1d78193 --- /dev/null +++ b/plugins/CustomVariables/Menu.php @@ -0,0 +1,33 @@ +<?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\CustomVariables; + +use Piwik\Common; +use Piwik\Menu\MenuUser; +use Piwik\Piwik; +use Piwik\Plugins\UsersManager\UserPreferences; + +/** + * This class allows you to add, remove or rename menu items. + * To configure a menu (such as Admin Menu, Reporting Menu, User Menu...) simply call the corresponding methods as + * described in the API-Reference http://developer.piwik.org/api-reference/Piwik/Menu/MenuAbstract + */ +class Menu extends \Piwik\Plugin\Menu +{ + public function configureUserMenu(MenuUser $menu) + { + $userPreferences = new UserPreferences(); + $default = $userPreferences->getDefaultWebsiteId(); + $idSite = Common::getRequestVar('idSite', $default, 'int'); + + if (Piwik::isUserHasAdminAccess($idSite)) { + $menu->addManageItem('Custom Variables', $this->urlForAction('manage'), $orderId = 30); + } + } +} diff --git a/plugins/CustomVariables/Model.php b/plugins/CustomVariables/Model.php index 9d98a352fa..235809e1da 100644 --- a/plugins/CustomVariables/Model.php +++ b/plugins/CustomVariables/Model.php @@ -15,12 +15,14 @@ use Piwik\Log; class Model { - const SCOPE_PAGE = 'log_link_visit_action'; - const SCOPE_VISIT = 'log_visit'; - const SCOPE_CONVERSION = 'log_conversion'; const DEFAULT_CUSTOM_VAR_COUNT = 5; + const SCOPE_PAGE = 'page'; + const SCOPE_VISIT = 'visit'; + const SCOPE_CONVERSION = 'conversion'; + private $scope = null; + private $table = null; public function __construct($scope) { @@ -29,21 +31,27 @@ class Model } $this->scope = $scope; + $this->table = Common::prefixTable($this->getTableNameFromScope($scope)); } - public function getScopeName() + private function getTableNameFromScope($scope) { // actually we should have a class for each scope but don't want to overengineer it for now - switch ($this->scope) { + switch ($scope) { case self::SCOPE_PAGE: - return 'Page'; + return 'log_link_visit_action'; case self::SCOPE_VISIT: - return 'Visit'; + return 'log_visit'; case self::SCOPE_CONVERSION: - return 'Conversion'; + return 'log_conversion'; } } + public function getScopeName() + { + return ucfirst($this->scope); + } + /** * @see getHighestCustomVarIndex() * @return int @@ -96,8 +104,7 @@ class Model private function getCustomVarColumnNames() { - $dbTable = $this->getDbTableName(); - $columns = Db::getColumnNamesFromTable($dbTable); + $columns = Db::getColumnNamesFromTable($this->table); $customVarColumns = array_filter($columns, function ($column) { return false !== strpos($column, 'custom_var_'); @@ -108,14 +115,13 @@ class Model public function removeCustomVariable() { - $dbTable = $this->getDbTableName(); - $index = $this->getHighestCustomVarIndex(); + $index = $this->getHighestCustomVarIndex(); if ($index < 1) { return null; } - Db::exec(sprintf('ALTER TABLE %s ', $dbTable) + Db::exec(sprintf('ALTER TABLE %s ', $this->table) . sprintf('DROP COLUMN custom_var_k%d,', $index) . sprintf('DROP COLUMN custom_var_v%d;', $index)); @@ -124,22 +130,16 @@ class Model public function addCustomVariable() { - $dbTable = $this->getDbTableName(); - $index = $this->getHighestCustomVarIndex() + 1; - $maxLen = CustomVariables::getMaxLengthCustomVariables(); + $index = $this->getHighestCustomVarIndex() + 1; + $maxLen = CustomVariables::getMaxLengthCustomVariables(); - Db::exec(sprintf('ALTER TABLE %s ', $dbTable) + Db::exec(sprintf('ALTER TABLE %s ', $this->table) . sprintf('ADD COLUMN custom_var_k%d VARCHAR(%d) DEFAULT NULL,', $index, $maxLen) . sprintf('ADD COLUMN custom_var_v%d VARCHAR(%d) DEFAULT NULL;', $index, $maxLen)); return $index; } - private function getDbTableName() - { - return Common::prefixTable($this->scope); - } - public static function getCustomVariableIndexFromFieldName($fieldName) { $onlyNumber = str_replace(array('custom_var_k', 'custom_var_v'), '', $fieldName); diff --git a/plugins/CustomVariables/Tracker/CustomVariablesRequestProcessor.php b/plugins/CustomVariables/Tracker/CustomVariablesRequestProcessor.php index 44e6d59350..720aca8431 100644 --- a/plugins/CustomVariables/Tracker/CustomVariablesRequestProcessor.php +++ b/plugins/CustomVariables/Tracker/CustomVariablesRequestProcessor.php @@ -9,6 +9,8 @@ namespace Piwik\Plugins\CustomVariables\Tracker; use Piwik\Common; +use Piwik\Plugins\CustomVariables\CustomVariables; +use Piwik\Plugins\CustomVariables\Model; use Piwik\Tracker\Request; use Piwik\Tracker\RequestProcessor; use Piwik\Tracker\Visit\VisitProperties; @@ -36,7 +38,7 @@ class CustomVariablesRequestProcessor extends RequestProcessor public function processRequestParams(VisitProperties $visitProperties, Request $request) { // TODO: re-add optimization where if custom variables exist in request, don't bother selecting them in Visitor - $visitorCustomVariables = $request->getCustomVariables($scope = 'visit'); + $visitorCustomVariables = $request->getCustomVariables($scope = Model::SCOPE_VISIT); if (!empty($visitorCustomVariables)) { Common::printDebug("Visit level Custom Variables: "); Common::printDebug($visitorCustomVariables); 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 new file mode 100644 index 0000000000..4b6b1c213d --- /dev/null +++ b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.controller.js @@ -0,0 +1,35 @@ +/*! + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +(function () { + angular.module('piwikApp').controller('ManageCustomVarsController', ManageCustomVarsController); + + ManageCustomVarsController.$inject = ['manageCustomVarsModel', 'piwik', '$filter']; + + function ManageCustomVarsController(manageCustomVarsModel, piwik, $filter) { + manageCustomVarsModel.fetchUsages(); + + this.model = manageCustomVarsModel; + this.createCustomVariableSlot = function () { + var highestIndex = 5; + angular.forEach(manageCustomVarsModel.customVariables, function (customVar) { + if (customVar.index > highestIndex) { + highestIndex = customVar.index; + } + }); + + var translate = $filter('translate'); + + var command = './console customvariables:set-max-custom-variables ' + (highestIndex + 1); + var text = translate('CustomVariables_CreatingCustomVariableTakesTime'); + text += '<br /><br />' + translate('CustomVariables_CurrentAvailableCustomVariables', '<strong>' + highestIndex + '</strong>'); + text += '<br /><br />' + translate('CustomVariables_ToCreateCustomVarExecute'); + text += '<br /><br /><code>' + command + '</code>'; + + piwik.helper.modalConfirm('<div class="ui-confirm" title="' + translate('CustomVariables_CreateNewSlot') + '">' + text + '<br /><br /></div>'); + } + } +})(); \ 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 new file mode 100644 index 0000000000..8cc7c60e60 --- /dev/null +++ b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.html @@ -0,0 +1,41 @@ +<div class="manageCustomVars"> + <h2 piwik-enriched-headline>{{ 'CustomVariables_CustomVariables'|translate }}</h2> + + {{ 'CustomVariables_ManageDescription'|translate }} + + <br /> + + <h3>{{ customVariables.scope }}</h3> + <table class="dataTable entityTable" style="max-width: 900px;"> + <thead> + <tr> + <th>{{'CustomVariables_Scope'|translate }}</th> + <th>{{'CustomVariables_Index'|translate }}</th> + <th>{{'CustomVariables_Usages'|translate }}</th> + </tr> + </thead> + <tbody> + <tr> + <td colspan="3" ng-show="manageCustomVars.model.isLoading">{{ 'General_Loading'|translate }}</td> + </tr> + <tr ng-repeat="customVariables in manageCustomVars.model.customVariables"> + <td class="scope">{{ customVariables.scope|ucfirst }}</td> + <td class="index">{{ customVariables.index }}</td> + <td> + <span ng-show="(customVariables.usages|length) === 0" + class="unused">{{'CustomVariables_Unused'|translate }}</span> + <span ng-show="customVariables.usages|length" ng-repeat="cvar in customVariables.usages|orderBy:'-nb_actions'"> + <span title="{{ 'CustomVariables_UsageDetails'|translate:cvar.nb_visits:cvar.nb_actions }}">{{ cvar.name }}</span><span ng-show="!$last">, </span> + </span> + </td> + </tr> + </tbody> + </table> + + <br/> + <a class="btn addCustomVar" ng-show="!manageCustomVars.model.isLoading" value="" + ng-click="manageCustomVars.createCustomVariableSlot()" + >{{ 'CustomVariables_CreateNewSlot'|translate }} <span class="icon-info"></span></a><br/> + + +</div> \ No newline at end of file diff --git a/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.js b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.js new file mode 100644 index 0000000000..1623d50b27 --- /dev/null +++ b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.js @@ -0,0 +1,26 @@ +/*! + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/** + * Usage: + * <div piwik-manage-custom-vars> + */ +(function () { + angular.module('piwikApp').directive('piwikManageCustomVars', piwikManageCustomVars); + + piwikManageCustomVars.$inject = ['piwik']; + + function piwikManageCustomVars(piwik){ + return { + restrict: 'A', + scope: {}, + templateUrl: 'plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.html?cb=' + piwik.cacheBuster, + controller: 'ManageCustomVarsController', + controllerAs: 'manageCustomVars' + }; + } +})(); \ No newline at end of file diff --git a/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.less b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.less new file mode 100644 index 0000000000..2d3e4e4f04 --- /dev/null +++ b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.directive.less @@ -0,0 +1,10 @@ +.manageCustomVars { + .unused { + color: @color-silver; + } + + .scope, .index { + width: 90px; + max-width: 90px; + } +} \ No newline at end of file diff --git a/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.model.js b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.model.js new file mode 100644 index 0000000000..3cc5b3d4b2 --- /dev/null +++ b/plugins/CustomVariables/angularjs/manage-custom-vars/manage-custom-vars.model.js @@ -0,0 +1,36 @@ +/*! + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +(function () { + angular.module('piwikApp').factory('manageCustomVarsModel', manageCustomVarsModel); + + manageCustomVarsModel.$inject = ['piwikApi']; + + function manageCustomVarsModel(piwikApi) { + + var model = { + customVariables : [], + extractions : [], + isLoading: false, + fetchUsages: fetchUsages + }; + + return model; + + function fetchUsages() { + + model.isLoading = true; + + piwikApi.fetch({method: 'CustomVariables.getUsagesOfSlots'}) + .then(function (customVariables) { + model.customVariables = customVariables; + })['finally'](function () { // .finally() is not IE8 compatible see https://github.com/angular/angular.js/commit/f078762d48d0d5d9796dcdf2cb0241198677582c + model.isLoading = false; + }); + } + + } +})(); \ No newline at end of file diff --git a/plugins/CustomVariables/lang/en.json b/plugins/CustomVariables/lang/en.json index 7d99f97bf2..61033b2757 100644 --- a/plugins/CustomVariables/lang/en.json +++ b/plugins/CustomVariables/lang/en.json @@ -6,6 +6,16 @@ "CustomVariablesReportDocumentation": "This report contains information about your Custom Variables. Click on a variable name to see the distribution of the values. %s For more information about Custom Variables in general, read the %sCustom Variables documentation on piwik.org%s", "PluginDescription": "Custom Variables are (name, value) pairs that you can assign using the Javascript API to visitors or any of their action. Piwik will then report how many visits, pages, conversions for each of these custom names and values. View the detailed Custom Variables for each user and action in the Visitor Log.<br />Required to use <a href=\"http://piwik.org/docs/ecommerce-analytics/\">Ecommerce Analytics</a> feature!", "ScopePage": "scope page", - "ScopeVisit": "scope visit" + "ScopeVisit": "scope visit", + "ManageDescription": "This overview shows all custom variable slots and their usages. The names within each slot are ordered by how often they were used in total.", + "Scope": "Scope", + "Index": "Index", + "Usages": "Usages", + "Unused": "Unused", + "CreateNewSlot": "Create a new Custom Variable slot", + "UsageDetails": "%s visits and %s actions since creation of this website.", + "CreatingCustomVariableTakesTime": "Creating a new custom variable slot can take a long time depending on the size of your database. Therefore it is only possible to do this via a command which needs to be executed on the command line.", + "CurrentAvailableCustomVariables": "Currently you can use up to %s Custom Variables per site.", + "ToCreateCustomVarExecute": "To create a new custom variable slot execute the following command within your Piwik installation: " } } \ No newline at end of file diff --git a/plugins/CustomVariables/templates/manage.twig b/plugins/CustomVariables/templates/manage.twig new file mode 100644 index 0000000000..fa7a085aa9 --- /dev/null +++ b/plugins/CustomVariables/templates/manage.twig @@ -0,0 +1,11 @@ +{% extends 'user.twig' %} + +{% block topcontrols %} + <div class="top_bar_sites_selector piwikTopControl"> + <div piwik-siteselector class="sites_autocomplete"></div> + </div> +{% endblock %} + +{% block content %} + <div piwik-manage-custom-vars> +{% endblock %} \ No newline at end of file diff --git a/plugins/CustomVariables/tests/Integration/ModelTest.php b/plugins/CustomVariables/tests/Integration/ModelTest.php index 128e5b09ef..905a5f6a1d 100644 --- a/plugins/CustomVariables/tests/Integration/ModelTest.php +++ b/plugins/CustomVariables/tests/Integration/ModelTest.php @@ -19,7 +19,7 @@ use Piwik\Tests\Framework\TestCase\IntegrationTestCase; */ class ModelTest extends IntegrationTestCase { - private static $cvarScopes = array('log_link_visit_action', 'log_visit', 'log_conversion'); + private static $cvarScopes = array('page', 'visit', 'conversion'); public function setUp() { diff --git a/plugins/CustomVariables/tests/System/expected/test_CustomVariablesSystemTest__CustomVariables.getCustomVariables_day.xml b/plugins/CustomVariables/tests/System/expected/test_CustomVariablesSystemTest__CustomVariables.getCustomVariables_day.xml index 3a5683bdc6..054f9b1e31 100644 --- a/plugins/CustomVariables/tests/System/expected/test_CustomVariablesSystemTest__CustomVariables.getCustomVariables_day.xml +++ b/plugins/CustomVariables/tests/System/expected/test_CustomVariablesSystemTest__CustomVariables.getCustomVariables_day.xml @@ -3,6 +3,12 @@ <row> <label>Name_PAGE_1</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Name_PAGE_1</segment> <subtable> <row> @@ -15,6 +21,12 @@ <row> <label>Name_PAGE_2</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==Name_PAGE_2</segment> <subtable> <row> @@ -27,6 +39,12 @@ <row> <label>Name_PAGE_3</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Name_PAGE_3</segment> <subtable> <row> @@ -39,6 +57,12 @@ <row> <label>Name_PAGE_4</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==Name_PAGE_4</segment> <subtable> <row> @@ -51,6 +75,12 @@ <row> <label>Name_PAGE_5</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Name_PAGE_5</segment> <subtable> <row> @@ -63,6 +93,12 @@ <row> <label>Name_PAGE_6</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>6</index> + </row> + </slots> <segment>customVariableName==Name_PAGE_6</segment> <subtable> <row> @@ -75,6 +111,12 @@ <row> <label>Name_PAGE_7</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>7</index> + </row> + </slots> <segment>customVariableName==Name_PAGE_7</segment> <subtable> <row> @@ -87,6 +129,12 @@ <row> <label>Name_PAGE_8</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>8</index> + </row> + </slots> <segment>customVariableName==Name_PAGE_8</segment> <subtable> <row> @@ -113,6 +161,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Name_VISIT_1</segment> <subtable> <row> @@ -152,6 +206,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==Name_VISIT_2</segment> <subtable> <row> @@ -191,6 +251,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Name_VISIT_3</segment> <subtable> <row> @@ -230,6 +296,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==Name_VISIT_4</segment> <subtable> <row> @@ -269,6 +341,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Name_VISIT_5</segment> <subtable> <row> @@ -308,6 +386,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>6</index> + </row> + </slots> <segment>customVariableName==Name_VISIT_6</segment> <subtable> <row> @@ -347,6 +431,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>7</index> + </row> + </slots> <segment>customVariableName==Name_VISIT_7</segment> <subtable> <row> @@ -386,6 +476,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>8</index> + </row> + </slots> <segment>customVariableName==Name_VISIT_8</segment> <subtable> <row> diff --git a/plugins/CustomVariables/tests/UI/.gitignore b/plugins/CustomVariables/tests/UI/.gitignore new file mode 100644 index 0000000000..f39be478e7 --- /dev/null +++ b/plugins/CustomVariables/tests/UI/.gitignore @@ -0,0 +1,2 @@ +/processed-ui-screenshots +/screenshot-diffs \ No newline at end of file diff --git a/plugins/CustomVariables/tests/UI/CustomVariables_spec.js b/plugins/CustomVariables/tests/UI/CustomVariables_spec.js new file mode 100644 index 0000000000..a64a1cd7ce --- /dev/null +++ b/plugins/CustomVariables/tests/UI/CustomVariables_spec.js @@ -0,0 +1,31 @@ +/*! + * Piwik - free/libre analytics platform + * + * Screenshot integration tests. + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +describe("CustomVariables", function () { + this.timeout(0); + + this.fixture = "Piwik\\Plugins\\CustomVariables\\tests\\Fixtures\\VisitWithManyCustomVariables"; + + it('should show an overview of all used custom variables', function (done) { + expect.screenshot('manage').to.be.captureSelector('.pageWrap', function (page) { + page.load("?idSite=1&period=day&date=2010-01-03&module=CustomVariables&action=manage"); + }, done); + }); + + it('should be visible in the menu', function (done) { + expect.screenshot('link_in_menu').to.be.captureSelector('li:contains(Manage)', function (page) { + }, done); + }); + + it('should show custom variable creation command in dialog', function (done) { + expect.screenshot('create').to.be.captureSelector('.ui-dialog', function (page) { + page.click('.manageCustomVars .addCustomVar') + }, done); + }); +}); \ No newline at end of file diff --git a/plugins/CustomVariables/tests/UI/expected-ui-screenshots/CustomVariables_create.png b/plugins/CustomVariables/tests/UI/expected-ui-screenshots/CustomVariables_create.png new file mode 100644 index 0000000000000000000000000000000000000000..ccd46cfa9b282160d74b6e3a68f096ca63a02d21 GIT binary patch literal 19928 zcmcJ%1z45qwm&*CFfc$6kQA_x5|mC6L_k2gLlC8rZm{T5KtNLI?n##d6KN5cbVzqP z>G+Rtt-a6Q=d5+kx%d8`%d>T{WisRa-gk^&jnDUqti<`V6lYN=)OpEAVhSkKF+ccz z>@+_7{qCK_C-~0^8&OH6)9~eb`k4>>|1&QisoS7X1jNW6JXBN+ISO?ZB`J1a$uVYe z*hxzXcPP9{=4Dn;devy^Qj}_osjW@Z%S@3jv3qUWTC1kRkI%D^Ww|V6V%r4kD_MQ$ z>3w`|B&0Li)kv0PS)`~ElWCQnJeGfsqqcTt%UgJwqmI|6{nHh(C7i2(^JI*TP<+Q; zVN8cB&x`4Rw}hgveBkT*<3z6ue|)zrqjl>N5fRacYpf)`@RLWE$o$0M>zXftI6ZuY z)O*sykBKD5ML!_FdCls}Bjo2HrBALQKbQP(e!VIG%kito0}Pc74Y#K(kNn5Gj}sb} zWVbhd?KvMums`8FbXs6?{LRC_$y`dl({%58t|PA_Uqvi>)kX4zUx@u6i`<rKW1T~% z?%4P^y~{aEL1K8o@WgE<CixiW+8n3w6lxJCr?LhE<h^7%Iy-;s>grl<9MF6aE+h7g zt;BM)c+S3%L|((s&+n{%WA~nDeq|*UJ3IU7GiSaU1PkI@T3Xu9{XBX6)P?%>sg@5P zKPr#X-5RHqJTUrRT|>Kj@9I@lTwL7t?=CsRU`c7|x2dT&j~zR<sB?Jm<Kfn^Vq&6U z0x2n}`Rk(@8MpoS7H}=hy}7!Lvz>`+D;`IK&s^;7xe5vk*KobM1`U3fZ{5C~(QzjY zFK^{zAgwTsKPii-sOT}T^OQH79>X^%y>IW%INZHQPhZ{`_VFX<qcWVmIP!*bt9Nf7 z9;|pwbV|@RU;-&WeEQ`3=FPF8Qmf-P<>Kl?u1l|OPXza>p6(Xu+nNuc5u^wT3gU78 zean4ssf2IO-_P&m_Ucm}KEClDRb8~pPD4Y(EmqcImufMwXCC-(@7wG4Jh=EP!Q<lo zKuT59rtV--qxca`n)57OW=nR7r@omPb9=mSumr6e$=uvr<ejI-T;1G$&CZ@?V`CH8 zXuTWB@4zY>FJ%5$(Z)YDA>mlO>-rhzt>r*c7LBoA-n3jaHe<DT@7}%pY(7|Q)R}NH z&UIa~HC~wZ<jIparsQIHhy-0W#r8IrI<wU83hd4%l5;#e9TF1qI4ILiIz7d8LsQ12 zB`lGPRN6$p+-c*+^VZ1MT;>Cx4H|<S;RAl@U09&X<(kgXu7Jx={OQvtjCo@)tv6gN z`=tTHA^V+mL)aP#roB0S`2#<<tZ_N=Dk@$L{$vK<-_y+wmEF}SGI}k%|LbBTj}^Uw zf<l0CYgcc3YC*vzd3pKS!4fv)(=IIdSG(<vhsp_k5Fj%B87JsMI)MqStGg&1;7#jJ z-jyQr;OSGk!?j=!z3tUsM#JTteD;ezB_qz#J-Y5Jn#E#zdRK4XzWqKXM(c%#l+@Yg zmKGusl6T=On#X={g@?7@Oy??jo^`n1!sfWq#{Fw%<`gY0?KvtQ!cn)aSp5UM!FCo- zgZn`P?4O^zU!^xOia6T7i4w8$563i&=b8^BmWoS<9$?c-8Yj+C^O5Mf?_B4y7)skM zR&Sf!t0$K0E;Cfu(hBG=d|?0!9b(K6Z|?VRTLYT#8|yWPxZFr?%eZkXjX#!|)9Ie& zNM(EUY=XFdo>3?LgeePq%^HT%$KSs$h?@V7e*I~bh@&G<LSiDj<Eq}Z8#j)XZm5^# z8#L;}2JS1hN^DRwpL5w@(wZJ5W77%1E%dfbD{5((<yUQNY_OYj--;1%Qm{VqXRG!} zO1j3wcetf^g>#3~r2BMFPtT3U67xY)I7Ydl9s4^QYs(cY%@}!uqr-#K=g*4=(+IBa z%*018y38d<yqxc5TpTJRrlX^~k^hLDR$6K%R4H0Bw5Fnh-<B`7DPJb)-d9y!x0Axc z!l4GH5rzw8$<LV|ebiQ0Pj^0dtL>tgm_tj=(SfCp{DW&-Jvt=EUcETX=F8O_{vPsp zaJ;_Ps3+s28FC8OhRSSE%a6-7K8A(q!F4Zn#$~K+s=2xf6kCo4Nzgc*7%Z`D{K%yG zJ~Z?#Th0C@x4q4VWa)@J`y~wn8qPUCe}8#3HJ@m1OZ~<mYSgQ2&5|gpn;$Vz98+n5 z;(<5g9FOU`;Vwh1AflnUfa)uJ5o}e1joia6oEob+xc*K=LxY0PZvI{9O}X*SCH~R8 zU04K}ppyFVYE^|U3twN~@9pgm-Q9)SV|d@fdQZ%y#^dXi$sHYT)l5t_g&Or2T-Vpv zfB*5LXI2)o*<kVck&%(@{f&-%<E|S`1uk${p~##qu^8rHZOzrK33~MkHL>YQKz0nZ zxjdYiA@ugt#fPxR*Op2~$D2PgVV2+mNj!XrAH`|v_4Vy3X{^MOS_ohKq*|y4Y;@Te zp4US|TKgOENA+ED!ht`3DrBh_J}jnkiP1E{ydhyRsQsx1WlpuI{KLtPeN9ZS37Kz( zkMmC`0Kb0yqJx8?l)ARMN=QRPBbwXW+rKsL&vy3W#fxij-n#o8Hl}5ehm||5SPZEs zDP7~T9AOrH@IX9X$W1JQRr_6VaPTVpHk9s=sR4}?Dwh23>Av|H8O^0E+}x^;j*h3H z@Mjw2^m94?Hllk+m?{@f3NJ;^!0-Tm=mQt;4Bfj(b^|ZuS-35Ro&@y3LJy3jE8aw2 z7dF1<SG^xGx*{U4kVh~wGTLn}4Obw~>?7p1`)FFZV##v2{JMaEfY`=#+vPnmNk_+0 z<e@DQY}^)mvx&j)yuH1lZss)QV*^anH_|uVH8;3b@7kB!FWq*@5^QHNZG3}ezp5%n zpHMLeyKmeq!k+YqUnsApkJ}<_t!Co*9#hKBRD>>bxTa-E9BjW}XbD=Cj-BJz+Xf~r zgpY}2s$>VKmQ0qGmR{xNCVSBl*RcAl?n87mlS@|j64!<`I*d`ml-W8-{~q}{qmjz8 zCVNx;&8;m7L&NLsvHad!qaL(3Wn*f|bX{NL9mlWj=(spoY+m;Y@A&)p_~3Z=T}gHo zm(8l3P3;Q%Uv1o@V#>;w1q21xpjl4HdF&GFI89v^z;!G7?d<ICCS+xu>&?-AQ24y< z@#bX`lFzWlFYWBaWo3gJDl;-N0_J+mN+y5Lbvgd>B>PeA<`TnegO6Hmz1wm1?p<P} z%iZk|I4-iMR$wb6xm2Qhn4Fx96xo=VnD-G8H=X`t#Xffj!Kr?mtl5EDH63hxGBi}t zZm+6+W<aa_YIM$53qc3y_o$b@XXPs<Q=bcJZX^eljJi{nm6bVe_P@w?+p~8)!1b2e z&V{VWWC}Hh8RV)Zbsth`pEuQC9<33!7%F`|KCVy2XZw9SE&OSn*RR43p$AS*ysSEv zY4gQ*^)yGLJ@9`Fy*op^I_xm|t7>cHL9R~K%jF^7EbR)?gI!$R=+U7=&(tGyXn4&h znvfm*Peb<7u#<xtX+5aa)z!a$|6U7AAKcpd*ml0Vsr1o_c?ahHyGK!L*Exku`zD48 z?3nxb@O^xiFHif|50rdq84`S%Xz(I)BL`Y_oBjkGks?QBk!;ymK0FlE1I3v_(dl@~ zUFgK9p`FDMrrgRmNWl>j5_)NEU7+T*)6r+ds2GIKS8Iuigzi8v*3SKeO{-LIvEu!E z!mzNgt3pCFe6j70F_%ntNBaA(pdMGJF_akn-q@()U#WaMIr&Vh+Vu*+Dne1cspgM% zL7XdH&?t_fpbp5-^hL38cNhH{zURL0h;oRFE_K<m2sP)NcVX^lItmClhZ31-UndTQ zEiW>tmiBas{K@VoCi(;~1(y%A8BF&xDb-*09BknY8!pqR%xGH@G%zZrAlnBj9tJie zAsLysuE)V;Wo6}CjErA{g%5qw(r*2p?~zt^hjNLJI(LQR1i!;_eOoj)Kn0}r6Ogg$ zwS==^m~^VEt5M69bMv-*vp8p0XuOeJ=26c^pgiNFvUI8jCi8D-G>0W}l4`0G+q4~f z*^{9RfT3`0$BUZJww72<;OV}?>jBRMPPZdC)5lQIbA8s=t&z<OUBEiFGTv=d9Vxd^ zF1^3%)h-Q|bS6m>qZ}-pu<sYTpk+eq%$}@r*-H5Q83lN#ufl<Cx+C7wx^?)T{i51E z=!tMe9#~s*P;i>OV>iG=QYnraG!5)uq!kKCNT3f34<GN#H*lPZbwCX{$tL|#VH@A@ zW*dlDFauU*;@kf%i0T?_HD}en!%AwpshKz;lz19N#;R4DCZBkXmR4cni#H92kXhf) z7q2riGuNi0E$LZV+x0&IO7sZ`2y?yX3*~g}tm+bn3C$^koV>gzcAu<^F!T~jFSd({ z6wL*lf7f;hA8F0xv(mb6(+TabJ`mXKGuU2hq`f?m^##2myghb&f63D0ZolrHyvTGg z--k<=F1?B6cR2QbrE7oRHGqou65z@ZCpBk*Aca9Db5;1ceq{m<`qM-$UKg!LFJE|( z`@_zG{bbvf5o(DbDt4W~qF$ble!5ai`B!m{R4mBHUAyZqX3Nd!_OMgq{N@$$vG(j# z*k1c9M~7_AxOvYMndonwokT1eMIs_1s1dg<ZDrjc)UrU`GJv}Ku)+YwSHCj^*EThs zX>V_z?M^2~kY<O_-Z|7NtjahXtatJ8v|3tPV>2_}yf)Kg(U#R8T3vS5ryLiuOOUF? z!_Qv_7_>uRBOrxi$|$fw1&h(L!QJ5D>3inVX8sJVN^EMhv{z;`qmK!=vbwhR+S~io z!(bYu`)0^ia|%23W+*dF9IpfjE!i5)eGw2SW@2);$Z7)fNLCheiq`d&#c=u8o}SA& zIXSb~Y)V+}IzIpUiuBFw=jk(Y*e$h!8y?);+{{{~gt2^fZ~XlU0KTrx2p?TJb&;mX zv1Nc}CVU`YPj-R)J*BjmSj{P%v-lsx&dgzLTwE#WJl=2n{nG)_lp0BKMx{)DaKUH% zs;a6!c$)`w{_}XR{TlDJ3UVRTPNA)??s$)7rDuZ4>xV}?c&8|<wQg!@%hUXzWexpC zLc4&`>_E8URw?kWSzA65GO`D$U0<LPr|eTvQ~z3C4nnR<ON;a&PqY*rJY#}$Z>g0* zX<6AX*p;H8H)PCoZVCPV@c_d{r19;~H*?Kb_c`*=|CV|FUlP~<?bm72JoTSEdGf$p zWa}1-!GpQJU5XbqscVDp?W%eQKAF?y+PiK!XGtwT-#_1@qMD=i74R3k?d%VH#!(8~ zu*%k6>B+^SCzZ~)+aoS3g6C+3sJ?#v>bQjNMVgY!GZyKLwP0#~m0ZKaxZ#zz2lpu{ zw-h{vr1OUscr4Xd+)Yxwgl<w~WCK_MtQgeY-Hp#!Q_X2x!$lHJ<_BP<7OBZ2RW1xS zZs5CYE`ANTau;bu{R~2|X5|;PD(uf69v+^j#_#`>n0;k&08LQmeX;R9-GhL^IH&0= z2%*FD-oJkzxW0&%7S$nuxG?|@P}@7=1bJ*{34!tcsB&>={dD)#^71mq_RE(qw{G1+ zp^#G_$!SUoK=qkcPp{4}Ex-Lacp^+ql1cMWl?yk(+s+(qeq>)m`9z^k(*Yd{015!b zS72u{bQ`e#YX6J)Caf|m4WmhOiPDjASIV!0tx<_+E^}D(S5PqN`S>Wz2a3KzIbVyY z**^)GB$Rnj@6J{DxIp_P0G$(2Q3W8SvPf=;$F$h+`Ez~v$M3DJ?|>IL|DJsf$FI4# z<g1>Dt?fN%QFtf>bP$q~;!8+KOsq{b1~-0SkkGqBzPh`RJMlAF`jMR6DHQUqfv1KA z2nz^ME%fGcTSUWW#pY<6whk)jJ__XCC}+Y=0haLZ>r>OJai@m5h_Ixnd&UYkRX8U~ zxyrc0O^%lpe_XhjE|7$IJ+K){S%Fsf6K~lmFdyXlgZT2i{5;LoqY>^z$r$+5rH#R4 zh6OznfVI!yJskV`7W4yAfVbDSTBgW=J3<Az%Fa#%b$YhH@aDI=x?j`NDSTB?yz;Eo zyD_8Y)Tc~#ub^b(1dMSmZ+N9`e4R8uW%j3{AG2(PbjOg8k|G?q4qzR!Ns-C|Z7*Z_ zxb%vy!bUZ3GCRJJu7jGC;)A(^dIe|c1G6?Q<I7JII};`R7Z=U^8&BZl`vI}_0XQ^K z3>bijmX-}z*N-_{{o!&u<WI;P&bg`&Z5n|<X~{T+sqVuqP&>p_RKjmDF%bjnxP13T z`@Q8OfQ${muEmUv(|;`B#$jiLIAsJ%+$NQtV(RgLD?ARLUi37bf}*1M%a?h5RW2oj zqCT)~{by%^+Dwd(izz9ELHj4-<>l3H3b}4KkZK>piBN)v5517r>hJHT7ZTE0FQv%O z&!?xOyAN9q(15tBYh_=VO{!!Rv?IT7-$Xye#j(D5^QImEusFP%ZQvdCMaEsv7V^yc zIjrV>UI(@i!KO<JI6gu^*1{|@n7gd{qjZfy<At?_+#0`v0*()nk+%{O60U9h<OuS7 zGKw)7Q1Kn&d7|hcZO|K|z$`UmX=0L5YQGe<hQ@L!-)>Q;G#TiR+wh5Ul3wCXM8{sB z;<;LE)=z(yfIwVa+;bb49%tZGZLJ6bPXBljpi}wo2hRCV>+ogfSkTD|t~lPBLB0#E zO}Ijql{3>t?Y*L>t@gLALIu#_#tW4s#Ka7jh>1N3MXz1I?n}*Y-xpT06L}|otBo-* zf1o>uzdI@aw|hd^h=TAShpNfb4N<EfpYJCW6#N`#R|w>{n^%(8&@ge;2Bw7xqGpPg zP*?v%4qLTBVCu%lsNZZ=zeCn=Ns^&rl9ImqF(woFB>qY}Qn-%RRubt5*2|)&^Bvdp z^DRe(5O8sp?wwkhb#kfWT7p?Wl#T=d6zn%P%o8PoNz>EQ?FPhI&5exGV6SsjvobT2 zz(YceK`jw~^5lKf!u_}SP1s-czQp<f;9y4p6%%)ME?>;oX!OGV=8KgLpcU4!uEAPm z6$he=vZ>0f^kmZyrww`)hBR7`*M$9bqtV1%F}Z-bArl>I9xGAQswst>F*v9plG<%8 zip?DYn*d8fH$+XH(~FBpbluulii3{Zm`q>I{&RIf)gU1tWxnH7gVjjM-uOAy643x! z1uQVM-6vXA&OIrWEP-bjr3_kQqP9r0jax_M!hUMbztEhKLYr0N7NPOMW^;6LF_nsl zj`jzb9cq5z!Uc@SXt^E1nKNg29G0oho;~}yYwn4*wz*vlD=X_A@^d$Kq=%)#3`_;4 z;aI?y3;N#H=Bbn07)Z&TXFI0=7ne?0nAXY3$#H+J(Xa&;4Ft>7`92e7jiS>CciY7+ zbQYUyzVr0_qMEBi+LG?(J2*T{4Zji6$j8fj|Mb)K@{9~At`(gsXF4t}(x*?K^4QIj zz(qG5dSR+-B(pL-{k)O|mXx+F-Q0l1oJqoh$|$>Lr%(BT%oTXw<ahK?F|n~S#ir(p znwYm(`(itqPSLrT{FGSW!q2u$+d5iWS|%%hMCoL(ur$2z%|6gy;K}pCZk@2vm|hrl z-#bsqWmXG{W<ZH`He(mosR`;+&A}$6Egv<AxCq9on9BD0NnZGzH6M2%##oi?jves8 z7C3$B%hu$M;juaf8wnehW7ra|hBmnj(jHxzFg^V-JUl$LJUzV1s;Xb}^L`*%P;T+_ z@O&;WrwF7_-*St2-WK%*PHlU17*(=kkwS(r%64hsa#K^&>_`<q6&2Nw3J1%i<m4|v zc1brZK*R(|=hxJfVZkt9%FCB81C<JSJhQSA{QdhQs4YpUsRlrW5IB#T+k~%&a5nO( zVr5fzF5>fASXh9xba``S^rEh=?!?Sz)Zm_|=`IwHd#2dO*6~s9S#1iGy(!(rCYYKb zp1du!a6fUGEAZM4+@r2<f!TernQ6x?X$*FU@AmO|q1zdX+cnX~=Bd+d(V79urtTnp zb6wHY=rRqIBY-ttDQk^#&&e&T*Sj;87%cP+Dr{$wv0`*{kpw?(z6aTIcBE)2C#EWo z^e^`?S?UgbyZ<N%&h6=j8)lqV<6?^=Rg?%Bk(Vcet+kfxaX<h}swmO|WK>|SuVhmn zfONpBUH<O6bU67I87b+v(NS9H)vtAOb2mz3vDumof`Y@7Y!)ntI*bTTA3uJCN=TuS zt7E?A_>Xn}y);M$f)@BEC=>_+rz9mMXS-5^8!AtoBY(BM?Fcw>a(Y@H^mNp#3)FmL zKfXMGvw=Jfmsy`)2<!FhC!q_xw6%Sgo15FDtD~?)O-}ApRCF&aA|esgbYo*<dpB2v z13>Xu=<dZ<KM6gA(+f`m|KoAny$2Y9?o-77a1rvJ)*(3MS9iMN-(3U{&tgCy1~IeL zZh;hZw|g@VzrLMRQc+1LDkAZ|K+T~(W*R7A>Z)P1MCQ_Ai2ZHj)^;7)_@D2;y|yB1 z%+f`()Sas<oRpOG+2iOiYF)+oNa2BTfO_F_-aj_IN|(o`qg?ThUjk4Pq1{;qv(aj( z?297e;wJ}+&HX{KQG3j7J^AR_vuAps0(@_3x)0dl&dV{8iNliwq*pmOF4gR>6S%s% zKHkKuUF<J}UF-=8Cg6zU02@0=wxI8=0*PaQM*^$n(eXI2Lnv}VBU3}-M}-5t&#(tq zakvIWIl+@-?LC8_Wg{Xx=|&tl1R%);08y_6xuDML{BacMT?VkzFqU#PyYrcSH6AtW z+A1ofAoD-b(mDqMEzkt=ElKoNsntZD-Ga*FsC#E>V=dEV;)RA&?9-RZX5t<wDUra& zF)tW~OC~j%CeKjc(C`c1xzW$0GjHC$UBhZxN=_%I(3%!@W6+G~?5H(1?hA{8;mP`) z3K-b(NE@1*oYbrLA&UCT$$>XJHW4h00lWu3L?K^ER`(<sG4WgYkY8I`2mqtsAUjcn zN#qn_Dcba}n&B|rEvudm>F!oaN=X@idr|0)MdnU%4whr7Qx>EZL^^IVf5G|R9I2_R zi)*P%ZaJ_YC4y-h<b)5dxfBo)sjq+TU{DCYSw<@`dthB7DJAs{Bm;J*^+~S_o=OEf ze&Yvb<MqDZJ372GGnw`e4%khxSzZ@>eU|UWNG!`NM!0nSs`ExPb1qx*B)r^zIC~ZQ z*t>|gCg}K2(+*euq-Z8lp}X9A>g)}<xPUJYyhm^ac!LW=gy!~a7(M@iHKv{^_Y70F z#(^K^cEY%ZgB+oO0h);!cdFxCCaqg0T3h8VWy2J=xuQw^0OS`OafU(ZgUigo$%($- zoO_ThVmk24eP88QRSMm}s!p6%(vZJFsKL=!%;86enl{?4gj3n)SCV)8erLbf5bvzI zL-a3d0`IlcEq8=A*k*lF5~(|Y-;8>5sG+>U@!<ojl@K)Yi}3BckdRA=C}1<)%6>Rv z@Z<?0upC4aI@+HR=5gK5Yq-bBv>J7Ua1s2sc%7Y{JXYf;Uh!XCJ4Zlp_i!W`%MsSi z9NA`&?ki#Li~^QW|EI%t#=*hi_iX2Jxc<tm56okyc9V<q^6oI}RFb>9yO+Yc34yL* zHe9aE?iFP{-TLWmeZ3eE+(ZysPhY&qeMl9r5EDLcX&k>p%L0v!Mc=@{>R{Inc}@_K zLu!tjn%A`8&<Y34>Aq9{Lidk12SZAd^Nr_R(ROAO=kSq(1F|8;9Hi54187t5-PBS? z0on%E`0n-@1V6=Qse@J#s()Z6V|j<15VkBZm_!f^P6MC-<gFB|`ae^eZr3aY?XdP2 z$@$NkkTZX{w~{Cm%>|sU7Nn)XivrbPx*e`Z)aU_*z)bW6(Ux(kG(YeiD1Oi1*s~mA zDs9^CzZ)rRq87Dh<`iETwmILEsa9^w2sPjwP%83s_>VtvoCGl8c(^ljx#c4zr2<)E z*odY1lHB!8*Idrr2qibvAXZ6**!~hZ`K>Z@s2KE2OwwS2`hqm(_v!8nimjVBZ~8;^ z|I#)0PBxWz0h^8dxhq*?*g`6=rIp1fWB#|uUdAxZ{8TzuXNb_fdrD9XeGr5m8_P02 zF`+#5C8a%lH`)FiNSE~N?DD7S#1s@l;4^!tltVey-Ut2%6<aAww?@aTFYmtHpV!lg zcCj!2!5=@&%6bg;mmdg@O$JLnD<%ssnqD72RS%U=?CH}lX=!PM!bkgsl2?i+S;%t3 zt)4FRX%(A&Leyp8FD(%{H)H=J3&7?NC{i;(@-*G=f03pP4l@~AGP0Y1Ob~DlMVv@F zoS8^8jX&3Zd596A2!MW1pFMjC6iyP*#DT9=6M|7wIIosmehU}<Q?20H|H7Yoth!kh za{@oEKha-s3Hs@tTwJtSnYXnsADWt6))BrV%eaJaGbt%Q!twUf{vzYh`J!-)mlAdI zVRkXIX8U<MGml(!k`Pu2o3Z7oZ*FL4IG!A#!%-c_XP0q{g@v=4_4e&cfL76wsn~l6 z;!jKazFiKm|DBiDfRfksO|4r&G=dsXM*ZM0%QzWj7dq8+k9dG@%kFXL3XBV21_=OG zWomCH-kqHt{r&B=jEN#859vK-+-up?yS`sG-Cb}l=aYBUIgEc^3oV*9><cN;s?@-E zq763w!WJ4LO&U3%5y}{<M<d$;sIZiUs*BFYhzS4BpRb1YzQsRZ@UI2DcK5C#vv#@C zX}bFH27iR8)`RfJ_>NE?5Z*ZaQ^v#{+8PD(tT69Onxi&hn@s3r^o(cK4DkH686nMS z{^TOS0tjLeP3`jKG{yQrT%gCeC+Pf!Ikqxl(AuKA-lWAP`#LT^r2wmaU`R?vMh2&5 zVqs`#h_41cJ2s}relgp4eSQ5gYejiQ1p^yfM~-24gt$NHQ@FZnHSU5)&xi7a=-%wH zSia~jX>%x3+u+wBBtl6^X=aNTy}G{6F(RZ$oSM9=ImiVl^agwP^A-1!=ZgqZ32zFn z8N6$WW)37U9jt-%_6ZCWS5qSgxakSPixiE+0+!|4wQFNwM?rBw@SdF=dcMzGGCm^W zl$@Mg(~`;H5U8gKSj#Isyu66cmtla$HdKy=VM4A0IuWz5VEyeZh?po~j?yzSo`I|R zy``lN8gC9?(7@z?nlz1xkz0rSKyG(9HjYeT(Jd&t!>zd0LCTn#is}w{$I$biA`W|Z z+K2fflSVJW@uI0A)Z(6w>3Nr|^lqac@vElbcB*7+ctZZ5TayB;KJYMVp@*YjDaMwT z%(qIDc>cit1C!S}5sdob!w2AnAoDbWx0&y-qSIiD?d}gjSP&iE*ZDKK80f-*?CHK; z3J2Nd(f@(dSq@lxdW(NQ0FMuZTD%u8UNjvPZ(2PFlmP{{$fW1&-qwmYpwP9AjA^7T z5fZ)v=v6y7ND1mKxqxHd{I;3oXo5Ha^o{5M<=VrUj~d0ro<G$TexglPuid<v2pY-D zmoG(DMyfu9hkHSuLH#4`)lm#iW{yhrA8WK3C!7@d#~PXZq!Dr@S4@>{D7Rb4d-+Rr z;*B_C_D~;SVKIP(;FVqLl0<*WK1fdznmJ)QZRC=z-O4$8yu|z5l{X-j1F{B;It~a3 zs)nz27braREG*}zrlxMOu}NrXM2+{hXZuP^LE#0R#KIaa;vW`90*I;>I1pGV8At2+ zP*Hy`^j-u@bau3+X1WNB1`%KdQqs~^vp?u;mxt7mDw>;Y4vCVBZ@;46etp%IDhHg6 zCZw_d=Zb=xxwP<!6DP(1)}`g-U_g?Bj%H9WiWRa*%Re)et_hmm?(aDUm&Xvd007jP zB0~v$i%QU0Nzt`9i53Vbly>M6?}1leW>P`r9XTb3XPbYy7asOE%z|`J&R2`Fmpj=; z%eY2CQ^Q54&*d=fsqu25VYQ-Eg~yRQD7ScUwH(KNZxT{cX7a&$&i?pv9H7Suc<+FB z!2~>igZ*#T^>PEqh#=D*2W)a*R`x=<?c5va4g;KR{~6<6M=<WPmE<Qu7cMCDdDc@> zU?d}IYt+vdhK6)-OhDsX-Pm{_CiX4^*_oFh8v@&_Ib*OLS{EV~R903Jg6av5eMS&$ z(w<_O#D{?h3@Uulksuj*1Hl5CmQ~lCvi`AW>%tfn5p-`b_cPfDAVloonLl?f%5k}D zh7h;_NXRWTg?e9)i9LKc9--_08f>8HjgIiW$-0uW<2Y$gG}!=NwkDQeL}C*9Cg z^H$*X>ma0g<>s=*InOhqL?BS`qrgxasI;=85V{F%<)+Bj`0-x_Qp5>a=)y2ACME)~ zC+gv8@rKkZAII`tmJ`I0!1etDE&yIqt8zxKX>I{&ybZM3GXFdR9&o%j)$U3Rnl9<L z-&b>yeC^H+eB$NarupMI0d>W4m#O|JpcT)k53zR{`CPZ}>~1a%{&-3V;8Gj&PcuRF zFR8c7%x=R~o7EL-Y3Jb3CRBJ5i1UwgyFxf__Wrkjgy9NyUJnACL{{H@pNE3mA^>VM zDDC+F31cPz#(bMN5ljE}&6_)5e^T*UpMVGC)*SL7G#LUosM<=WjUR<C<k}jKiGb|2 z#?3<OvdG>V#Yq6}4af9lBBIyB6%Gvi{FF-r=sM)VUml!7y&^n@Nc$jT$SWzmgXc=K z@E_<nucX-yK>mq>!kgvc3Ikw$H)<#)VFkM1n^h-7Mn?L84I?HYVbB)ES^Dx91kSdW zhm8h`7y+6RQBo2>35W6?nPfgx%8u|iNDEQM3()|g1O%oJs6vI7l9JLNC=XJa99Bk< zi_&zsG1FnNHr{~vQ%Ix-ZQ4t*MJ?b+c>Vfy*c-=T&0lmWVp%?hhJ?JCpEofZDkZYA zvU=&@AYp4;)MJPclm6H|c|`PMW)2(DQBr#5s;#DW3&FU#$B!QmJYr>IBLj|cBlpyK zif29f)6LDz^|h~$U*E{+Kl&-nc12e%>R!_|i}ZWedy|JO%I(0*5%qS>PG0^4Ilq0D z880k?m_u}1N!-Tz`q<nYV_DUvxe_4!$*C#H>0h8;uh;d;%F3o?WE9NzX_i<(-N&10 zk9~0eJ{~Af;ENhgI9OS|{;GFJGI!H^2z`g`CO3CU`-&7FSbJ4kuutes`zxQA{kt#( zWgeCQv&0vB0n#?bq^Y<5PKU~r9j$b-fd&m!xr`?9ghsKMuX3i!7wGLcjSH|gAJArp z0pp0%O-p+*R@NJWHCbx;$54d-Rn>5q;(hDs>A4CK4zNo;_byn0p(HbR{MfOVn~Um7 zs;U#9!1(z3rbqDnZNYD1cV%UO7v#JaoqJ0*@(v!vl`v2y#ugU?pvd8&fEam0LDv77 zB#ByfUFZ*I^GZYirvh;i{{mGS<H28QOWh{NU!;h8jZ$z?l;WwxmM-oin}F!R!*z@c z`R4y^*7Sd~?EcAm|C^}l|Mu(dTLcZCKY#YR@Ot)j$`q9%-{yTmUD|GEqRxX3R)U61 z)!cE&dDMYPhB!~XIxgp-ouMVL_6<$jUk!t+d**E6<Uux$_|CKMgaOq2q)aMVwXl-R zDVZH>9wnGX&|Q%FaGGv@kyum@;4Sb=KV>H%t*zKq8b|b?&jtz6ur!#VBM|yrsoc1L zC}@$9<j^Kh-F@C#>oDr}B6!<pISO>oUvM<Y1)cA~!Sg0!csPdS1C9>147&twO^kw^ z3eH(Xz#d3z5c=WW-`}UW%0W+W@`#I##9?W`6Z8Wl7YRM#ik7za8YFP^Iupb(21$pa zIaMsTZk>iOju@aq{EIZq6*8w^1M3AGuMe7vTD2>$EuVI*D`J~N!?<EuxrWcGTWzMG z1KRzXunjOkOy&*5ZGsm!Tri(ggANKz^J!}&JNez`=OEMxJ@s?BVC$80_-6eDCk-$G zUje;?qhd5fMnT~R#Z4cYFJdwxd7BKuq+1OiAq)$K9z72aIk<dv5J(Hy3)_8YstyI? zk&H|O_!5K=Hvn=q0SiL9!Lg#5?0&}q0yzdkAghyenUSNe^7CtQ1qxznv???-bAbZX z*VpSIZ;IFY8U$IqKwzf`J_7UN+5!h89-)jUwQn*=1d(^#7a5McD;!~37)FDtKG@Vm z3OCdawPLd?0C}!YC{x&kV={S@*HY}4)3q&a!pGBxdpVDChi5c8*y!n9@}0hHL#|-V zlT0U%_dU2u2H=|^vc+OCKr1-22JoREc=;BrOOPvN)_FY+1xO)O2_>r%+$psRdzM#6 zBLlqli;=LxNbGQ~D-{nl>Tx6pYX42j+++hN)PZ2L(}SQ76nXXcZ!uBPH=J$9P>&uz zMsOiKZ~pT(3a!$YUrX8GLEyqbEq@4@Gv66!5?W-v^fVB*)l*O|9)TbQ<i4}q&U8YE z(=AaMB8Ldlh89%^02@+h;ELr~qBoJ47^;?M#N?3B5t5qEy7~<EThN&-IFo<%7DOP2 zOq|H$$LF56$N0iVki@JZnUB4d8VO*#R+?5;?C#sYP6-_CZ(z)&3}olEa%9>f-L{4u zU`zM_FKODW_!(JvPbXQ8!qNm&qEOXS&(J%AvvMaQN(UP&KP~MvXmMPpINWw^0aK|B zg-1pCf!lJ=_~!{E914vB31>$qIZXs|{{U|q!g6B}sw;Lp*#;i&K|sk!_1-eSKY_S( zBaN^-6~rLD3JdRo#la3IIa(+c<Q)0OkYENQ9MT+Lb&qy?`5FNgO?*_<xeq>PlfC9Z zU5rky1T54!{Npt4+fM^1x!X(SWJZlRoz|ai@9utUYden!G!RrxW~{=xBT;}KfNISK ziq3fKwCExk(jth&g54P*V-UP%nXa9jmfj2J0{jOArBUiuKwbj$=#N#R^V8E_GjT2# zzzK((AuQ(FkWI(ewzll{HEU%3!s#P`@sa>o$FRFVe75N~EURgS#y^%1jY&+-5fj5T zbYjm94G%+R6-i3E)EmeHbAx=$<6>SOp6@g(;Q6kpB=Ul6yT3VT36?KnO@lX(&Bw*Y zb`ePh^uk}j>=dcJ%PK1cAb*YRcmF&3XeOjFST}?ujlly4p@jxA;t1)4#Lh_(mr)}i zAD$3wlrb*atb>R?$Xe%_)eBBQK!*oT0sxmau&xo|HvI9QYh#`r5gHoWM5Y9E=ZUiN z_2@0o)`+fL@r6=|DzzDO+Fb0%9B4Gg@Mg~q4-Gxr(>883Ht!v1ZHyMgl(4LIZ|#VS zU2B~7)CchTa=iWw<mol42_+<u77cz-O2NN%Xq99KU}tuAoD`fPHSY&9RoMVQrA5_F z1>yd%e9izahtM6D`I6^5>?V?Z2iqucrw7SafB`|utcHU1EiEr^b{CR5pIi!n7vAcb zDxF}!hFMx=mw^AB{9I*ORQwef=t6f5S9-Pb{3#pZgWtrcF(hRPHM+CR=0!aQgDo3Z zhL2E_Y>$?xDso(Jx+$-$><KZ#({!*7o;TxNf0mA7*;6^))YY#*nY>XZXWXi8qI!LL zq77RnAuXWbW)ZyZ>y!0#BYVb|_@+L9!@d$rTCm-o=;#D_94zRnmA?G47Wr4xMOpoU z*SY%;2L`MJ!x@NA4i`zxZud{iM|+*<DkoGUZzyTMS4MT&h06>8*CC7+!g65CFtD(+ zO&&kc7&NGTh369-><!WaY&exHH9Qnx!gn<_!UILd$E$QKHyG5z#-$`B5k7?^h!z%1 zt)pd3N7Ibof=KikGW#HcAt4n$hh^sIc%{+XxVL4gan5H^FUM-};H4(wkM?h(K7&YG zV7$nF$b!xkoKNnNW~+J!^?dC62L?N#c;kgg#lN+Lpw@KfC@=?dYtGQHtUbb&MXm3s zQPXE!<kFQ#(vUDA@eZyNXkFBx{fU4y6R3L*1sUO&5GJGm?b)a+<-Cp?PI+;(M%P9i zUJ<wzKB67R#8CZX5Jf509d;<-1rGO858!}yL2GMk_aV#6JYuiHXAeUkedTscH)Ntt z{1IDuTzxqkEqLQ`<SS_F2F+oNFJb1yozmg!o0E{<tA`ZgF(8XF=5*qWIS~B@kN8Vz zDWYJ*7QD0EHNb5$fFx%C>%NVMAOjaghE#VtX;&qkwzUmLG~hiW(=Wgd{DGSpOn(0W zDg2NBC__u~Y}pW&2-q<nF7J63pKTz^==S%t^HaoMmQJwwCVhd|+dNyRB?m}uoB_uY z14*eRXJ%t!5|a8;oL$;=YY)Y)Ejb(!yH8($xFZN}0|yWrr%%{B|4(N_NB(~tLi*p3 z-Tx&p{I_2pz7BZ9o?k^;XY*xA%U)Hv=924F^JO5SR~~p@P_}bjDxGI~7?i&&AHQU> zAkZLm#AZ4;ZV?k5RD7+Nq#N`#v!?R<Cr+Lmj<6CoqUm;bBwV;Qb$`BQH%t0KvEs95 z*N}kE%F5`~DQTxCnAR1^C85IS0!MMXmCvgt$HrbkhfmP0ao>(V+M$I8bUd$`W%(iH zK+%&TyZ3}dox_0b&@Lt)9{qNCx!A|9q^yi&1;9-C2D#&aosAi8TQ$G=C2S$2RN<-a zJZ~jO=qwP4H(&MgZpTB?2SG&0hzvwYfTTyp2{>H>L<cg~9hAslabT>ZJ7~S+e73i| zE>Qca7e4<5N-1XF<WP4ben6lngh?|yimxM*{Wxq<juFR+^N=C#FV$tlB9Sj(8mL!L z_F(|#$M!DlJS3Mp&8I$3o4#%O3<6!tLuH7hfe0x8T|y07_wE}DKz^1E_A-JR;UHVV z#{{m~>9`M`d19Fk_$M6wT&7s&P!1McYWMa%OXB3URS-z^LH<An!U_yqo@i*?zLHsm zNz;mlqfTahkm{A}40(>rKz{Fr8{8qk13ox1y`oI1c2{=6MmDcowm4?Oqy;-?8`aLn zD>YZt$~#^1BW&O)z$XOLLem7j;Wgw|j7_|wwv#cQf-{uaHla~Y;>NBBasXpdg+(-L z?yhNLVYrYg6EpKUK*)G6XBbF97~@`6?8==^($5miHO2jSaPezn<0*!R0kr_H8P$W( zGl6B$FMq+nnM#APXrH8>-sh$T$e(?9|Nbi22q0=AsVA6`QM9QB&P{*&wiIZgK2UAI z>$zm$q*-i+<i{`u&@z!M6m)V#qPAPWB7Y>OGkX^rV6Lhjw!*W8&zy4Tq-GU{J9nNS zZpbr3Ltjur5xJDzX8LhYzQtg%43&W66R=Sr;RKh5w8CM96p~0Vd`3h~on6KnzAJJ2 zkOH;^GHHRhI}jv8Vq;EP=abh+!20>0O^q(C62PIpkST)kj8fN~0$?0vlUCLSO|Gs| zJuM2mATj$u7F-#5YTzZ{XkY&n0atTCNWO~<`y`|BUq;6E@E=A7HmGYihIq2Mc#5i| z*o?(3!;snNlTB+&UiSr<a7cY`Q3W#=j#$aG^etZs6%F7l45@pCt|5rhv+0n<W) zNJxeW;DJxP$Dz7S1th7b!^V4l&X_dR*ZaWx00#p?49MgU#tqx5J<T4~v0(CPCN@5v z4L17CvQZkh_fb)|VWCraWf^hBPtKh`e;Kl0m|mds^k7ifR3o+tyhy$P%%%JnTjgV0 z1=vu?Ny%}_Fw`lgm|lZeg>Qt8bJMm4BNhNaK7@ndJ@}Kckpe~|wyfSs0s9F!ryu;2 zNsf2;VS1H0pnG~wPG#60X;PW@;!IK*|4npBO5jR?q$C}ZOM6EM5ljsTxU|q@K4(^s z%KP|p!IqC5=xfu#CPkvjo|v?*(HEs)kb3g<8_t3hTMuXhrb9l?7yY^1-2p_|Go@%l z(>X;JgZnKp2I<3XgHJ(Ku*0NtPRLql_1RSC8(JttktGcz+Yc!ihxKK4bk}Dlcl4CQ zRgV<*sD}3sTBjdSZ;CDTyAF&!^4U>EFv>Vo>7=*_lQ<A-mFBS2+#7?U0~17=)S0}| zLWxF_Iyy9fYXftKhlf8zM7&TIf*GNVptiO)@kft*nz&A#IyF%PlRKX8-kpfycenr* z1&#y=(Z!5%=qyG}Uw?o9CPSNKHDrDcgcwkskts~rk>Uypm)18n;7PrqplaEi)7VWd z{#$>hMW5HC5zZU&JHi{enHd@P8v6h@0)V53qn|1p`wcN&_so{${=lb@dc9iKp<|$A z9^bbx#FeUa5#D0}1?O2f&g4R_JTMlJ#Fvep=#Ju9l3d`mU@_fOVvMbtrrNMa!Y2@F zOSqk_u&*$YP(4kVY=CYjP*@s=877xX3f!6y9a(NwP<Gp2GFB7SyHOS0kU--o!wFan z@ia}C&Ao*+IY)k{cKiAjm$VYkgpv|&NCJ;dO`Sx+8m(?_Vq@fBq!r>EX044OV1eqx zv;;t2&&fj{pVOe}>j5T#hk0dYW;V^7gG?2YZCl4r3QN_HG8}vx1zdK?4|pwN=R+87 zcDRE3=g*%AE6Z#STc8Ce`A-Ng$q@^H5K0IHIKhVqf{m;X)fSbs_f=;?lHfmCFKpnT z1^l^~EzQk8V7{!$4K```ZW32=_4|2Y&hG9B&~4yM-3F}c4SR}$Oj61?n>rQImb+v( zZx6<xXCk6(H{)zjpP`EZuFKnLdt#w=uio`|pHME0N)E9u>C42cyNvXD|LGWgX{Rlh zI>@+3+b7jR=AJER2}50eaO&_u(iH`yWq$sOh@ktY>v!%DLKq40R$zb#K5CXTrsKcr ze4?9ubPv3)f{Oq$A`+Lfox2pytgb(#3*5}Z!vhR^eCMj_c5eYtEdzlygw||_tt&~V zo4Gt8HXW^YLzprIl29Tr9QQsf>>bRfsVS#u9U;C3w14RCwV>ESq6t6L7F-*!m|rI* zGQiA$%;DMa`BN@|H?v{nnUI=VJJk&~CFfknUyK{4e$xPr`Otx|UD1rAZYZ;d2Ya0$ zQv<I7*CbBF%q;7lM?cH>rprh3_JIv)89tW|UKA3mbH(+jre$T-BX0u)hs^a4lw{{Q zNBj74|7rv&Q(=F9LeIFl&GzQf!mRF(8V`@qr9T#XNCq3njYQ=BEuCfWn><452NDVr zS_91d4y+Kc<-bp2V>Q6Wcm*FGv`QE=w6Nk71cegfcjv&Z`RYT&kOz~I1`Nk*-<%{M z1ojB>e&xaDAY!OK{t2+05*aCi(EJ^kAXIkBNLDHqO!GzmTOtaDOlKfe5z4v-vfvQp zn1G{=9NNRplA142G;Yil6coU#2Z8AJbydU}ZYrRU+!p|e?t=`9aZ@<Z%Uw(AvFQ*z z1yUJs{b;iiwD8BD+%Ok}6adhtKqZGfLm)C~%)#aoC@<}%5Dj^BTs%eiJPfpZf@DDt z8?83>Br<Na3aLG505AN1fR~imMde~%(+)PyxkbSlltcC9T~I?NU`kvZvQ}OfX@dZI znYK&7Ztr$ASg7Ox%Lkk`lHAJmvoNK^=0Yaw%jx!f$w`+Ma%4YXbR~4K{grji?Y2`6 zq1iKSkh!t~+66JTJ}UpWrDWkpp!ll5hHr!v`5H`yHXT|$s9}TVSn9UN1v#XlA72Cr z=a=pxQztmX|CDrE5ZDTHuR(YKXq_cr>Kye}{r<c$fys96O++>B6#OULf3_jIW+A{K zBGX@t>3okvZbMK`2J(FOI!aP{d0JE^gW09$Eij<j`(OW@P`TDL-8cd0`${ebL6IQT z19o``R0<L|-cB3Spgdkcy@FnfxEC;Dj<^>viwruV*2LxN0o7fTb!gh0hnOXUU_mda z6JNlF^|NY94rR);7X;-8L^dlB6Hv7TY?ZITsE29%jEq#L3IK;h!@-M(R1N>IQIJF( zyc(kVfH;STf<o#ge6-Vn$ok+$RBw+HpzO#@&^`N)RiSKzgoYw29f(De>=(*x!<#em zVZQF3`9OChf_C1&fBy=&d`1ScLY;4GmrLSC0c#hT_Fe$-(-8(ptsrJGAq0v8M4lmY zAOQ13<lGi9^RBV6v1`ptxmO{GqbPt);s>7#G~aVzas$1f^kB{6lE$6b{v?4c?orPI zTOnv?wJ<fI%l5Zv<AS-r>#Hivy#uzK5NsG*Ubb*uf?PDHMg0?P3y5v?`)X;X@UOoQ z)z*IfiU*+zqwd)nGG2zi^VanNjVCo{wEbzrK=k1l3Jh+@Tn{SP{XrtzwGXg1Fp6(& zZ9N7zGk_#6NQC5DXp3PA7)MJx@PG3cH${2sR&wa=%wkC6BVk}j?}0w`NLspUf15@q z0vV%Pc5uM?>Hjs^*ajs7G6E2NN2Y@FUUbkftL32}c(4s}<JiQ+TX2RmZc8x6DygGE zZoUB39FeX;Ji=~(T5g^th+M#fhWp>ORp8^&Cya6my^Mwz{C|8yj(;AG|Bv_c_^-ci zUBvko#$b@!3GmoVpM#O@MIvG%!7-5Cen1i%v2Y>!YdrfBZYkmgw;fT7-UbN>8B~0t zqVl{W(r4BIQ9hYeb0+ma_{`E6c4g0ic4G74k(f#aR0I3PzD~re{csKfhA-M<@>QwC ze)Ho%>Ep6J4Ywz$OYx)^4t*q6e4CBUa+VNY<zbb_f)l)?5kN9GG6p6gp~IXAUc=_F z3Y`>^<norKBf*kS*~>l7_qx?!J0Kxw<mhB+pw9x+@&;%p<8%p_vSKa)a+i$<r(c85 zxXU~pcNerHuM2pnJAdRb@1tFk+sy28v58+W-%N9>yb%8f+5!eL#2;WXT0Ze1=Obn@ zv833x;KuwUxRA*DfDm}c0CP@Y{W}8?iUz2wR!ak%r4<zhfP0ZyL+}_8-3+;(0d#uM zd=RaDqeD2@V}F7cz86JqeK4Py`wbbu%>&W}|9q4ec@YK2P7j6&9T)Q(k<0^hQ2@Nr z^|#3wUe07RZ?8?r9I}wLfb8`GRqL`+<qZ$e$kK%y3Lv9UU`10Pw*si6J$wZfiw-7z zK}V}c$}@~z)xjZyfa%u^<;>O9x{C(gY4XU>HfTJ^4MmV4X!1cYRXU*wBe_Tb#kEi` z4TDeVWl4i}FSIjB4CxRxv%6)^$7=y!v4afXZ!o!@HT)d9U-sRguz?ID`C$iom@sIc zYY<3C1obRZz=;Du&KnpEcPU?K8xA)3@(^$nGW2qq?&`Z*<n6&YGt8;x$O`)U%#JAL zs*)USHwurZ#=DCe8Qnr|R{|Z80MR#~=i;GYl2Fvxm=TuU+hN4%6o`bNWF)X3Afpqm zJJ!fOGf>F&*@xS#fHZ8A2h0U<sJ5~Y!nOfnB3*i==7<K8DmlcNS^?IR`u(L=3@AOw zPxx6u=-~pGHxe&j-Z_MM(~I!w8X(J!LIE4)gmuP4A?a0cgpgJZ)qNbM#_Pbl17`M< z&kpW%Pz&02VD87D-Z@*0eY#tZWKP@U{CO0ddD7qyErs^cP5Ip_)^_`Fe-LDT0d7B{ zKi{3+2hMS<IQ`2NTvgeg6>~RmVvdIa<ahvqL2=iI%LVR!dc)>*`UDq=Di#uIYU)mi zO#_S`gKfnCqhV)I$h<kkg-|HSAm4*%1;X19-|6V^09p?BwAJCh6I?`c;R(3Mj4<-5 zpq0D^`U0bGnYZKNolvxZKhv?+D14YNTWQVS{J}q&E4dW869q7&i5k;h9279e`SjFP z5HJv*f>S45z2MoI9JtQ}nT{hKY^RKkoepHs78zTpR^bz3V5sY3^?+STGT5q6Wjasq z5D?`KX#-Bk_AF?r7b0sxBB}>LBnY_T!@XzVI$Asmx5~v;Ik|34sHGwIwLs1q=%~9M zOT%)vvUI5$*MhGYQt-1=`d3_Qf_wp`;nSOx1bz>nHh+7ra><{uSzqn_qvjgM>x{|W zi+#65_5BpMqLSY2v&@zJXtfO3Xx(<mwOZLj-))bXacOrVjc;#_k#Mikg&CXtSa+1j z?w&cVASCxpJv?+no)z|!c;q-(SmZ#g;F_fGjN72u(Tm>b=xDMdN*bE*mMH~DD9kS` z;8s^Zi(GwQ5D%hEU~q8bq3nJiuX3QgZ0d##x?WmEb$?l9T(%d7Lk9&1D?fPx8aKzz zfxD!FgoO7sV{>zv!otFgv@}OtwPX4~WA7E+w>>dchC?dmBLx@W&QEH(1!YoP4^z9+ z;eI$%)6*I{48vHV{OWjDgc=#a%{s8U_wT=^|KPJ$j(YWbV~XF8H9|UM(!K&+SjZrG z*1IkvD=X}GC4VOtdqZ-dzhB<mJez}q13sUUre-Fj=~}Ay_V$38BtN;81nqwi_o%01 zZZ3V_y@rB<Vsc}L<Q%>(&RjY1nxK#n)M_~pHW*EP3;NAgXmk^BI6LU#jF)_8=jWw< zZfpt7Oive~(aGPwed|MKC7I~z=&(vc8Sp#l(&XG863Ab^sba2>{h+|=ngQp-is2kA zRt2}U1&v6T4a=s(m*bWYZ_g&?BtXN-#no(4((>yiuy<J|CMMdrQ>fZ_9DF`EH@9`? zs)E6#{Ef~VH*ZeioRzh;v%z2u3<{D8Nl8uZ>F!Pvx%wFranv+4CeNQ^3RW5##CKeU zV3c(J@KC6@<wHh%em*-VH#a>0?D)7S0RchoZgGZuNO(j<PghqWe5Nq;qn{%qan3F- zJ%fXLIcwJkhK7`+rTx7i&z%d5JF}uf6R_04=%^|Wm5Q5N75jd5vYWkqG5)DjcJA&u z01d)y!p(-@-I^F1=bMF^Q7717`}=pMcO*G6gM*rohn$_AeMC%5Y+`8%^Vz+b8^T>y zOT-67E_Aoa&owXLOpJ^kMMOlL^%NcG>)T!xK%ow^<OCPWQc|XwOz~EOH8eDKmoK4E z_%#Q$=5V93{m1cV{W>?gP-BUX3IwR6T)C4C5U9${I9@B<ykzg;a0c#R1`nYLo@vOZ zL#@(4^wvB+_&jQRGFUxnCN=f3jEu2^L$4z%4eFXT50!Pr@VcWwb4SO~vNZ}tDnw0! zheEA7jH`CQi`}8Wbqs~7_4y2AJ}8Da^ze7UY2;pN|3ClW@c0;a^xzB^(Fb@fl%%+< KSdOUPoBsnzzn3=v literal 0 HcmV?d00001 diff --git a/plugins/CustomVariables/tests/UI/expected-ui-screenshots/CustomVariables_link_in_menu.png b/plugins/CustomVariables/tests/UI/expected-ui-screenshots/CustomVariables_link_in_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..95e1c7783d2a13920a16d9493042245cfd09b2c1 GIT binary patch literal 5143 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 literal 0 HcmV?d00001 diff --git a/plugins/CustomVariables/tests/UI/expected-ui-screenshots/CustomVariables_manage.png b/plugins/CustomVariables/tests/UI/expected-ui-screenshots/CustomVariables_manage.png new file mode 100644 index 0000000000000000000000000000000000000000..c520cde1bf581d24ea6dd7993c69e6ba9dfe6a20 GIT binary patch literal 44125 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 DXR-e_ literal 0 HcmV?d00001 diff --git a/tests/PHPUnit/System/expected/test_FlattenReports__CustomVariables.getCustomVariables_day.xml b/tests/PHPUnit/System/expected/test_FlattenReports__CustomVariables.getCustomVariables_day.xml index c8cd332705..cb25516ca4 100644 --- a/tests/PHPUnit/System/expected/test_FlattenReports__CustomVariables.getCustomVariables_day.xml +++ b/tests/PHPUnit/System/expected/test_FlattenReports__CustomVariables.getCustomVariables_day.xml @@ -4,6 +4,12 @@ <row> <label>CustomVarPage</label> <nb_actions>18</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <is_aggregate>1</is_aggregate> </row> <row> @@ -15,6 +21,12 @@ <sum_visit_length>6</sum_visit_length> <bounce_count>0</bounce_count> <nb_visits_converted>0</nb_visits_converted> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <is_aggregate>1</is_aggregate> </row> <row> @@ -68,6 +80,12 @@ <sum_visit_length>1</sum_visit_length> <bounce_count>0</bounce_count> <nb_visits_converted>0</nb_visits_converted> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <is_aggregate>1</is_aggregate> </row> <row> @@ -84,6 +102,12 @@ <row> <label>CustomVarPage</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <is_aggregate>1</is_aggregate> </row> <row> diff --git a/tests/PHPUnit/System/expected/test_ImportLogs__CustomVariables.getCustomVariables_month.xml b/tests/PHPUnit/System/expected/test_ImportLogs__CustomVariables.getCustomVariables_month.xml index dc1a11ab2b..a1fea85a41 100644 --- a/tests/PHPUnit/System/expected/test_ImportLogs__CustomVariables.getCustomVariables_month.xml +++ b/tests/PHPUnit/System/expected/test_ImportLogs__CustomVariables.getCustomVariables_month.xml @@ -3,6 +3,12 @@ <row> <label>HTTP-code</label> <nb_actions>43</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==HTTP-code</segment> <subtable> <row> @@ -61,6 +67,12 @@ <revenue>25</revenue> <sum_daily_nb_uniq_visitors>7</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Not-Bot</segment> <subtable> <row> @@ -151,6 +163,12 @@ <revenue>10</revenue> <sum_daily_nb_uniq_visitors>3</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>1</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==User+Name</segment> <subtable> <row> @@ -196,6 +214,12 @@ <row> <label>Generation Time</label> <nb_actions>4</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Generation+Time</segment> <subtable> <row> @@ -221,6 +245,12 @@ <row> <label>Windows Status Code</label> <nb_actions>4</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==Windows+Status+Code</segment> <subtable> <row> @@ -267,6 +297,12 @@ <revenue>5</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Bot</segment> <subtable> <row> @@ -308,6 +344,12 @@ <revenue>5</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Forum+status</segment> <subtable> <row> @@ -349,6 +391,12 @@ <revenue>5</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_ImportLogs__CustomVariables.getUsagesOfSlots.xml b/tests/PHPUnit/System/expected/test_ImportLogs__CustomVariables.getUsagesOfSlots.xml new file mode 100644 index 0000000000..002b96ca46 --- /dev/null +++ b/tests/PHPUnit/System/expected/test_ImportLogs__CustomVariables.getUsagesOfSlots.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="utf-8" ?> +<result> + <row> + <scope>visit</scope> + <index>1</index> + <usages> + <row> + <name>Domain landed</name> + <nb_visits>12</nb_visits> + <nb_actions>16</nb_actions> + </row> + <row> + <name>Not-Bot</name> + <nb_visits>7</nb_visits> + <nb_actions>10</nb_actions> + </row> + <row> + <name>User Name</name> + <nb_visits>3</nb_visits> + <nb_actions>5</nb_actions> + </row> + <row> + <name>Bot</name> + <nb_visits>1</nb_visits> + <nb_actions>1</nb_actions> + </row> + </usages> + </row> + <row> + <scope>visit</scope> + <index>2</index> + <usages> + <row> + <name>Demo language</name> + <nb_visits>1</nb_visits> + <nb_actions>1</nb_actions> + </row> + </usages> + </row> + <row> + <scope>visit</scope> + <index>3</index> + <usages> + <row> + <name>Forum status</name> + <nb_visits>1</nb_visits> + <nb_actions>1</nb_actions> + </row> + </usages> + </row> + <row> + <scope>visit</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>5</index> + <usages> + <row> + <name>VisitorType</name> + <nb_visits>1</nb_visits> + <nb_actions>1</nb_actions> + </row> + </usages> + </row> + <row> + <scope>page</scope> + <index>1</index> + <usages> + <row> + <name>HTTP-code</name> + <nb_visits>0</nb_visits> + <nb_actions>69</nb_actions> + </row> + <row> + <name>Generation Time</name> + <nb_visits>0</nb_visits> + <nb_actions>4</nb_actions> + </row> + </usages> + </row> + <row> + <scope>page</scope> + <index>2</index> + <usages> + <row> + <name>Windows Status Code</name> + <nb_visits>0</nb_visits> + <nb_actions>4</nb_actions> + </row> + </usages> + </row> + <row> + <scope>page</scope> + <index>3</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>5</index> + <usages> + </usages> + </row> +</result> \ No newline at end of file diff --git a/tests/PHPUnit/System/expected/test_OneVisitorTwoVisits__CustomVariables.getUsagesOfSlots.xml b/tests/PHPUnit/System/expected/test_OneVisitorTwoVisits__CustomVariables.getUsagesOfSlots.xml new file mode 100644 index 0000000000..81163427e5 --- /dev/null +++ b/tests/PHPUnit/System/expected/test_OneVisitorTwoVisits__CustomVariables.getUsagesOfSlots.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8" ?> +<result> + <row> + <scope>visit</scope> + <index>1</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>2</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>3</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>5</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>1</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>2</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>3</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>5</index> + <usages> + </usages> + </row> +</result> \ No newline at end of file diff --git a/tests/PHPUnit/System/expected/test_OneVisitorTwoVisits_withCookieSupport__CustomVariables.getUsagesOfSlots.xml b/tests/PHPUnit/System/expected/test_OneVisitorTwoVisits_withCookieSupport__CustomVariables.getUsagesOfSlots.xml new file mode 100644 index 0000000000..81163427e5 --- /dev/null +++ b/tests/PHPUnit/System/expected/test_OneVisitorTwoVisits_withCookieSupport__CustomVariables.getUsagesOfSlots.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8" ?> +<result> + <row> + <scope>visit</scope> + <index>1</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>2</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>3</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>5</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>1</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>2</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>3</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>5</index> + <usages> + </usages> + </row> +</result> \ No newline at end of file diff --git a/tests/PHPUnit/System/expected/test_SiteSearch_AllSites__CustomVariables.getCustomVariables_day.xml b/tests/PHPUnit/System/expected/test_SiteSearch_AllSites__CustomVariables.getCustomVariables_day.xml index 9a056e8786..5b6b0bc255 100644 --- a/tests/PHPUnit/System/expected/test_SiteSearch_AllSites__CustomVariables.getCustomVariables_day.xml +++ b/tests/PHPUnit/System/expected/test_SiteSearch_AllSites__CustomVariables.getCustomVariables_day.xml @@ -6,6 +6,12 @@ <label>_pk_scount</label> <nb_visits>4</nb_visits> <nb_actions>6</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==_pk_scount</segment> <subtable> <row> @@ -24,6 +30,12 @@ <label>_pk_scat</label> <nb_visits>2</nb_visits> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==_pk_scat</segment> <subtable> <row> @@ -39,6 +51,12 @@ <label>_pk_scount</label> <nb_visits>3</nb_visits> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==_pk_scount</segment> <subtable> <row> @@ -62,6 +80,12 @@ <label>_pk_scat</label> <nb_visits>2</nb_visits> <nb_actions>2</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==_pk_scat</segment> <subtable> <row> @@ -89,6 +113,12 @@ <label>_pk_scount</label> <nb_visits>1</nb_visits> <nb_actions>2</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==_pk_scount</segment> <subtable> <row> @@ -102,6 +132,12 @@ <label>_pk_scat</label> <nb_visits>1</nb_visits> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==_pk_scat</segment> <subtable> <row> @@ -130,6 +166,12 @@ <sum_visit_length>541</sum_visit_length> <bounce_count>0</bounce_count> <nb_visits_converted>0</nb_visits_converted> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==test+cvar+name</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_SiteSearch_AllSites__CustomVariables.getCustomVariables_month.xml b/tests/PHPUnit/System/expected/test_SiteSearch_AllSites__CustomVariables.getCustomVariables_month.xml index 50b6b4821e..76eae7c657 100644 --- a/tests/PHPUnit/System/expected/test_SiteSearch_AllSites__CustomVariables.getCustomVariables_month.xml +++ b/tests/PHPUnit/System/expected/test_SiteSearch_AllSites__CustomVariables.getCustomVariables_month.xml @@ -7,6 +7,12 @@ <nb_visits>7</nb_visits> <nb_actions>9</nb_actions> <sum_daily_nb_uniq_visitors>7</sum_daily_nb_uniq_visitors> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==_pk_scount</segment> <subtable> <row> @@ -34,6 +40,12 @@ <nb_visits>4</nb_visits> <nb_actions>5</nb_actions> <sum_daily_nb_uniq_visitors>4</sum_daily_nb_uniq_visitors> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==_pk_scat</segment> <subtable> <row> @@ -71,6 +83,12 @@ <nb_visits>1</nb_visits> <nb_actions>2</nb_actions> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==_pk_scount</segment> <subtable> <row> @@ -86,6 +104,12 @@ <nb_visits>1</nb_visits> <nb_actions>1</nb_actions> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==_pk_scat</segment> <subtable> <row> @@ -116,6 +140,12 @@ <nb_visits_converted>0</nb_visits_converted> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==test+cvar+name</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_SiteSearch_CustomVariables.getCustomVariables_firstSite_lastN__API.getProcessedReport_day.xml b/tests/PHPUnit/System/expected/test_SiteSearch_CustomVariables.getCustomVariables_firstSite_lastN__API.getProcessedReport_day.xml index 96a5e2ca93..04b14932b5 100644 --- a/tests/PHPUnit/System/expected/test_SiteSearch_CustomVariables.getCustomVariables_firstSite_lastN__API.getProcessedReport_day.xml +++ b/tests/PHPUnit/System/expected/test_SiteSearch_CustomVariables.getCustomVariables_firstSite_lastN__API.getProcessedReport_day.xml @@ -111,11 +111,23 @@ <reportMetadata> <result prettyDate="Sunday, January 3, 2010"> <row> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==_pk_scount</segment> <idsubdatatable>3173</idsubdatatable> </row> <row> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==_pk_scat</segment> <idsubdatatable>3172</idsubdatatable> @@ -123,11 +135,23 @@ </result> <result prettyDate="Monday, January 4, 2010"> <row> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==_pk_scount</segment> <idsubdatatable>3176</idsubdatatable> </row> <row> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==_pk_scat</segment> <idsubdatatable>3175</idsubdatatable> diff --git a/tests/PHPUnit/System/expected/test_SiteSearch_CustomVariables.getCustomVariables_firstSite_lastN__API.getProcessedReport_month.xml b/tests/PHPUnit/System/expected/test_SiteSearch_CustomVariables.getCustomVariables_firstSite_lastN__API.getProcessedReport_month.xml index 84acfed862..0d9935f4ed 100644 --- a/tests/PHPUnit/System/expected/test_SiteSearch_CustomVariables.getCustomVariables_firstSite_lastN__API.getProcessedReport_month.xml +++ b/tests/PHPUnit/System/expected/test_SiteSearch_CustomVariables.getCustomVariables_firstSite_lastN__API.getProcessedReport_month.xml @@ -80,11 +80,23 @@ <reportMetadata> <result prettyDate="January 2010"> <row> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==_pk_scount</segment> <idsubdatatable>3198</idsubdatatable> </row> <row> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==_pk_scat</segment> <idsubdatatable>3197</idsubdatatable> diff --git a/tests/PHPUnit/System/expected/test_ecommerceOrderWithItems__CustomVariables.getCustomVariables_day.xml b/tests/PHPUnit/System/expected/test_ecommerceOrderWithItems__CustomVariables.getCustomVariables_day.xml index 1d0ee64c8d..caf12153e5 100755 --- a/tests/PHPUnit/System/expected/test_ecommerceOrderWithItems__CustomVariables.getCustomVariables_day.xml +++ b/tests/PHPUnit/System/expected/test_ecommerceOrderWithItems__CustomVariables.getCustomVariables_day.xml @@ -33,6 +33,12 @@ </goals> <nb_conversions>3</nb_conversions> <revenue>3121.11</revenue> + <slots> + <row> + <scope>visit</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==ValueIsZero</segment> <subtable> <row> @@ -104,6 +110,12 @@ </goals> <nb_conversions>3</nb_conversions> <revenue>3121.11</revenue> + <slots> + <row> + <scope>visit</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> @@ -146,6 +158,12 @@ <label>_pkc</label> <nb_visits>7</nb_visits> <nb_actions>12</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==_pkc</segment> <subtable> <row> @@ -191,6 +209,12 @@ <label>_pkn</label> <nb_visits>6</nb_visits> <nb_actions>11</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==_pkn</segment> <subtable> <row> @@ -216,6 +240,12 @@ <label>_pks</label> <nb_visits>6</nb_visits> <nb_actions>11</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==_pks</segment> <subtable> <row> @@ -265,6 +295,12 @@ </goals> <nb_conversions>2</nb_conversions> <revenue>3111.11</revenue> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==VisitorName</segment> <subtable> <row> @@ -302,6 +338,12 @@ <label>_pkp</label> <nb_visits>8</nb_visits> <nb_actions>8</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==_pkp</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_noVisit_PeriodIsLast__CustomVariables.getUsagesOfSlots.xml b/tests/PHPUnit/System/expected/test_noVisit_PeriodIsLast__CustomVariables.getUsagesOfSlots.xml new file mode 100644 index 0000000000..81163427e5 --- /dev/null +++ b/tests/PHPUnit/System/expected/test_noVisit_PeriodIsLast__CustomVariables.getUsagesOfSlots.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8" ?> +<result> + <row> + <scope>visit</scope> + <index>1</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>2</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>3</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>5</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>1</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>2</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>3</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>5</index> + <usages> + </usages> + </row> +</result> \ No newline at end of file diff --git a/tests/PHPUnit/System/expected/test_noVisit__CustomVariables.getUsagesOfSlots.xml b/tests/PHPUnit/System/expected/test_noVisit__CustomVariables.getUsagesOfSlots.xml new file mode 100644 index 0000000000..81163427e5 --- /dev/null +++ b/tests/PHPUnit/System/expected/test_noVisit__CustomVariables.getUsagesOfSlots.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8" ?> +<result> + <row> + <scope>visit</scope> + <index>1</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>2</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>3</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>visit</scope> + <index>5</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>1</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>2</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>3</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>4</index> + <usages> + </usages> + </row> + <row> + <scope>page</scope> + <index>5</index> + <usages> + </usages> + </row> +</result> \ No newline at end of file diff --git a/tests/PHPUnit/System/expected/test_periodIsRange_dateIsLastN_MetadataAndNormalAPI__CustomVariables.getCustomVariables_range.xml b/tests/PHPUnit/System/expected/test_periodIsRange_dateIsLastN_MetadataAndNormalAPI__CustomVariables.getCustomVariables_range.xml index 00acc7d7d0..8851c23d9a 100644 --- a/tests/PHPUnit/System/expected/test_periodIsRange_dateIsLastN_MetadataAndNormalAPI__CustomVariables.getCustomVariables_range.xml +++ b/tests/PHPUnit/System/expected/test_periodIsRange_dateIsLastN_MetadataAndNormalAPI__CustomVariables.getCustomVariables_range.xml @@ -23,6 +23,12 @@ <revenue>1000</revenue> <sum_daily_nb_uniq_visitors>2</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> @@ -88,6 +94,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE</segment> <subtable> <row> @@ -114,6 +126,16 @@ <row> <label>Status user</label> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Status+user</segment> <subtable> <row> @@ -148,6 +170,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Value+will+be+VERY+long+and+truncated</segment> <subtable> <row> @@ -189,6 +217,12 @@ <revenue>1000</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==Othercustom+value+which+should+be+truncated+abcdefghijklmnopqrstuvwxyz</segment> <subtable> <row> @@ -215,6 +249,12 @@ <row> <label>Language</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Language</segment> <subtable> <row> @@ -228,6 +268,12 @@ <row> <label>SET WITH EMPTY VALUE PAGE SCOPE</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE+PAGE+SCOPE</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_periodIsRange_dateIsLastN_MetadataAndNormalAPI_pagesegment__CustomVariables.getCustomVariables_range.xml b/tests/PHPUnit/System/expected/test_periodIsRange_dateIsLastN_MetadataAndNormalAPI_pagesegment__CustomVariables.getCustomVariables_range.xml index 00acc7d7d0..8851c23d9a 100644 --- a/tests/PHPUnit/System/expected/test_periodIsRange_dateIsLastN_MetadataAndNormalAPI_pagesegment__CustomVariables.getCustomVariables_range.xml +++ b/tests/PHPUnit/System/expected/test_periodIsRange_dateIsLastN_MetadataAndNormalAPI_pagesegment__CustomVariables.getCustomVariables_range.xml @@ -23,6 +23,12 @@ <revenue>1000</revenue> <sum_daily_nb_uniq_visitors>2</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> @@ -88,6 +94,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE</segment> <subtable> <row> @@ -114,6 +126,16 @@ <row> <label>Status user</label> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Status+user</segment> <subtable> <row> @@ -148,6 +170,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Value+will+be+VERY+long+and+truncated</segment> <subtable> <row> @@ -189,6 +217,12 @@ <revenue>1000</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==Othercustom+value+which+should+be+truncated+abcdefghijklmnopqrstuvwxyz</segment> <subtable> <row> @@ -215,6 +249,12 @@ <row> <label>Language</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Language</segment> <subtable> <row> @@ -228,6 +268,12 @@ <row> <label>SET WITH EMPTY VALUE PAGE SCOPE</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE+PAGE+SCOPE</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_reportLimiting__CustomVariables.getCustomVariables_day.xml b/tests/PHPUnit/System/expected/test_reportLimiting__CustomVariables.getCustomVariables_day.xml index 6b7a4a8b1c..c1ba006247 100644 --- a/tests/PHPUnit/System/expected/test_reportLimiting__CustomVariables.getCustomVariables_day.xml +++ b/tests/PHPUnit/System/expected/test_reportLimiting__CustomVariables.getCustomVariables_day.xml @@ -3,6 +3,12 @@ <row> <label>liked</label> <nb_actions>20</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==liked</segment> <subtable> <row> @@ -20,6 +26,12 @@ <row> <label>tweeted</label> <nb_actions>20</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==tweeted</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_reportLimiting_rankingQuery__CustomVariables.getCustomVariables_day.xml b/tests/PHPUnit/System/expected/test_reportLimiting_rankingQuery__CustomVariables.getCustomVariables_day.xml index 6b7a4a8b1c..c1ba006247 100644 --- a/tests/PHPUnit/System/expected/test_reportLimiting_rankingQuery__CustomVariables.getCustomVariables_day.xml +++ b/tests/PHPUnit/System/expected/test_reportLimiting_rankingQuery__CustomVariables.getCustomVariables_day.xml @@ -3,6 +3,12 @@ <row> <label>liked</label> <nb_actions>20</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==liked</segment> <subtable> <row> @@ -20,6 +26,12 @@ <row> <label>tweeted</label> <nb_actions>20</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==tweeted</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables__CustomVariables.getCustomVariables_day.xml b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables__CustomVariables.getCustomVariables_day.xml index ebbd07023b..7ffb6725e4 100644 --- a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables__CustomVariables.getCustomVariables_day.xml +++ b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables__CustomVariables.getCustomVariables_day.xml @@ -24,6 +24,12 @@ </goals> <nb_conversions>3</nb_conversions> <revenue>1000</revenue> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> @@ -86,6 +92,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE</segment> <subtable> <row> @@ -125,6 +137,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Value+will+be+VERY+long+and+truncated</segment> <subtable> <row> @@ -150,6 +168,16 @@ <row> <label>Status user</label> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Status+user</segment> <subtable> <row> @@ -181,6 +209,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>1000</revenue> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==Othercustom+value+which+should+be+truncated+abcdefghijklmnopqrstuvwxyz</segment> <subtable> <row> @@ -206,6 +240,12 @@ <row> <label>Language</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Language</segment> <subtable> <row> @@ -218,6 +258,12 @@ <row> <label>SET WITH EMPTY VALUE PAGE SCOPE</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE+PAGE+SCOPE</segment> <subtable> <row> @@ -230,6 +276,12 @@ <row> <label>var1</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==var1</segment> <subtable> <row> @@ -242,6 +294,12 @@ <row> <label>var2</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==var2</segment> <subtable> <row> @@ -254,6 +312,12 @@ <row> <label>var3</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==var3</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables__CustomVariables.getCustomVariables_week.xml b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables__CustomVariables.getCustomVariables_week.xml index 92a4a5c7be..0514b1d5d3 100644 --- a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables__CustomVariables.getCustomVariables_week.xml +++ b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables__CustomVariables.getCustomVariables_week.xml @@ -25,6 +25,12 @@ <revenue>1000</revenue> <sum_daily_nb_uniq_visitors>2</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> @@ -90,6 +96,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE</segment> <subtable> <row> @@ -131,6 +143,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Value+will+be+VERY+long+and+truncated</segment> <subtable> <row> @@ -157,6 +175,16 @@ <row> <label>Status user</label> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Status+user</segment> <subtable> <row> @@ -191,6 +219,12 @@ <revenue>1000</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==Othercustom+value+which+should+be+truncated+abcdefghijklmnopqrstuvwxyz</segment> <subtable> <row> @@ -217,6 +251,12 @@ <row> <label>Language</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Language</segment> <subtable> <row> @@ -230,6 +270,12 @@ <row> <label>SET WITH EMPTY VALUE PAGE SCOPE</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE+PAGE+SCOPE</segment> <subtable> <row> @@ -243,6 +289,12 @@ <row> <label>var1</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==var1</segment> <subtable> <row> @@ -256,6 +308,12 @@ <row> <label>var2</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==var2</segment> <subtable> <row> @@ -269,6 +327,12 @@ <row> <label>var3</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + </slots> <segment>customVariableName==var3</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchALL_noGoalData__CustomVariables.getCustomVariables_day.xml b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchALL_noGoalData__CustomVariables.getCustomVariables_day.xml index 7e941dea10..1bfb23612e 100644 --- a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchALL_noGoalData__CustomVariables.getCustomVariables_day.xml +++ b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchALL_noGoalData__CustomVariables.getCustomVariables_day.xml @@ -24,6 +24,12 @@ </goals> <nb_conversions>3</nb_conversions> <revenue>1000</revenue> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> @@ -86,6 +92,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE</segment> <subtable> <row> @@ -111,6 +123,16 @@ <row> <label>Status user</label> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Status+user</segment> <subtable> <row> @@ -142,6 +164,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Value+will+be+VERY+long+and+truncated</segment> <subtable> <row> @@ -181,6 +209,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>1000</revenue> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==Othercustom+value+which+should+be+truncated+abcdefghijklmnopqrstuvwxyz</segment> <subtable> <row> @@ -206,6 +240,12 @@ <row> <label>Language</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Language</segment> <subtable> <row> @@ -218,6 +258,12 @@ <row> <label>SET WITH EMPTY VALUE PAGE SCOPE</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE+PAGE+SCOPE</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchALL_noGoalData__CustomVariables.getCustomVariables_week.xml b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchALL_noGoalData__CustomVariables.getCustomVariables_week.xml index 54f91c076f..4041ca8eac 100644 --- a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchALL_noGoalData__CustomVariables.getCustomVariables_week.xml +++ b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchALL_noGoalData__CustomVariables.getCustomVariables_week.xml @@ -25,6 +25,12 @@ <revenue>1000</revenue> <sum_daily_nb_uniq_visitors>2</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> @@ -90,6 +96,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE</segment> <subtable> <row> @@ -116,6 +128,16 @@ <row> <label>Status user</label> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Status+user</segment> <subtable> <row> @@ -150,6 +172,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Value+will+be+VERY+long+and+truncated</segment> <subtable> <row> @@ -191,6 +219,12 @@ <revenue>1000</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==Othercustom+value+which+should+be+truncated+abcdefghijklmnopqrstuvwxyz</segment> <subtable> <row> @@ -217,6 +251,12 @@ <row> <label>Language</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Language</segment> <subtable> <row> @@ -230,6 +270,12 @@ <row> <label>SET WITH EMPTY VALUE PAGE SCOPE</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE+PAGE+SCOPE</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchVisitorType__CustomVariables.getCustomVariables_day.xml b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchVisitorType__CustomVariables.getCustomVariables_day.xml index 304bb2fe65..428f0180ae 100644 --- a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchVisitorType__CustomVariables.getCustomVariables_day.xml +++ b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchVisitorType__CustomVariables.getCustomVariables_day.xml @@ -19,6 +19,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE</segment> <subtable> <row> @@ -44,6 +50,16 @@ <row> <label>Status user</label> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Status+user</segment> <subtable> <row> @@ -75,6 +91,12 @@ </goals> <nb_conversions>1</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Value+will+be+VERY+long+and+truncated</segment> <subtable> <row> @@ -119,6 +141,12 @@ </goals> <nb_conversions>2</nb_conversions> <revenue>0</revenue> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> @@ -157,6 +185,12 @@ <row> <label>Language</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Language</segment> <subtable> <row> @@ -169,6 +203,12 @@ <row> <label>SET WITH EMPTY VALUE PAGE SCOPE</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE+PAGE+SCOPE</segment> <subtable> <row> diff --git a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchVisitorType__CustomVariables.getCustomVariables_week.xml b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchVisitorType__CustomVariables.getCustomVariables_week.xml index c4f92b8e6b..4c0da8f95e 100644 --- a/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchVisitorType__CustomVariables.getCustomVariables_week.xml +++ b/tests/PHPUnit/System/expected/test_twoVisitsWithCustomVariables_segmentMatchVisitorType__CustomVariables.getCustomVariables_week.xml @@ -20,6 +20,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE</segment> <subtable> <row> @@ -46,6 +52,16 @@ <row> <label>Status user</label> <nb_actions>3</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>4</index> + </row> + <row> + <scope>page</scope> + <index>5</index> + </row> + </slots> <segment>customVariableName==Status+user</segment> <subtable> <row> @@ -80,6 +96,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>3</index> + </row> + </slots> <segment>customVariableName==Value+will+be+VERY+long+and+truncated</segment> <subtable> <row> @@ -126,6 +148,12 @@ <revenue>0</revenue> <sum_daily_nb_uniq_visitors>1</sum_daily_nb_uniq_visitors> <sum_daily_nb_users>0</sum_daily_nb_users> + <slots> + <row> + <scope>visit</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==VisitorType</segment> <subtable> <row> @@ -165,6 +193,12 @@ <row> <label>Language</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>1</index> + </row> + </slots> <segment>customVariableName==Language</segment> <subtable> <row> @@ -178,6 +212,12 @@ <row> <label>SET WITH EMPTY VALUE PAGE SCOPE</label> <nb_actions>1</nb_actions> + <slots> + <row> + <scope>page</scope> + <index>2</index> + </row> + </slots> <segment>customVariableName==SET+WITH+EMPTY+VALUE+PAGE+SCOPE</segment> <subtable> <row> diff --git a/tests/PHPUnit/Unit/DataTable/Renderer/CSVTest.php b/tests/PHPUnit/Unit/DataTable/Renderer/CSVTest.php index c6fd94e406..057f500d18 100644 --- a/tests/PHPUnit/Unit/DataTable/Renderer/CSVTest.php +++ b/tests/PHPUnit/Unit/DataTable/Renderer/CSVTest.php @@ -96,6 +96,22 @@ class DataTable_Renderer_CSVTest extends \PHPUnit_Framework_TestCase return $table; } + protected function _getDataTableHavingAnArrayInRowMetadata() + { + $array = array( + array(Row::COLUMNS => array('label' => 'sub1', 'count' => 1)), + array(Row::COLUMNS => array('label' => 'sub2', 'count' => 2), Row::METADATA => array('test' => 'render')), + array(Row::COLUMNS => array('label' => 'sub3', 'count' => 2), Row::METADATA => array('test' => 'renderMe', 'testArray' => 'ignore')), + array(Row::COLUMNS => array('label' => 'sub4', 'count' => 6), Row::METADATA => array('testArray' => array('do not render'))), + array(Row::COLUMNS => array('label' => 'sub5', 'count' => 2), Row::METADATA => array('testArray' => 'do ignore', 'mymeta' => 'should be rendered')), + array(Row::COLUMNS => array('label' => 'sub6', 'count' => 3), Row::METADATA => array('mymeta' => 'renderrrrrr')), + ); + + $table = new DataTable(); + $table->addRowsFromArray($array); + + return $table; + } public function testCSVTest1() { @@ -186,6 +202,25 @@ class DataTable_Renderer_CSVTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected, $actual); } + public function testCSVTest7_shouldNotRenderMetadataThatContainsAnArray() + { + $dataTable = $this->_getDataTableHavingAnArrayInRowMetadata(); + $render = new Csv(); + $render->setTable($dataTable); + $render->convertToUnicode = false; + + // the column "testArray" should be ignored and not rendered, all other columns should be assigned correctly + $expected = "label,count,metadata_test,metadata_mymeta +sub1,1,, +sub2,2,render, +sub3,2,renderMe, +sub4,6,, +sub5,2,,should be rendered +sub6,3,,renderrrrrr"; + $rendered = $render->render(); + $this->assertEquals($expected, $rendered); + } + /** * DATA OF DATATABLE_ARRAY * ------------------------- -- GitLab