Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/API/API.php22
-rw-r--r--plugins/API/ProcessedReport.php14
-rw-r--r--plugins/API/RowEvolution.php29
-rw-r--r--plugins/API/SegmentMetadata.php38
-rw-r--r--plugins/Actions/Columns/ActionType.php52
-rw-r--r--plugins/Actions/Columns/ActionUrl.php5
-rw-r--r--plugins/Actions/Columns/ClickedUrl.php26
-rw-r--r--plugins/Actions/Columns/DestinationPage.php6
-rw-r--r--plugins/Actions/Columns/DownloadUrl.php26
-rw-r--r--plugins/Actions/Columns/EntryPageTitle.php27
-rw-r--r--plugins/Actions/Columns/EntryPageUrl.php27
-rw-r--r--plugins/Actions/Columns/ExitPageTitle.php27
-rw-r--r--plugins/Actions/Columns/ExitPageUrl.php33
-rw-r--r--plugins/Actions/Columns/IdPageview.php8
-rw-r--r--plugins/Actions/Columns/InteractionPosition.php7
-rw-r--r--plugins/Actions/Columns/Keyword.php6
-rw-r--r--plugins/Actions/Columns/KeywordwithNoSearchResult.php6
-rw-r--r--plugins/Actions/Columns/Metrics/AveragePageGenerationTime.php1
-rw-r--r--plugins/Actions/Columns/PageGenerationTime.php50
-rw-r--r--plugins/Actions/Columns/PageTitle.php23
-rw-r--r--plugins/Actions/Columns/PageUrl.php24
-rw-r--r--plugins/Actions/Columns/SearchCategory.php6
-rw-r--r--plugins/Actions/Columns/SearchDestinationPage.php6
-rw-r--r--plugins/Actions/Columns/SearchKeyword.php24
-rw-r--r--plugins/Actions/Columns/SearchNoResultKeyword.php6
-rw-r--r--plugins/Actions/Columns/TimeSpentRefAction.php1
-rw-r--r--plugins/Actions/Columns/VisitTotalActions.php33
-rw-r--r--plugins/Actions/Columns/VisitTotalInteractions.php16
-rw-r--r--plugins/Actions/Columns/VisitTotalSearches.php16
-rw-r--r--plugins/Actions/lang/en.json11
-rw-r--r--plugins/Contents/Columns/ContentInteraction.php25
-rw-r--r--plugins/Contents/Columns/ContentName.php27
-rw-r--r--plugins/Contents/Columns/ContentPiece.php25
-rw-r--r--plugins/Contents/Columns/ContentTarget.php25
-rw-r--r--plugins/Contents/Contents.php4
-rw-r--r--plugins/Contents/lang/en.json3
-rw-r--r--plugins/CoreHome/Columns/IdSite.php9
-rw-r--r--plugins/CoreHome/Columns/LinkVisitActionId.php42
-rw-r--r--plugins/CoreHome/Columns/ServerMinute.php35
-rw-r--r--plugins/CoreHome/Columns/ServerTime.php21
-rw-r--r--plugins/CoreHome/Columns/UserId.php21
-rw-r--r--plugins/CoreHome/Columns/VisitFirstActionMinute.php45
-rw-r--r--plugins/CoreHome/Columns/VisitFirstActionTime.php22
-rw-r--r--plugins/CoreHome/Columns/VisitGoalBuyer.php48
-rw-r--r--plugins/CoreHome/Columns/VisitGoalConverted.php24
-rw-r--r--plugins/CoreHome/Columns/VisitId.php31
-rw-r--r--plugins/CoreHome/Columns/VisitIp.php31
-rw-r--r--plugins/CoreHome/Columns/VisitLastActionMinute.php51
-rw-r--r--plugins/CoreHome/Columns/VisitLastActionTime.php15
-rw-r--r--plugins/CoreHome/Columns/VisitTotalTime.php12
-rw-r--r--plugins/CoreHome/Columns/VisitorDaysSinceFirst.php13
-rw-r--r--plugins/CoreHome/Columns/VisitorDaysSinceOrder.php15
-rw-r--r--plugins/CoreHome/Columns/VisitorId.php33
-rw-r--r--plugins/CoreHome/Columns/VisitorReturning.php47
-rw-r--r--plugins/CoreHome/Columns/VisitsCount.php14
-rw-r--r--plugins/CoreHome/CoreHome.php24
-rw-r--r--plugins/CoreHome/Tracker/LogTable/Conversion.php5
-rw-r--r--plugins/CoreHome/Tracker/LogTable/ConversionItem.php7
-rw-r--r--plugins/CoreHome/Tracker/LogTable/LinkVisitAction.php5
-rw-r--r--plugins/CoreHome/Tracker/LogTable/Visit.php4
-rw-r--r--plugins/CoreHome/angularjs/common/services/piwik-api.js2
-rw-r--r--plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js6
-rw-r--r--plugins/CoreHome/lang/en.json4
-rw-r--r--plugins/CoreHome/templates/_dataTableActions.twig5
-rw-r--r--plugins/CorePluginsAdmin/CorePluginsAdmin.php1
-rw-r--r--plugins/CorePluginsAdmin/angularjs/field/field.directive.js6
-rw-r--r--plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.html24
-rw-r--r--plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.less88
-rw-r--r--plugins/CorePluginsAdmin/angularjs/form-field/field-multiselect.html2
-rw-r--r--plugins/CorePluginsAdmin/angularjs/form-field/field-radio.html2
-rw-r--r--plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.js33
m---------plugins/CustomDimensions0
-rw-r--r--plugins/CustomVariables/Categories/CustomVariablesCategory.php18
-rw-r--r--plugins/CustomVariables/Columns/SearchCategory.php26
-rw-r--r--plugins/CustomVariables/CustomDimension.php36
-rw-r--r--plugins/CustomVariables/CustomVariables.php19
-rw-r--r--plugins/CustomVariables/Model.php29
-rw-r--r--plugins/CustomVariables/lang/en.json1
-rw-r--r--plugins/CustomVariables/tests/Integration/ModelTest.php20
-rw-r--r--plugins/DevicePlugins/Columns/Plugin.php5
-rw-r--r--plugins/DevicePlugins/Columns/PluginCookie.php1
-rw-r--r--plugins/DevicePlugins/Columns/PluginDirector.php1
-rw-r--r--plugins/DevicePlugins/Columns/PluginFlash.php1
-rw-r--r--plugins/DevicePlugins/Columns/PluginGears.php1
-rw-r--r--plugins/DevicePlugins/Columns/PluginJava.php1
-rw-r--r--plugins/DevicePlugins/Columns/PluginPdf.php1
-rw-r--r--plugins/DevicePlugins/Columns/PluginQuickTime.php1
-rw-r--r--plugins/DevicePlugins/Columns/PluginRealPlayer.php1
-rw-r--r--plugins/DevicePlugins/Columns/PluginSilverlight.php1
-rw-r--r--plugins/DevicePlugins/Columns/PluginWindowsMedia.php1
-rw-r--r--plugins/DevicesDetection/Columns/BrowserEngine.php25
-rw-r--r--plugins/DevicesDetection/Columns/BrowserName.php21
-rw-r--r--plugins/DevicesDetection/Columns/BrowserVersion.php21
-rw-r--r--plugins/DevicesDetection/Columns/DeviceBrand.php23
-rw-r--r--plugins/DevicesDetection/Columns/DeviceModel.php9
-rw-r--r--plugins/DevicesDetection/Columns/DeviceType.php32
-rw-r--r--plugins/DevicesDetection/Columns/Os.php15
-rw-r--r--plugins/DevicesDetection/Columns/OsVersion.php21
-rw-r--r--plugins/DevicesDetection/Segment.php21
-rw-r--r--plugins/DevicesDetection/lang/en.json3
-rw-r--r--plugins/Ecommerce/Columns/Items.php18
-rw-r--r--plugins/Ecommerce/Columns/Order.php37
-rw-r--r--plugins/Ecommerce/Columns/ProductCategory.php7
-rw-r--r--plugins/Ecommerce/Columns/ProductName.php21
-rw-r--r--plugins/Ecommerce/Columns/ProductPrice.php21
-rw-r--r--plugins/Ecommerce/Columns/ProductQuantity.php21
-rw-r--r--plugins/Ecommerce/Columns/ProductSku.php21
-rw-r--r--plugins/Ecommerce/Columns/Revenue.php9
-rw-r--r--plugins/Ecommerce/Columns/RevenueDiscount.php3
-rw-r--r--plugins/Ecommerce/Columns/RevenueShipping.php3
-rw-r--r--plugins/Ecommerce/Columns/RevenueSubtotal.php3
-rw-r--r--plugins/Ecommerce/Columns/RevenueTax.php3
-rw-r--r--plugins/Ecommerce/Ecommerce.php52
-rw-r--r--plugins/Ecommerce/lang/en.json4
-rw-r--r--plugins/Events/Categories/EventsCategory.php19
-rw-r--r--plugins/Events/Columns/EventAction.php23
-rw-r--r--plugins/Events/Columns/EventCategory.php23
-rw-r--r--plugins/Events/Columns/EventName.php23
-rw-r--r--plugins/Events/Columns/EventValue.php56
-rw-r--r--plugins/Events/Columns/TotalEvents.php21
-rw-r--r--plugins/Events/Segment.php22
-rw-r--r--plugins/ExampleTracker/Columns/ExampleActionDimension.php33
-rw-r--r--plugins/ExampleTracker/Columns/ExampleConversionDimension.php29
-rw-r--r--plugins/ExampleTracker/Columns/ExampleDimension.php6
-rw-r--r--plugins/ExampleTracker/Columns/ExampleVisitDimension.php29
-rw-r--r--plugins/Goals/Columns/DaysToConversion.php6
-rw-r--r--plugins/Goals/Columns/IdGoal.php23
-rw-r--r--plugins/Goals/Columns/Revenue.php20
-rw-r--r--plugins/Goals/Columns/VisitsUntilConversion.php7
-rw-r--r--plugins/Goals/GoalDimension.php41
-rw-r--r--plugins/Goals/Goals.php71
-rw-r--r--plugins/Goals/lang/en.json6
-rw-r--r--plugins/Morpheus/stylesheets/main.less20
-rw-r--r--plugins/Morpheus/stylesheets/ui/_components.less26
-rw-r--r--plugins/Morpheus/templates/demo.twig16
-rw-r--r--plugins/Provider/Columns/Provider.php23
-rw-r--r--plugins/Referrers/Columns/Campaign.php6
-rw-r--r--plugins/Referrers/Columns/Keyword.php22
-rw-r--r--plugins/Referrers/Columns/Referrer.php6
-rw-r--r--plugins/Referrers/Columns/ReferrerName.php15
-rw-r--r--plugins/Referrers/Columns/ReferrerType.php29
-rw-r--r--plugins/Referrers/Columns/ReferrerUrl.php16
-rw-r--r--plugins/Referrers/Columns/SearchEngine.php6
-rw-r--r--plugins/Referrers/Columns/SocialNetwork.php6
-rw-r--r--plugins/Referrers/Columns/Website.php8
-rw-r--r--plugins/Referrers/Columns/WebsitePage.php6
-rw-r--r--plugins/Referrers/Segment.php21
-rw-r--r--plugins/Referrers/functions.php4
-rw-r--r--plugins/Referrers/lang/en.json2
-rw-r--r--plugins/Resolution/Columns/Configuration.php5
-rw-r--r--plugins/Resolution/Columns/Resolution.php19
-rw-r--r--plugins/Resolution/Segment.php21
-rw-r--r--plugins/SegmentEditor/SegmentEditor.php19
-rw-r--r--plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator-model.js69
-rw-r--r--plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.controller.js319
-rw-r--r--plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.html61
-rw-r--r--plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.js64
-rw-r--r--plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.less204
-rw-r--r--plugins/SegmentEditor/javascripts/Segmentation.js516
-rw-r--r--plugins/SegmentEditor/stylesheets/segmentation.less264
-rw-r--r--plugins/SegmentEditor/templates/_segmentSelector.twig100
-rw-r--r--plugins/SegmentEditor/tests/Integration/SegmentEditorTest.php2
-rw-r--r--plugins/UserCountry/Categories/LocationsCategory.php17
-rw-r--r--plugins/UserCountry/Columns/City.php22
-rw-r--r--plugins/UserCountry/Columns/Continent.php23
-rw-r--r--plugins/UserCountry/Columns/Country.php30
-rw-r--r--plugins/UserCountry/Columns/Latitude.php22
-rw-r--r--plugins/UserCountry/Columns/Longitude.php22
-rw-r--r--plugins/UserCountry/Columns/Provider.php2
-rw-r--r--plugins/UserCountry/Columns/Region.php22
-rw-r--r--plugins/UserCountry/Segment.php21
-rw-r--r--plugins/UserCountry/lang/en.json4
-rw-r--r--plugins/UserId/Columns/UserId.php9
-rw-r--r--plugins/UserLanguage/Columns/Language.php21
-rw-r--r--plugins/VisitTime/Columns/DayOfTheWeek.php5
-rw-r--r--plugins/VisitTime/Columns/LocalMinute.php43
-rw-r--r--plugins/VisitTime/Columns/LocalTime.php24
-rw-r--r--plugins/VisitTime/Columns/ServerTime.php33
-rw-r--r--plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php6
-rw-r--r--plugins/VisitTime/Segment.php21
-rw-r--r--plugins/VisitTime/lang/en.json8
-rw-r--r--plugins/VisitorInterest/Columns/PagesPerVisit.php5
-rw-r--r--plugins/VisitorInterest/Columns/VisitDuration.php7
-rw-r--r--plugins/VisitorInterest/Columns/VisitsByDaysSinceLastVisit.php14
-rw-r--r--plugins/VisitorInterest/Columns/VisitsbyVisitNumber.php5
185 files changed, 2820 insertions, 1929 deletions
diff --git a/plugins/API/API.php b/plugins/API/API.php
index 2100ea825f..4e27e5e663 100644
--- a/plugins/API/API.php
+++ b/plugins/API/API.php
@@ -29,6 +29,7 @@ use Piwik\Plugin\SettingsProvider;
use Piwik\Plugins\API\DataTable\MergeDataTables;
use Piwik\Plugins\CoreAdminHome\CustomLogo;
use Piwik\Plugins\CorePluginsAdmin\SettingsMetadata;
+use Piwik\Site;
use Piwik\Translation\Translator;
use Piwik\Measurable\Type\TypeManager;
use Piwik\Version;
@@ -152,6 +153,7 @@ class API extends \Piwik\Plugin\API
if (empty($idSites)) {
Piwik::checkUserHasSomeViewAccess();
} else {
+ $idSites = Site::getIdSitesFromIdSitesString($idSites);
Piwik::checkUserHasViewAccess($idSites);
}
@@ -433,9 +435,27 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasViewAccess($idSite);
+ $apiParameters = array();
+ $entityNames = StaticContainer::get('entities.idNames');
+ foreach ($entityNames as $entityName) {
+ if ($entityName === 'idGoal' && $idGoal) {
+ $apiParameters['idGoal'] = $idGoal;
+ } elseif ($entityName === 'idDimension' && $idDimension) {
+ $apiParameters['idDimension'] = $idDimension;
+ } else {
+ // ideally it would get the value from API params but dynamic params is not possible yet in API. If this
+ // method is called eg in Request::processRequest, it could in theory pick up a param from the original request
+ // and not from the API request within the original request.
+ $idEntity = Common::getRequestVar($entityName, 0, 'int');
+ if ($idEntity > 0) {
+ $apiParameters[$entityName] = $idEntity;
+ }
+ }
+ }
+
$rowEvolution = new RowEvolution();
return $rowEvolution->getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label, $segment, $column,
- $language, $idGoal, $legendAppendMetric, $labelUseAbsoluteUrl, $idDimension);
+ $language, $apiParameters, $legendAppendMetric, $labelUseAbsoluteUrl);
}
/**
diff --git a/plugins/API/ProcessedReport.php b/plugins/API/ProcessedReport.php
index 360d6b7ddf..1cd327c8c7 100644
--- a/plugins/API/ProcessedReport.php
+++ b/plugins/API/ProcessedReport.php
@@ -14,6 +14,7 @@ use Piwik\Archive\DataTableFactory;
use Piwik\CacheId;
use Piwik\Cache as PiwikCache;
use Piwik\Common;
+use Piwik\Container\StaticContainer;
use Piwik\DataTable;
use Piwik\DataTable\Row;
use Piwik\DataTable\Simple;
@@ -48,6 +49,18 @@ class ProcessedReport
{
$reportsMetadata = $this->getReportMetadata($idSite, $period, $date, $hideMetricsDoc, $showSubtableReports);
+ $entityNames = StaticContainer::get('entities.idNames');
+ foreach ($entityNames as $entityName) {
+ if ($entityName === 'idGoal' || $entityName === 'idDimension') {
+ continue; // idGoal and idDimension is passed directly but for other entities we need to "workaround" and
+ // check for eg idFoo from GET/POST because we cannot add parameters to API dynamically
+ }
+ $idEntity = Common::getRequestVar($entityName, 0, 'int');
+ if ($idEntity > 0) {
+ $apiParameters[$entityName] = $idEntity;
+ }
+ }
+
foreach ($reportsMetadata as $report) {
// See ArchiveProcessor/Aggregator.php - unique visitors are not processed for period != day
// todo: should use SettingsPiwik::isUniqueVisitorsEnabled instead
@@ -73,6 +86,7 @@ class ProcessedReport
}
}
}
+
return false;
}
diff --git a/plugins/API/RowEvolution.php b/plugins/API/RowEvolution.php
index f7af6b93b1..41c75bffde 100644
--- a/plugins/API/RowEvolution.php
+++ b/plugins/API/RowEvolution.php
@@ -36,7 +36,7 @@ class RowEvolution
'getPageUrl'
);
- public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true, $idDimension = false)
+ public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $apiParameters = array(), $legendAppendMetric = true, $labelUseAbsoluteUrl = true)
{
// validation of requested $period & $date
if ($period == 'range') {
@@ -51,9 +51,9 @@ class RowEvolution
$label = DataTablePostProcessor::unsanitizeLabelParameter($label);
$labels = Piwik::getArrayFromApiParameter($label);
- $metadata = $this->getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $idGoal, $idDimension);
+ $metadata = $this->getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $apiParameters);
- $dataTable = $this->loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $idGoal, $idDimension);
+ $dataTable = $this->loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $apiParameters);
if (empty($labels)) {
$labels = $this->getLabelsFromDataTable($dataTable, $labels);
@@ -244,11 +244,11 @@ class RowEvolution
* @param string $apiAction
* @param string|bool $label
* @param string|bool $segment
- * @param int|bool $idGoal
+ * @param array $apiParameters
* @throws Exception
* @return DataTable\Map|DataTable
*/
- private function loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $idGoal = false, $idDimension = false)
+ private function loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $apiParameters)
{
if (!is_array($label)) {
$label = array($label);
@@ -264,9 +264,6 @@ class RowEvolution
'format' => 'original',
'serialize' => '0',
'segment' => $segment,
- 'idGoal' => $idGoal,
- 'idDimension' => $idDimension,
-
// data for row evolution should NOT be limited
'filter_limit' => -1,
@@ -275,6 +272,11 @@ class RowEvolution
// can be sorted in a different order)
'labelFilterAddLabelIndex' => count($label) > 1 ? 1 : 0,
);
+ if (!empty($apiParameters) && is_array($apiParameters)) {
+ foreach ($apiParameters as $param => $value) {
+ $parameters[$param] = $value;
+ }
+ }
// add "processed metrics" like actions per visit or bounce rate
// note: some reports should not be filtered with AddColumnProcessedMetrics
@@ -306,19 +308,12 @@ class RowEvolution
* @param $apiModule
* @param $apiAction
* @param $language
- * @param $idGoal
+ * @param $apiParameters
* @throws Exception
* @return array
*/
- private function getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $idGoal = false, $idDimension = false)
+ private function getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $apiParameters)
{
- $apiParameters = array();
- if (!empty($idGoal) && $idGoal > 0) {
- $apiParameters = array('idGoal' => $idGoal);
- }
- if (!empty($idDimension) && $idDimension > 0) {
- $apiParameters = array('idDimension' => (int) $idDimension);
- }
$reportMetadata = API::getInstance()->getMetadata($idSite, $apiModule, $apiAction, $apiParameters, $language,
$period, $date, $hideMetricsDoc = false, $showSubtableReports = true);
diff --git a/plugins/API/SegmentMetadata.php b/plugins/API/SegmentMetadata.php
index 1cce5fd3dd..03f6f64336 100644
--- a/plugins/API/SegmentMetadata.php
+++ b/plugins/API/SegmentMetadata.php
@@ -8,12 +8,19 @@
*/
namespace Piwik\Plugins\API;
+use Piwik\Category\CategoryList;
use Piwik\Columns\Dimension;
use Piwik\Piwik;
use Piwik\Plugin\Segment;
class SegmentMetadata
{
+ /**
+ * Map of category name to order
+ * @var array
+ */
+ private $categoryOrder = array();
+
public function getSegmentsMetadata($idSites = array(), $_hideImplementationData = true, $isAuthenticatedWithViewAccess)
{
$segments = array();
@@ -55,9 +62,21 @@ class SegmentMetadata
$segments[] = $segment->toArray();
}
+ $categoryList = CategoryList::get();
+
foreach ($segments as &$segment) {
+ $categoryId = $segment['category'];
$segment['name'] = Piwik::translate($segment['name']);
- $segment['category'] = Piwik::translate($segment['category']);
+ $segment['category'] = Piwik::translate($categoryId);
+
+ if (!isset($this->categoryOrder[$segment['category']])) {
+ $category = $categoryList->getCategory($categoryId);
+ if (!empty($category)) {
+ $this->categoryOrder[$segment['category']] = $category->getOrder();
+ } else {
+ $this->categoryOrder[$segment['category']] = 999;
+ }
+ }
if ($_hideImplementationData) {
unset($segment['sqlFilter']);
@@ -81,12 +100,25 @@ class SegmentMetadata
{
$customVarCategory = Piwik::translate('CustomVariables_CustomVariables');
- $columns = array('type', 'category', 'name', 'segment');
+ $columns = array('category', 'type', 'name', 'segment');
foreach ($columns as $column) {
// Keep segments ordered alphabetically inside categories..
$type = -1;
- if ($column == 'name') $type = 1;
+ if ($column == 'name') {
+ $type = 1;
+ }
+
+ if ($column === 'category') {
+ $idOrder1 = $this->categoryOrder[$row1[$column]];
+ $idOrder2 = $this->categoryOrder[$row2[$column]];
+
+ if ($idOrder1 === $idOrder2) {
+ continue;
+ }
+
+ return $idOrder1 > $idOrder2 ? 1 : -1;
+ }
$compare = $type * strcmp($row1[$column], $row2[$column]);
diff --git a/plugins/Actions/Columns/ActionType.php b/plugins/Actions/Columns/ActionType.php
index 59f09c87e9..c407403588 100644
--- a/plugins/Actions/Columns/ActionType.php
+++ b/plugins/Actions/Columns/ActionType.php
@@ -8,9 +8,9 @@
*/
namespace Piwik\Plugins\Actions\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
use Piwik\Tracker\Action;
use Exception;
@@ -30,41 +30,27 @@ class ActionType extends ActionDimension
Action::TYPE_DOWNLOAD => 'downloads'
);
- /**
- * The name of the dimension which will be visible for instance in the UI of a related report and in the mobile app.
- * @return string
- */
- public function getName()
+ protected $columnName = 'type';
+ protected $dbTableName = 'log_action';
+ protected $segmentName = 'actionType';
+ protected $type = self::TYPE_ENUM;
+ protected $nameSingular = 'Actions_ActionType';
+ protected $namePlural = 'Actions_ActionTypes';
+ protected $category = 'General_Actions';
+
+ public function __construct()
{
- return Piwik::translate('Actions_ActionType');
+ $this->acceptValues = sprintf('A type of action, such as: %s', implode(', ', $this->types));
}
- protected function configureSegments()
+ public function getEnumColumnValues()
{
- $types = $this->types;
-
- $segment = new Segment();
- $segment->setSegment('actionType');
- $segment->setName('Actions_ActionType');
- $segment->setSqlSegment('log_action.type');
- $segment->setType(Segment::TYPE_DIMENSION);
- $segment->setAcceptedValues(sprintf('A type of action, such as: %s', implode(', ', $types)));
- $segment->setSqlFilter(function ($type) use ($types) {
- if (array_key_exists($type, $types)) {
- return $type;
- }
-
- $index = array_search(strtolower(trim(urldecode($type))), $types);
-
- if ($index === false) {
- throw new Exception("actionType must be one of: " . implode(', ', $types));
- }
+ return $this->types;
+ }
- return $index;
- });
- $segment->setSuggestedValuesCallback(function ($idSite, $maxSuggestionsToReturn) use ($types) {
- return array_slice(array_values($types), 0, $maxSuggestionsToReturn);
- });
- $this->addSegment($segment);
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ // do not genereate any metric for this
}
+
} \ No newline at end of file
diff --git a/plugins/Actions/Columns/ActionUrl.php b/plugins/Actions/Columns/ActionUrl.php
index 5fa80d1efa..13fdecc033 100644
--- a/plugins/Actions/Columns/ActionUrl.php
+++ b/plugins/Actions/Columns/ActionUrl.php
@@ -14,10 +14,7 @@ use Piwik\Plugins\Actions\Segment;
class ActionUrl extends ActionDimension
{
- public function getName()
- {
- return Piwik::translate('Actions_ColumnActionURL');
- }
+ protected $nameSingular = 'Actions_ColumnActionURL';
protected function configureSegments()
{
diff --git a/plugins/Actions/Columns/ClickedUrl.php b/plugins/Actions/Columns/ClickedUrl.php
index cd9bc3b7dc..861b6d5202 100644
--- a/plugins/Actions/Columns/ClickedUrl.php
+++ b/plugins/Actions/Columns/ClickedUrl.php
@@ -8,24 +8,28 @@
*/
namespace Piwik\Plugins\Actions\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
+use Piwik\Tracker\Action;
class ClickedUrl extends ActionDimension
{
- public function getName()
+ protected $columnName = 'idaction_url';
+ protected $segmentName = 'outlinkUrl';
+ protected $nameSingular = 'Actions_ColumnClickedURL';
+ protected $namePlural = 'Actions_ColumnClickedURLs';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
+ protected $type = self::TYPE_URL;
+
+ public function getDbColumnJoin()
{
- return Piwik::translate('Actions_ColumnClickedURL');
+ return new ActionNameJoin();
}
- protected function configureSegments()
+ public function getDbDiscriminator()
{
- $segment = new Segment();
- $segment->setSegment('outlinkUrl');
- $segment->setName('Actions_ColumnClickedURL');
- $segment->setSqlSegment('log_link_visit_action.idaction_url');
- $this->addSegment($segment);
+ return new Discriminator('log_action', 'type', Action::TYPE_OUTLINK);
}
-
}
diff --git a/plugins/Actions/Columns/DestinationPage.php b/plugins/Actions/Columns/DestinationPage.php
index e47b7195be..4b2b3eb184 100644
--- a/plugins/Actions/Columns/DestinationPage.php
+++ b/plugins/Actions/Columns/DestinationPage.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class DestinationPage extends Dimension
{
- public function getName()
- {
- return Piwik::translate('General_ColumnDestinationPage');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'General_ColumnDestinationPage';
} \ No newline at end of file
diff --git a/plugins/Actions/Columns/DownloadUrl.php b/plugins/Actions/Columns/DownloadUrl.php
index d611e86f21..6375bba69b 100644
--- a/plugins/Actions/Columns/DownloadUrl.php
+++ b/plugins/Actions/Columns/DownloadUrl.php
@@ -8,24 +8,28 @@
*/
namespace Piwik\Plugins\Actions\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
+use Piwik\Tracker\Action;
class DownloadUrl extends ActionDimension
{
- public function getName()
+ protected $segmentName = 'downloadUrl';
+ protected $nameSingular = 'Actions_ColumnDownloadURL';
+ protected $namePlural = 'Actions_ColumnDownloadURLs';
+ protected $columnName = 'idaction_url';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
+ protected $type = self::TYPE_URL;
+
+ public function getDbColumnJoin()
{
- return Piwik::translate('Actions_ColumnDownloadURL');
+ return new ActionNameJoin();
}
- protected function configureSegments()
+ public function getDbDiscriminator()
{
- $segment = new Segment();
- $segment->setSegment('downloadUrl');
- $segment->setName('Actions_ColumnDownloadURL');
- $segment->setSqlSegment('log_link_visit_action.idaction_url');
- $this->addSegment($segment);
+ return new Discriminator('log_action', 'type', Action::TYPE_DOWNLOAD);
}
-
}
diff --git a/plugins/Actions/Columns/EntryPageTitle.php b/plugins/Actions/Columns/EntryPageTitle.php
index 30445f9549..5034f72408 100644
--- a/plugins/Actions/Columns/EntryPageTitle.php
+++ b/plugins/Actions/Columns/EntryPageTitle.php
@@ -8,8 +8,8 @@
*/
namespace Piwik\Plugins\Actions\Columns;
-use Piwik\Piwik;
-use Piwik\Plugins\Actions\Segment;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -19,13 +19,21 @@ class EntryPageTitle extends VisitDimension
{
protected $columnName = 'visit_entry_idaction_name';
protected $columnType = 'INTEGER(10) UNSIGNED NULL';
+ protected $type = self::TYPE_TEXT;
+ protected $segmentName = 'entryPageTitle';
+ protected $nameSingular = 'Actions_ColumnEntryPageTitle';
+ protected $namePlural = 'Actions_WidgetEntryPageTitles';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
- protected function configureSegments()
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('entryPageTitle');
- $segment->setName('Actions_ColumnEntryPageTitle');
- $this->addSegment($segment);
+ return new ActionNameJoin();
+ }
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator('log_action', 'type', Action::TYPE_PAGE_TITLE);
}
/**
@@ -44,9 +52,4 @@ class EntryPageTitle extends VisitDimension
return (int) $idActionName;
}
-
- public function getName()
- {
- return Piwik::translate('Actions_ColumnEntryPageTitle');
- }
}
diff --git a/plugins/Actions/Columns/EntryPageUrl.php b/plugins/Actions/Columns/EntryPageUrl.php
index 6b67b9a092..25750024da 100644
--- a/plugins/Actions/Columns/EntryPageUrl.php
+++ b/plugins/Actions/Columns/EntryPageUrl.php
@@ -8,8 +8,8 @@
*/
namespace Piwik\Plugins\Actions\Columns;
-use Piwik\Piwik;
-use Piwik\Plugins\Actions\Segment;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -19,13 +19,21 @@ class EntryPageUrl extends VisitDimension
{
protected $columnName = 'visit_entry_idaction_url';
protected $columnType = 'INTEGER(11) UNSIGNED NULL DEFAULT NULL';
+ protected $segmentName = 'entryPageUrl';
+ protected $nameSingular = 'Actions_ColumnEntryPageURL';
+ protected $namePlural = 'Actions_ColumnEntryPageURLs';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
+ protected $type = self::TYPE_URL;
- protected function configureSegments()
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('entryPageUrl');
- $segment->setName('Actions_ColumnEntryPageURL');
- $this->addSegment($segment);
+ return new ActionNameJoin();
+ }
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator('log_action', 'type', Action::TYPE_PAGE_URL);
}
/**
@@ -69,9 +77,4 @@ class EntryPageUrl extends VisitDimension
return false;
}
- public function getName()
- {
- return Piwik::translate('Actions_ColumnEntryPageURL');
- }
-
}
diff --git a/plugins/Actions/Columns/ExitPageTitle.php b/plugins/Actions/Columns/ExitPageTitle.php
index 97428d9ad9..6207eff5fd 100644
--- a/plugins/Actions/Columns/ExitPageTitle.php
+++ b/plugins/Actions/Columns/ExitPageTitle.php
@@ -8,8 +8,8 @@
*/
namespace Piwik\Plugins\Actions\Columns;
-use Piwik\Piwik;
-use Piwik\Plugins\Actions\Segment;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -19,13 +19,21 @@ class ExitPageTitle extends VisitDimension
{
protected $columnName = 'visit_exit_idaction_name';
protected $columnType = 'INTEGER(10) UNSIGNED NULL';
+ protected $segmentName = 'exitPageTitle';
+ protected $nameSingular = 'Actions_ColumnExitPageTitle';
+ protected $namePlural = 'Actions_WidgetExitPageTitles';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
+ protected $type = self::TYPE_TEXT;
- protected function configureSegments()
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('exitPageTitle');
- $segment->setName('Actions_ColumnExitPageTitle');
- $this->addSegment($segment);
+ return new ActionNameJoin();
+ }
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator('log_action', 'type', Action::TYPE_PAGE_TITLE);
}
/**
@@ -59,9 +67,4 @@ class ExitPageTitle extends VisitDimension
return $action->getIdActionNameForEntryAndExitIds();
}
-
- public function getName()
- {
- return Piwik::translate('Actions_ColumnExitPageTitle');
- }
}
diff --git a/plugins/Actions/Columns/ExitPageUrl.php b/plugins/Actions/Columns/ExitPageUrl.php
index 094719bb75..c9e35e9da4 100644
--- a/plugins/Actions/Columns/ExitPageUrl.php
+++ b/plugins/Actions/Columns/ExitPageUrl.php
@@ -8,8 +8,11 @@
*/
namespace Piwik\Plugins\Actions\Columns;
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join;
+use Piwik\Columns\MetricsList;
use Piwik\Piwik;
-use Piwik\Plugins\Actions\Segment;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -19,13 +22,26 @@ class ExitPageUrl extends VisitDimension
{
protected $columnName = 'visit_exit_idaction_url';
protected $columnType = 'INTEGER(10) UNSIGNED NULL DEFAULT 0';
+ protected $type = self::TYPE_URL;
+ protected $segmentName = 'exitPageUrl';
+ protected $nameSingular = 'Actions_ColumnExitPageURL';
+ protected $namePlural = 'Actions_ColumnExitPageURLs';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
- protected function configureSegments()
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
{
- $segment = new Segment();
- $segment->setSegment('exitPageUrl');
- $segment->setName('Actions_ColumnExitPageURL');
- $this->addSegment($segment);
+ parent::configureMetrics($metricsList, $dimensionMetricFactory);
+ }
+
+ public function getDbColumnJoin()
+ {
+ return new Join\ActionNameJoin();
+ }
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator('log_action', 'type', Action::TYPE_PAGE_URL);
}
/**
@@ -65,9 +81,4 @@ class ExitPageUrl extends VisitDimension
return $id;
}
-
- public function getName()
- {
- return Piwik::translate('Actions_ColumnExitPageURL');
- }
}
diff --git a/plugins/Actions/Columns/IdPageview.php b/plugins/Actions/Columns/IdPageview.php
index c1d5352153..219fa7cbc0 100644
--- a/plugins/Actions/Columns/IdPageview.php
+++ b/plugins/Actions/Columns/IdPageview.php
@@ -8,6 +8,8 @@
*/
namespace Piwik\Plugins\Actions\Columns;
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -18,6 +20,8 @@ class IdPageview extends ActionDimension
{
protected $columnName = 'idpageview';
protected $columnType = 'CHAR(6) NULL DEFAULT NULL';
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'Actions_ColumnIdPageview';
/**
* @param Request $request
@@ -32,9 +36,9 @@ class IdPageview extends ActionDimension
return substr($request->getParam('pv_id'), 0, 6);
}
- public function getName()
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
{
- return Piwik::translate('Actions_ColumnIdPageview');
+ // metrics for idpageview do not really make any sense
}
} \ No newline at end of file
diff --git a/plugins/Actions/Columns/InteractionPosition.php b/plugins/Actions/Columns/InteractionPosition.php
index 13c85ede65..c825669450 100644
--- a/plugins/Actions/Columns/InteractionPosition.php
+++ b/plugins/Actions/Columns/InteractionPosition.php
@@ -19,6 +19,8 @@ class InteractionPosition extends ActionDimension
{
protected $columnName = 'interaction_position';
protected $columnType = 'SMALLINT UNSIGNED DEFAULT NULL';
+ protected $nameSingular = 'Actions_ColumnInteractionPosition';
+ protected $type = self::TYPE_NUMBER;
/**
* @param Request $request
@@ -46,9 +48,4 @@ class InteractionPosition extends ActionDimension
return false;
}
- public function getName()
- {
- return Piwik::translate('Actions_ColumnInteractionPosition');
- }
-
} \ No newline at end of file
diff --git a/plugins/Actions/Columns/Keyword.php b/plugins/Actions/Columns/Keyword.php
index 3d7051c451..7c7a5aa915 100644
--- a/plugins/Actions/Columns/Keyword.php
+++ b/plugins/Actions/Columns/Keyword.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class Keyword extends Dimension
{
- public function getName()
- {
- return Piwik::translate('General_ColumnKeyword');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'General_ColumnKeyword';
} \ No newline at end of file
diff --git a/plugins/Actions/Columns/KeywordwithNoSearchResult.php b/plugins/Actions/Columns/KeywordwithNoSearchResult.php
index d6ffaf2044..e96e50eaa3 100644
--- a/plugins/Actions/Columns/KeywordwithNoSearchResult.php
+++ b/plugins/Actions/Columns/KeywordwithNoSearchResult.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class KeywordwithNoSearchResult extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Actions_ColumnNoResultKeyword');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'Actions_ColumnNoResultKeyword';
} \ No newline at end of file
diff --git a/plugins/Actions/Columns/Metrics/AveragePageGenerationTime.php b/plugins/Actions/Columns/Metrics/AveragePageGenerationTime.php
index 9b44e88943..ed89226ac0 100644
--- a/plugins/Actions/Columns/Metrics/AveragePageGenerationTime.php
+++ b/plugins/Actions/Columns/Metrics/AveragePageGenerationTime.php
@@ -13,7 +13,6 @@ use Piwik\Metrics;
use Piwik\Metrics\Formatter;
use Piwik\Piwik;
use Piwik\Plugin\ProcessedMetric;
-use Piwik\Plugin\Report;
/**
* The average amount of time it takes to generate a page. Calculated as
diff --git a/plugins/Actions/Columns/PageGenerationTime.php b/plugins/Actions/Columns/PageGenerationTime.php
new file mode 100644
index 0000000000..d7c8344db4
--- /dev/null
+++ b/plugins/Actions/Columns/PageGenerationTime.php
@@ -0,0 +1,50 @@
+<?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\Actions\Columns;
+
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\MetricsList;
+use Piwik\Piwik;
+use Piwik\Plugin\ArchivedMetric;
+use Piwik\Plugin\ComputedMetric;
+use Piwik\Plugin\Dimension\ActionDimension;
+use Piwik\Tracker\Action;
+
+class PageGenerationTime extends ActionDimension
+{
+ protected $nameSingular = 'General_ColumnPageGenerationTime';
+ protected $columnName = 'custom_float';
+ protected $category = 'General_Actions';
+ protected $type = self::TYPE_DURATION_MS;
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator('log_action', 'type', Action::TYPE_PAGE_URL);
+ }
+
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ $metric1 = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_SUM);
+ $metricsList->addMetric($metric1);
+
+ $metric2 = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_MAX);
+ $metricsList->addMetric($metric2);
+
+ $metric3 = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_COUNT_WITH_NUMERIC_VALUE);
+ $metric3->setName('pageviews_with_generation_time');
+ $metric3->setTranslatedName(Piwik::translate('General_ColumnViewsWithGenerationTime'));
+ $metricsList->addMetric($metric3);
+
+ $metric = $dimensionMetricFactory->createComputedMetric($metric1->getName(), $metric3->getName(), ComputedMetric::AGGREGATION_AVG);
+ $metric->setName('avg_page_generation_time');
+ $metric->setTranslatedName(Piwik::translate('General_ColumnAverageGenerationTime'));
+ $metricsList->addMetric($metric);
+ }
+}
diff --git a/plugins/Actions/Columns/PageTitle.php b/plugins/Actions/Columns/PageTitle.php
index 6517bede92..77bdac1099 100644
--- a/plugins/Actions/Columns/PageTitle.php
+++ b/plugins/Actions/Columns/PageTitle.php
@@ -8,26 +8,29 @@
*/
namespace Piwik\Plugins\Actions\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
+use Piwik\Tracker\Action;
class PageTitle extends ActionDimension
{
protected $columnName = 'idaction_name';
protected $columnType = 'INTEGER(10) UNSIGNED';
+ protected $type = self::TYPE_TEXT;
+ protected $segmentName = 'pageTitle';
+ protected $nameSingular = 'Goals_PageTitle';
+ protected $namePlural = 'Actions_WidgetPageTitles';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
- protected function configureSegments()
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('pageTitle');
- $segment->setName('Actions_ColumnPageName');
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('Actions_ColumnPageName');
+ return new Discriminator('log_action', 'type', Action::TYPE_PAGE_TITLE);
}
-
}
diff --git a/plugins/Actions/Columns/PageUrl.php b/plugins/Actions/Columns/PageUrl.php
index 1f9a7035e5..a236f0e28e 100644
--- a/plugins/Actions/Columns/PageUrl.php
+++ b/plugins/Actions/Columns/PageUrl.php
@@ -8,26 +8,32 @@
*/
namespace Piwik\Plugins\Actions\Columns;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
+use Piwik\Tracker\Action;
class PageUrl extends ActionDimension
{
protected $columnName = 'idaction_url';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
+ protected $segmentName = 'pageUrl';
+ protected $nameSingular = 'Actions_ColumnPageURL';
+ protected $namePlural = 'Actions_PageUrls';
+ protected $type = self::TYPE_URL;
+ protected $acceptValues = 'All these segments must be URL encoded, for example: http%3A%2F%2Fexample.com%2Fpath%2Fpage%3Fquery';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
- protected function configureSegments()
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('pageUrl');
- $segment->setName('Actions_ColumnPageURL');
- $segment->setAcceptedValues('All these segments must be URL encoded, for example: ' . urlencode('http://example.com/path/page?query'));
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('Actions_ColumnPageURL');
+ return new Discriminator('log_action', 'type', Action::TYPE_PAGE_URL);
}
+
}
diff --git a/plugins/Actions/Columns/SearchCategory.php b/plugins/Actions/Columns/SearchCategory.php
index 6dc3c0b11b..e61ac25136 100644
--- a/plugins/Actions/Columns/SearchCategory.php
+++ b/plugins/Actions/Columns/SearchCategory.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class SearchCategory extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Actions_ColumnSearchCategory');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'Actions_ColumnSearchCategory';
} \ No newline at end of file
diff --git a/plugins/Actions/Columns/SearchDestinationPage.php b/plugins/Actions/Columns/SearchDestinationPage.php
index bf36621a9c..4e3271892d 100644
--- a/plugins/Actions/Columns/SearchDestinationPage.php
+++ b/plugins/Actions/Columns/SearchDestinationPage.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class SearchDestinationPage extends Dimension
{
- public function getName()
- {
- return Piwik::translate('General_ColumnDestinationPage');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'General_ColumnDestinationPage';
}
diff --git a/plugins/Actions/Columns/SearchKeyword.php b/plugins/Actions/Columns/SearchKeyword.php
index f3248da5cf..48283eae02 100644
--- a/plugins/Actions/Columns/SearchKeyword.php
+++ b/plugins/Actions/Columns/SearchKeyword.php
@@ -8,23 +8,27 @@
*/
namespace Piwik\Plugins\Actions\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
+use Piwik\Tracker\Action;
class SearchKeyword extends ActionDimension
{
- protected function configureSegments()
+ protected $columnName = 'idaction_name';
+ protected $segmentName = 'siteSearchKeyword';
+ protected $nameSingular = 'Actions_SiteSearchKeyword';
+ protected $namePlural = 'Actions_SiteSearchKeywords';
+ protected $type = self::TYPE_TEXT;
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
+
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('siteSearchKeyword');
- $segment->setName('Actions_SiteSearchKeyword');
- $segment->setSqlSegment('log_link_visit_action.idaction_name');
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('General_ColumnKeyword');
+ return new Discriminator('log_action', 'type', Action::TYPE_SITE_SEARCH);
}
}
diff --git a/plugins/Actions/Columns/SearchNoResultKeyword.php b/plugins/Actions/Columns/SearchNoResultKeyword.php
index f4b57c6431..3245d31efc 100644
--- a/plugins/Actions/Columns/SearchNoResultKeyword.php
+++ b/plugins/Actions/Columns/SearchNoResultKeyword.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class SearchNoResultKeyword extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Actions_ColumnNoResultKeyword');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'Actions_ColumnNoResultKeyword';
}
diff --git a/plugins/Actions/Columns/TimeSpentRefAction.php b/plugins/Actions/Columns/TimeSpentRefAction.php
index a51cac9d59..2b0a8c2526 100644
--- a/plugins/Actions/Columns/TimeSpentRefAction.php
+++ b/plugins/Actions/Columns/TimeSpentRefAction.php
@@ -17,6 +17,7 @@ class TimeSpentRefAction extends ActionDimension
{
protected $columnName = 'time_spent_ref_action';
protected $columnType = 'INTEGER(10) UNSIGNED NULL';
+ protected $type = self::TYPE_DURATION_S;
public function onNewAction(Request $request, Visitor $visitor, Action $action)
{
diff --git a/plugins/Actions/Columns/VisitTotalActions.php b/plugins/Actions/Columns/VisitTotalActions.php
index 750cfc8667..85ddc9336d 100644
--- a/plugins/Actions/Columns/VisitTotalActions.php
+++ b/plugins/Actions/Columns/VisitTotalActions.php
@@ -8,25 +8,42 @@
*/
namespace Piwik\Plugins\Actions\Columns;
+use Piwik\Columns\MetricsList;
+use Piwik\Piwik;
+use Piwik\Plugin\ArchivedMetric;
+use Piwik\Plugin\ComputedMetric;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\CoreHome\Segment;
+use Piwik\Columns\DimensionMetricFactory;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
-use Piwik\Tracker;
use Piwik\Tracker\Visitor;
class VisitTotalActions extends VisitDimension
{
protected $columnName = 'visit_total_actions';
protected $columnType = 'INT(11) UNSIGNED NULL';
+ protected $metricId = 'actions';
+ protected $nameSingular = 'Actions_ActionsInVisit';
+ protected $segmentName = 'actions';
+ protected $type = self::TYPE_NUMBER;
- protected function configureSegments()
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
{
- $segment = new Segment();
- $segment->setType(Segment::TYPE_METRIC);
- $segment->setSegment('actions');
- $segment->setName('General_NbActions');
- $this->addSegment($segment);
+ $metric1 = $dimensionMetricFactory->createCustomMetric('bounce_count', Piwik::translate('General_ColumnBounces'), 'sum(case %s when 1 then 1 when 0 then 1 else 0 end)');
+ $metric1->setDocumentation(Piwik::translate('General_ColumnBouncesDocumentation'));
+ $metricsList->addMetric($metric1);
+
+ $metric = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_SUM);
+ $metricsList->addMetric($metric);
+
+ $metric = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_MAX);
+ $metricsList->addMetric($metric);
+
+ $metric = $dimensionMetricFactory->createComputedMetric($metric1->getName(), 'nb_visits', ComputedMetric::AGGREGATION_RATE);
+ $metric->setTranslatedName(Piwik::translate('General_ColumnBounceRate'));
+ $metric->setName('bounce_rate');
+ $metric->setDocumentation(Piwik::translate('General_ColumnBounceRateDocumentation'));
+ $metricsList->addMetric($metric);
}
/**
diff --git a/plugins/Actions/Columns/VisitTotalInteractions.php b/plugins/Actions/Columns/VisitTotalInteractions.php
index 9c10b1e03a..a41244211c 100644
--- a/plugins/Actions/Columns/VisitTotalInteractions.php
+++ b/plugins/Actions/Columns/VisitTotalInteractions.php
@@ -18,20 +18,18 @@ class VisitTotalInteractions extends VisitDimension
{
protected $columnName = 'visit_total_interactions';
protected $columnType = 'SMALLINT UNSIGNED DEFAULT 0';
+ protected $type = self::TYPE_NUMBER;
+ protected $segmentName = 'interactions';
+ protected $nameSingular = 'General_NbInteractions';
+ protected $acceptValues = 'Any positive integer';
- protected function configureSegments()
+ public function __construct()
{
- $segment = new Segment();
- $segment->setType(Segment::TYPE_METRIC);
- $segment->setSegment('interactions');
- $segment->setName('General_NbInteractions');
- $segment->setAcceptedValues('Any positive integer');
- $segment->setSuggestedValuesCallback(function ($idSite, $maxValuesToReturn) {
+ $this->suggestedValuesCallback = function ($idSite, $maxValuesToReturn) {
$positions = range(1,50);
return array_slice($positions, 0, $maxValuesToReturn);
- });
- $this->addSegment($segment);
+ };
}
/**
diff --git a/plugins/Actions/Columns/VisitTotalSearches.php b/plugins/Actions/Columns/VisitTotalSearches.php
index e3ebb83247..559b8090bf 100644
--- a/plugins/Actions/Columns/VisitTotalSearches.php
+++ b/plugins/Actions/Columns/VisitTotalSearches.php
@@ -9,26 +9,18 @@
namespace Piwik\Plugins\Actions\Columns;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\CoreHome\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
-use Piwik\Tracker;
use Piwik\Tracker\Visitor;
class VisitTotalSearches extends VisitDimension
{
protected $columnName = 'visit_total_searches';
protected $columnType = 'SMALLINT(5) UNSIGNED NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setType(Segment::TYPE_METRIC);
- $segment->setSegment('searches');
- $segment->setName('General_NbSearches');
- $segment->setAcceptedValues('To select all visits who used internal Site Search, use: &segment=searches>0');
- $this->addSegment($segment);
- }
+ protected $segmentName = 'searches';
+ protected $nameSingular = 'General_NbSearches';
+ protected $acceptValues = 'To select all visits who used internal Site Search, use: &segment=searches>0';
+ protected $type = self::TYPE_NUMBER;
/**
* @param Request $request
diff --git a/plugins/Actions/lang/en.json b/plugins/Actions/lang/en.json
index ab9fbff5f7..8725fc8e3f 100644
--- a/plugins/Actions/lang/en.json
+++ b/plugins/Actions/lang/en.json
@@ -2,14 +2,18 @@
"Actions": {
"AvgGenerationTimeTooltip": "Average based on %1$s hit(s) %2$s between %3$s and %4$s",
"ColumnClickedURL": "Clicked URL",
+ "ColumnClickedURLs": "Clicked URLs",
"ColumnActionURL": "Action URL",
"ColumnClicks": "Clicks",
"ColumnClicksDocumentation": "The number of times this link was clicked.",
"ColumnDownloadURL": "Download URL",
+ "ColumnDownloadURLs": "Download URLs",
"ColumnEntryPageTitle": "Entry Page title",
"ColumnEntryPageURL": "Entry Page URL",
+ "ColumnEntryPageURLs": "Entry Page URLs",
"ColumnExitPageTitle": "Exit Page Title",
"ColumnExitPageURL": "Exit Page URL",
+ "ColumnExitPageURLs": "Exit Page URLs",
"ColumnNoResultKeyword": "Keyword with No Search Result",
"ColumnPageName": "Page Name",
"ColumnPagesPerSearch": "Search Results pages",
@@ -28,6 +32,7 @@
"ColumnUniqueOutlinks": "Unique Outlinks",
"ColumnIdPageview": "Pageview ID",
"ColumnInteractionPosition": "Interaction Position",
+ "ActionsInVisit": "Actions In Visit",
"DownloadsReportDocumentation": "In this report, you can see which files your visitors have downloaded. %s What Piwik counts as a download is the click on a download link. Whether the download was completed or not isn't known to Piwik.",
"EntryPagesReportDocumentation": "This report contains information about the entry pages that were used during the specified period. An entry page is the first page that a user views during their visit. %s The entry URLs are displayed as a folder structure.",
"EntryPageTitles": "Entry page titles",
@@ -49,7 +54,10 @@
"SiteSearchCategories2": "For example, Ecommerce websites typically have a \"Category\" selector so that visitors can restrict their searches to all products in a specific Category.",
"SiteSearchFollowingPagesDoc": "When visitors search on your website, they are looking for a particular page, content, product, or service. This report lists the pages that were clicked the most after an internal search. In other words, the list of pages the most searched for by visitors already on your website.",
"SiteSearchIntro": "Tracking searches that visitors make on your website is a very effective way to learn more about what your audience is looking for, it can help find ideas for new content, new Ecommerce products that potential customers might be searching for, and generally improve the visitors' experience on your website.",
+ "SiteSearchCategory": "Category (Site Search)",
+ "SiteSearchCategories": "Categories (Site Search)",
"SiteSearchKeyword": "Keyword (Site Search)",
+ "SiteSearchKeywords": "Keywords (Site Search)",
"SiteSearchKeywordsDocumentation": "This report lists the Search Keywords that visitors searched for on your internal Search Engine.",
"SiteSearchKeywordsNoResultDocumentation": "This report lists the Search Keywords that did not return any Search result: maybe the search engine algorithm can be improved, or maybe your visitors are looking for content that is not (yet) on your website?",
"SubmenuPagesEntry": "Entry pages",
@@ -66,6 +74,7 @@
"WidgetSearchCategories": "Search Categories",
"WidgetSearchKeywords": "Site Search Keywords",
"WidgetSearchNoResultKeywords": "Search Keywords with No Results",
- "ActionType": "Action Type"
+ "ActionType": "Action Type",
+ "ActionTypes": "Action Types"
}
} \ No newline at end of file
diff --git a/plugins/Contents/Columns/ContentInteraction.php b/plugins/Contents/Columns/ContentInteraction.php
index a50467f9d6..e188fab521 100644
--- a/plugins/Contents/Columns/ContentInteraction.php
+++ b/plugins/Contents/Columns/ContentInteraction.php
@@ -8,9 +8,9 @@
*/
namespace Piwik\Plugins\Contents\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
use Piwik\Plugins\Contents\Actions\ActionContent;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -19,19 +19,22 @@ class ContentInteraction extends ActionDimension
{
protected $columnName = 'idaction_content_interaction';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
-
- protected function configureSegments()
+ protected $type = self::TYPE_TEXT;
+ protected $acceptValues = 'The type of interaction with the content. For instance "click" or "submit".';
+ protected $segmentName = 'contentInteraction';
+ protected $nameSingular = 'Contents_ContentInteraction';
+ protected $namePlural = 'Contents_ContentInteractions';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
+
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('contentInteraction');
- $segment->setName('Contents_ContentInteraction');
- $segment->setAcceptedValues('The type of interaction with the content. For instance "click" or "submit".');
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('Contents_ContentInteraction');
+ return new Discriminator('log_action', 'type', $this->getActionId());
}
public function getActionId()
diff --git a/plugins/Contents/Columns/ContentName.php b/plugins/Contents/Columns/ContentName.php
index 6168a48725..47255787d6 100644
--- a/plugins/Contents/Columns/ContentName.php
+++ b/plugins/Contents/Columns/ContentName.php
@@ -8,10 +8,10 @@
*/
namespace Piwik\Plugins\Contents\Columns;
-use Piwik\Exception\InvalidRequestParameterException;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
+use Piwik\Exception\InvalidRequestParameterException;
use Piwik\Plugins\Contents\Actions\ActionContent;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -20,19 +20,22 @@ class ContentName extends ActionDimension
{
protected $columnName = 'idaction_content_name';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
-
- protected function configureSegments()
+ protected $segmentName = 'contentName';
+ protected $nameSingular = 'Contents_ContentName';
+ protected $namePlural = 'Contents_ContentNames';
+ protected $acceptValues = 'The name of a content block, for instance "Ad Sale"';
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
+
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('contentName');
- $segment->setName('Contents_ContentName');
- $segment->setAcceptedValues('The name of a content block, for instance "Ad Sale"');
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('Contents_ContentName');
+ return new Discriminator('log_action', 'type', $this->getActionId());
}
public function getActionId()
diff --git a/plugins/Contents/Columns/ContentPiece.php b/plugins/Contents/Columns/ContentPiece.php
index 4cd0722e5a..0bf5464611 100644
--- a/plugins/Contents/Columns/ContentPiece.php
+++ b/plugins/Contents/Columns/ContentPiece.php
@@ -8,9 +8,9 @@
*/
namespace Piwik\Plugins\Contents\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
use Piwik\Plugins\Contents\Actions\ActionContent;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -19,19 +19,22 @@ class ContentPiece extends ActionDimension
{
protected $columnName = 'idaction_content_piece';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
-
- protected function configureSegments()
+ protected $segmentName = 'contentPiece';
+ protected $nameSingular = 'Contents_ContentPiece';
+ protected $namePlural = 'Contents_ContentPieces';
+ protected $acceptValues = 'The actual content. For instance "ad.jpg" or "My text ad"';
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
+
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('contentPiece');
- $segment->setName('Contents_ContentPiece');
- $segment->setAcceptedValues('The actual content. For instance "ad.jpg" or "My text ad"');
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('Contents_ContentPiece');
+ return new Discriminator('log_action', 'type', $this->getActionId());
}
public function getActionId()
diff --git a/plugins/Contents/Columns/ContentTarget.php b/plugins/Contents/Columns/ContentTarget.php
index 9e81c687f3..7448770749 100644
--- a/plugins/Contents/Columns/ContentTarget.php
+++ b/plugins/Contents/Columns/ContentTarget.php
@@ -8,9 +8,9 @@
*/
namespace Piwik\Plugins\Contents\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Actions\Segment;
use Piwik\Plugins\Contents\Actions\ActionContent;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -19,19 +19,22 @@ class ContentTarget extends ActionDimension
{
protected $columnName = 'idaction_content_target';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
-
- protected function configureSegments()
+ protected $type = self::TYPE_URL;
+ protected $nameSingular = 'Contents_ContentTarget';
+ protected $namePlural = 'Contents_ContentTargets';
+ protected $segmentName = 'contentTarget';
+ protected $category = 'General_Actions';
+ protected $sqlFilter = '\\Piwik\\Tracker\\TableLogAction::getIdActionFromSegment';
+ protected $acceptValues = 'For instance the URL of a landing page: "http://landingpage.example.com"';
+
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('contentTarget');
- $segment->setName('Contents_ContentTarget');
- $segment->setAcceptedValues('For instance the URL of a landing page: "http://landingpage.example.com"');
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('Contents_ContentTarget');
+ return new Discriminator('log_action', 'type', $this->getActionId());
}
public function getActionId()
diff --git a/plugins/Contents/Contents.php b/plugins/Contents/Contents.php
index 289bdb25ec..580b752a53 100644
--- a/plugins/Contents/Contents.php
+++ b/plugins/Contents/Contents.php
@@ -14,7 +14,7 @@ use Piwik\Piwik;
class Contents extends \Piwik\Plugin
{
/**
- * @see Piwik\Plugin::registerEvents
+ * @see \Piwik\Plugin::registerEvents
*/
public function registerEvents()
{
@@ -59,4 +59,4 @@ class Contents extends \Piwik\Plugin
$joins[] = 'LEFT JOIN ' . Common::prefixTable('log_action') . ' AS log_action_content_interaction
ON log_link_visit_action.idaction_content_interaction = log_action_content_interaction.idaction';
}
-}
+} \ No newline at end of file
diff --git a/plugins/Contents/lang/en.json b/plugins/Contents/lang/en.json
index 0947590f69..e4bef887a0 100644
--- a/plugins/Contents/lang/en.json
+++ b/plugins/Contents/lang/en.json
@@ -7,8 +7,11 @@
"ContentInteractions": "Content Interactions",
"InteractionRate": "Interaction Rate",
"ContentName": "Content Name",
+ "ContentNames": "Content Names",
"ContentPiece": "Content Piece",
+ "ContentPieces": "Content Pieces",
"ContentTarget": "Content Target",
+ "ContentTargets": "Content Targets",
"Contents": "Contents",
"InteractionsMetricDocumentation": "The number of times a content block was interacted with (eg, a 'click' on a banner or ad).",
"ImpressionsMetricDocumentation": "The number of times a content block, such as a banner or an ad, was displayed on a page.",
diff --git a/plugins/CoreHome/Columns/IdSite.php b/plugins/CoreHome/Columns/IdSite.php
index 996cae629b..f757b5bf1c 100644
--- a/plugins/CoreHome/Columns/IdSite.php
+++ b/plugins/CoreHome/Columns/IdSite.php
@@ -8,10 +8,10 @@
*/
namespace Piwik\Plugins\CoreHome\Columns;
+use Piwik\Columns\Join\SiteNameJoin;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
-use Piwik\Tracker;
use Piwik\Tracker\Visitor;
class IdSite extends VisitDimension
@@ -23,6 +23,13 @@ class IdSite extends VisitDimension
// INDEX(idsite, config_id, visit_last_action_time) and we maybe not be sure whether config_id already exists at
// installing point (we do not know whether visit_last_action_time or idsite column would be added first).
+ protected $type = self::TYPE_TEXT;
+
+ public function getDbColumnJoin()
+ {
+ return new SiteNameJoin();
+ }
+
/**
* @param Request $request
* @param Visitor $visitor
diff --git a/plugins/CoreHome/Columns/LinkVisitActionId.php b/plugins/CoreHome/Columns/LinkVisitActionId.php
new file mode 100644
index 0000000000..6cc55c04bb
--- /dev/null
+++ b/plugins/CoreHome/Columns/LinkVisitActionId.php
@@ -0,0 +1,42 @@
+<?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\CoreHome\Columns;
+
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
+use Piwik\Piwik;
+use Piwik\Plugin\ArchivedMetric;
+use Piwik\Plugin\Dimension\ActionDimension;
+use Piwik\Plugin\Dimension\VisitDimension;
+use Piwik\Plugin\Segment;
+
+
+class LinkVisitActionId extends ActionDimension
+{
+ protected $columnName = 'idlink_va';
+ protected $acceptValues = 'Any integer.';
+ protected $category = 'General_Actions';
+ protected $nameSingular = 'General_Actions';
+ protected $metricId = 'hits';
+ protected $type = self::TYPE_NUMBER;
+
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ $metric = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_UNIQUE);
+ $metric->setTranslatedName(Piwik::translate('General_ColumnHits'));
+ $metric->setName('hits');
+ $metricsList->addMetric($metric);
+
+ $metric = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_UNIQUE);
+ $metric->setTranslatedName(Piwik::translate('General_ColumnPageviews'));
+ $metric->setDocumentation(Piwik::translate('General_ColumnPageviewsDocumentation'));
+ $metric->setName('pageviews');
+ $metricsList->addMetric($metric);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/Columns/ServerMinute.php b/plugins/CoreHome/Columns/ServerMinute.php
new file mode 100644
index 0000000000..ee095dcb3c
--- /dev/null
+++ b/plugins/CoreHome/Columns/ServerMinute.php
@@ -0,0 +1,35 @@
+<?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\CoreHome\Columns;
+
+use Piwik\Metrics\Formatter;
+use Piwik\Plugin\Dimension\ActionDimension;
+
+class ServerMinute extends ActionDimension
+{
+ protected $columnName = 'server_time';
+ protected $segmentName = 'actionServerMinute';
+ protected $sqlSegment = 'MINUTE(log_link_visit_action.server_time)';
+ protected $nameSingular = 'VisitTime_ColumnServerMinute';
+ protected $type = self::TYPE_DATETIME;
+ protected $acceptValues = '0, 1, 2, 3, ..., 56, 57, 58, 59';
+
+ public function __construct()
+ {
+ $this->suggestedValuesCallback = function ($idSite, $maxValuesToReturn) {
+ return range(0, min(59, $maxValuesToReturn));
+ };
+ }
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ return $value;
+ }
+
+}
diff --git a/plugins/CoreHome/Columns/ServerTime.php b/plugins/CoreHome/Columns/ServerTime.php
index 297c410058..4e308786f1 100644
--- a/plugins/CoreHome/Columns/ServerTime.php
+++ b/plugins/CoreHome/Columns/ServerTime.php
@@ -9,17 +9,34 @@
namespace Piwik\Plugins\CoreHome\Columns;
use Piwik\Date;
-use Piwik\Db;
+use Piwik\Metrics\Formatter;
use Piwik\Plugin\Dimension\ActionDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
-use Piwik\Tracker;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/VisitTime/functions.php';
class ServerTime extends ActionDimension
{
protected $columnName = 'server_time';
protected $columnType = 'DATETIME NOT NULL';
+ protected $segmentName = 'actionServerHour';
+ protected $sqlSegment = 'HOUR(log_link_visit_action.server_time)';
+ protected $nameSingular = 'VisitTime_ColumnServerHour';
+ protected $type = self::TYPE_DATETIME;
+
+ public function __construct()
+ {
+ $this->suggestedValuesCallback = function ($idSite, $maxValuesToReturn) {
+ return range(0, min(23, $maxValuesToReturn));
+ };
+ }
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ return \Piwik\Plugins\VisitTime\getTimeLabel($value);
+ }
public function install()
{
diff --git a/plugins/CoreHome/Columns/UserId.php b/plugins/CoreHome/Columns/UserId.php
index 50d1be09bc..c5423ae93a 100644
--- a/plugins/CoreHome/Columns/UserId.php
+++ b/plugins/CoreHome/Columns/UserId.php
@@ -12,9 +12,7 @@ use Piwik\Cache;
use Piwik\DataTable;
use Piwik\DataTable\Map;
use Piwik\Metrics;
-use Piwik\Piwik;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugin\Segment;
use Piwik\Plugins\VisitsSummary\API as VisitsSummaryApi;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -29,25 +27,18 @@ class UserId extends VisitDimension
* @var string
*/
protected $columnName = 'user_id';
+ protected $type = self::TYPE_TEXT;
+ protected $allowAnonymous = false;
+ protected $segmentName = 'userId';
+ protected $nameSingular = 'General_UserId';
+ protected $namePlural = 'General_UserIds';
+ protected $acceptValues = 'any non empty unique string identifying the user (such as an email address or a username).';
/**
* @var string
*/
protected $columnType = 'VARCHAR(200) NULL';
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setType('dimension');
- $segment->setSegment('userId');
- $segment->setCategory(Piwik::translate('General_Visit'));
- $segment->setName('General_UserId');
- $segment->setAcceptedValues('any non empty unique string identifying the user (such as an email address or a username).');
- $segment->setSqlSegment('log_visit.user_id');
- $segment->setRequiresAtLeastViewAccess(true);
- $this->addSegment($segment);
- }
-
/**
* @param Request $request
* @param Visitor $visitor
diff --git a/plugins/CoreHome/Columns/VisitFirstActionMinute.php b/plugins/CoreHome/Columns/VisitFirstActionMinute.php
new file mode 100644
index 0000000000..c3e16a9215
--- /dev/null
+++ b/plugins/CoreHome/Columns/VisitFirstActionMinute.php
@@ -0,0 +1,45 @@
+<?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\CoreHome\Columns;
+
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
+use Piwik\Plugin\Dimension\VisitDimension;
+use Piwik\Metrics\Formatter;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/VisitTime/functions.php';
+
+class VisitFirstActionMinute extends VisitDimension
+{
+ protected $columnName = 'visit_first_action_time';
+ protected $type = self::TYPE_DATETIME;
+
+ protected $sqlSegment = 'HOUR(log_visit.visit_first_action_time)';
+ protected $segmentName = 'visitStartServerMinute';
+ protected $acceptValues = '0, 1, 2, 3, ..., 56, 57, 58, 59';
+ protected $nameSingular = 'VisitTime_ColumnVisitStartServerMinute';
+
+ public function __construct()
+ {
+ $this->suggestedValuesCallback = function ($idSite, $maxValuesToReturn) {
+ return range(0, min(59, $maxValuesToReturn));
+ };
+ }
+
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ // no metrics to be generated
+ }
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ return $value;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/CoreHome/Columns/VisitFirstActionTime.php b/plugins/CoreHome/Columns/VisitFirstActionTime.php
index 3985d53339..f9318d6771 100644
--- a/plugins/CoreHome/Columns/VisitFirstActionTime.php
+++ b/plugins/CoreHome/Columns/VisitFirstActionTime.php
@@ -12,13 +12,33 @@ use Piwik\Date;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
-use Piwik\Tracker;
use Piwik\Tracker\Visitor;
+use Piwik\Metrics\Formatter;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/VisitTime/functions.php';
class VisitFirstActionTime extends VisitDimension
{
protected $columnName = 'visit_first_action_time';
protected $columnType = 'DATETIME NOT NULL';
+ protected $type = self::TYPE_DATETIME;
+
+ protected $sqlSegment = 'HOUR(log_visit.visit_first_action_time)';
+ protected $segmentName = 'visitStartServerHour';
+ protected $acceptValues = '0, 1, 2, 3, ..., 20, 21, 22, 23';
+ protected $nameSingular = 'VisitTime_ColumnVisitStartServerHour';
+
+ public function __construct()
+ {
+ $this->suggestedValuesCallback = function ($idSite, $maxValuesToReturn) {
+ return range(0, min(23, $maxValuesToReturn));
+ };
+ }
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ return $value;
+ }
/**
* @param Request $request
diff --git a/plugins/CoreHome/Columns/VisitGoalBuyer.php b/plugins/CoreHome/Columns/VisitGoalBuyer.php
index 779d5fd5be..5c6f908173 100644
--- a/plugins/CoreHome/Columns/VisitGoalBuyer.php
+++ b/plugins/CoreHome/Columns/VisitGoalBuyer.php
@@ -8,6 +8,7 @@
*/
namespace Piwik\Plugins\CoreHome\Columns;
+use Piwik\Metrics\Formatter;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Plugins\CoreHome\Segment;
@@ -33,19 +34,39 @@ class VisitGoalBuyer extends VisitDimension
protected $columnName = 'visit_goal_buyer';
protected $columnType = 'TINYINT(1) NULL';
+ protected $segmentName = 'visitEcommerceStatus';
+ protected $nameSingular = 'General_EcommerceVisitStatusDesc';
+ protected $type = self::TYPE_ENUM;
- protected function configureSegments()
+ public function __construct()
{
$example = Piwik::translate('General_EcommerceVisitStatusEg', '"&segment=visitEcommerceStatus==ordered,visitEcommerceStatus==orderedThenAbandonedCart"');
- $acceptedValues = implode(", ", self::$visitEcommerceStatus) . '. ' . $example;
+ $this->acceptValues = implode(", ", self::$visitEcommerceStatus) . '. ' . $example;
+ }
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ switch ($value) {
+ case 'ordered':
+ case self::TYPE_BUYER_ORDERED:
+ return Piwik::translate('CoreHome_VisitStatusOrdered');
+ case 'abandonedCart':
+ case self::TYPE_BUYER_OPEN_CART:
+ return Piwik::translate('Goals_AbandonedCart');
+ case 'orderedThenAbandonedCart':
+ case self::TYPE_BUYER_ORDERED_AND_OPEN_CART:
+ return Piwik::translate('CoreHome_VisitStatusOrderedThenAbandoned');
+ case 'none';
+ case self::TYPE_BUYER_NONE:
+ return Piwik::translate('UserCountryMap_None');
+ }
- $segment = new Segment();
- $segment->setSegment('visitEcommerceStatus');
- $segment->setName('General_EcommerceVisitStatusDesc');
- $segment->setAcceptedValues($acceptedValues);
- $segment->setSqlFilterValue(__NAMESPACE__ . '\VisitGoalBuyer::getVisitEcommerceStatus');
+ return $value;
+ }
- $this->addSegment($segment);
+ public function getEnumColumnValues()
+ {
+ return self::$visitEcommerceStatus;
}
/**
@@ -83,17 +104,6 @@ class VisitGoalBuyer extends VisitDimension
return false;
}
- public static function getVisitEcommerceStatus($status)
- {
- $id = array_search($status, self::$visitEcommerceStatus);
-
- if ($id === false) {
- throw new \Exception("Invalid 'visitEcommerceStatus' segment value $status");
- }
-
- return $id;
- }
-
/**
* @ignore
*/
diff --git a/plugins/CoreHome/Columns/VisitGoalConverted.php b/plugins/CoreHome/Columns/VisitGoalConverted.php
index 1c0cc40e65..26d87b7835 100644
--- a/plugins/CoreHome/Columns/VisitGoalConverted.php
+++ b/plugins/CoreHome/Columns/VisitGoalConverted.php
@@ -8,8 +8,11 @@
*/
namespace Piwik\Plugins\CoreHome\Columns;
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
+use Piwik\Piwik;
+use Piwik\Plugin\ComputedMetric;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\CoreHome\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -18,14 +21,21 @@ class VisitGoalConverted extends VisitDimension
{
protected $columnName = 'visit_goal_converted';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
+ protected $segmentName = 'visitConverted';
+ protected $nameSingular = 'General_VisitConvertedGoal';
+ protected $acceptValues = '0, 1';
- protected function configureSegments()
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
{
- $segment = new Segment();
- $segment->setSegment('visitConverted');
- $segment->setName('General_VisitConvertedGoal');
- $segment->setAcceptedValues('0, 1');
- $this->addSegment($segment);
+ $metric1 = $dimensionMetricFactory->createCustomMetric('nb_visits_converted', Piwik::translate('General_ColumnVisitsWithConversions'), 'sum(case %s when 1 then 1 else 0 end)');
+ $metricsList->addMetric($metric1);
+
+ $metric = $dimensionMetricFactory->createComputedMetric($metric1->getName(), 'nb_visits', ComputedMetric::AGGREGATION_RATE);
+ $metric->setTranslatedName(Piwik::translate('General_ColumnConversionRate'));
+ $metric->setDocumentation(Piwik::translate('General_ColumnConversionRateDocumentation'));
+ $metric->setName('visits_conversion_rate');
+ $metricsList->addMetric($metric);
}
/**
diff --git a/plugins/CoreHome/Columns/VisitId.php b/plugins/CoreHome/Columns/VisitId.php
index 9add50888a..b87f1b58d4 100644
--- a/plugins/CoreHome/Columns/VisitId.php
+++ b/plugins/CoreHome/Columns/VisitId.php
@@ -8,7 +8,10 @@
namespace Piwik\Plugins\CoreHome\Columns;
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
use Piwik\Piwik;
+use Piwik\Plugin\ArchivedMetric;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Plugin\Segment;
@@ -18,18 +21,28 @@ use Piwik\Plugin\Segment;
*/
class VisitId extends VisitDimension
{
+ protected $columnName = 'idvisit';
+ protected $acceptValues = 'Any integer.';
+ protected $nameSingular = 'General_Visit';
+ protected $namePlural = 'General_ColumnNbVisits';
+ protected $segmentName = 'visitId';
+ protected $allowAnonymous = false;
+ protected $metricId = 'visits';
+ protected $type = self::TYPE_TEXT;
+
protected function configureSegments()
{
- parent::configureSegments();
-
$segment = new Segment();
- $segment->setType('dimension');
- $segment->setCategory(Piwik::translate('General_Visit'));
- $segment->setName(Piwik::translate('General_Visit') . " ID");
- $segment->setSegment('visitId');
- $segment->setAcceptedValues('Any integer.');
- $segment->setSqlSegment('log_visit.idvisit');
- $segment->setRequiresAtLeastViewAccess(true);
+ $segment->setName('General_VisitId');
$this->addSegment($segment);
}
+
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ $metric = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_UNIQUE);
+ $metric->setTranslatedName(Piwik::translate('General_ColumnNbVisits'));
+ $metric->setDocumentation(Piwik::translate('General_ColumnNbVisitsDocumentation'));
+ $metric->setName('nb_visits');
+ $metricsList->addMetric($metric);
+ }
} \ No newline at end of file
diff --git a/plugins/CoreHome/Columns/VisitIp.php b/plugins/CoreHome/Columns/VisitIp.php
index 6dd2e5d6b9..ed8b196fd2 100644
--- a/plugins/CoreHome/Columns/VisitIp.php
+++ b/plugins/CoreHome/Columns/VisitIp.php
@@ -8,7 +8,9 @@
namespace Piwik\Plugins\CoreHome\Columns;
-use Piwik\Piwik;
+use Piwik\Common;
+use Piwik\Metrics\Formatter;
+use Piwik\Network\IPUtils;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Plugin\Segment;
@@ -18,19 +20,26 @@ use Piwik\Plugin\Segment;
*/
class VisitIp extends VisitDimension
{
- protected function configureSegments()
+ protected $columnName = 'location_ip';
+ protected $type = self::TYPE_BINARY;
+ protected $allowAnonymous = false;
+ protected $segmentName = 'visitIp';
+ protected $nameSingular = 'General_VisitorIP';
+ protected $namePlural = 'General_VisitorIPs';
+ protected $acceptValues = '13.54.122.1. </code>Select IP ranges with notation: <code>visitIp>13.54.122.0;visitIp<13.54.122.255';
+ protected $sqlFilterValue = array('Piwik\Network\IPUtils', 'stringToBinaryIP');
+
+ public function formatValue($value, $idSite, Formatter $formatter)
{
- parent::configureSegments();
+ $value = Common::hex2bin($value);
+ $value = IPUtils::binaryToStringIP($value);
+ return $value;
+ }
+ protected function configureSegments()
+ {
$segment = new Segment();
- $segment->setType('metric');
- $segment->setCategory(Piwik::translate('General_Visit'));
- $segment->setName('General_VisitorIP');
- $segment->setSegment('visitIp');
- $segment->setAcceptedValues('13.54.122.1. </code>Select IP ranges with notation: <code>visitIp>13.54.122.0;visitIp<13.54.122.255');
- $segment->setSqlSegment('log_visit.location_ip');
- $segment->setSqlFilterValue(array('Piwik\Network\IPUtils', 'stringToBinaryIP'));
- $segment->setRequiresAtLeastViewAccess(true);
+ $segment->setType(Segment::TYPE_METRIC); // we cannot remove this for now as it would assign dimension based on text type
$this->addSegment($segment);
}
}
diff --git a/plugins/CoreHome/Columns/VisitLastActionMinute.php b/plugins/CoreHome/Columns/VisitLastActionMinute.php
new file mode 100644
index 0000000000..06611fb2fc
--- /dev/null
+++ b/plugins/CoreHome/Columns/VisitLastActionMinute.php
@@ -0,0 +1,51 @@
+<?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\CoreHome\Columns;
+
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
+use Piwik\Plugin\Dimension\VisitDimension;
+use Piwik\Metrics\Formatter;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/VisitTime/functions.php';
+
+/**
+ * This dimension holds the best guess for a visit's end time. It is set the last action
+ * time for each visit. `ping=1` requests can be sent to update the dimension value so
+ * it can be a more accurate guess of the time the visitor spent on the site.
+ *
+ * Note: though it is named 'visit last action time' it actually refers to the visit's last action's
+ * end time.
+ */
+class VisitLastActionMinute extends VisitDimension
+{
+ protected $columnName = 'visit_last_action_time';
+ protected $type = self::TYPE_DATETIME;
+ protected $segmentName = 'visitEndServerMinute';
+ protected $nameSingular = 'VisitTime_ColumnVisitEndServerMinute';
+ protected $sqlSegment = 'MINUTE(log_visit.visit_last_action_time)';
+ protected $acceptValues = '0, 1, 2, 3, ..., 56, 57, 58, 59';
+
+ public function __construct()
+ {
+ $this->suggestedValuesCallback = function ($idSite, $maxValuesToReturn) {
+ return range(0, min(59, $maxValuesToReturn));
+ };
+ }
+
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ // no metrics for this dimension
+ }
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ return $value;
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/Columns/VisitLastActionTime.php b/plugins/CoreHome/Columns/VisitLastActionTime.php
index 4ba0761c2a..3b297fb68b 100644
--- a/plugins/CoreHome/Columns/VisitLastActionTime.php
+++ b/plugins/CoreHome/Columns/VisitLastActionTime.php
@@ -12,8 +12,10 @@ use Piwik\Date;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
-use Piwik\Tracker;
use Piwik\Tracker\Visitor;
+use Piwik\Metrics\Formatter;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/VisitTime/functions.php';
/**
* This dimension holds the best guess for a visit's end time. It is set the last action
@@ -26,6 +28,17 @@ use Piwik\Tracker\Visitor;
class VisitLastActionTime extends VisitDimension
{
protected $columnName = 'visit_last_action_time';
+ protected $type = self::TYPE_DATETIME;
+ protected $nameSingular = 'VisitTime_ColumnVisitEndServerHour';
+ protected $sqlSegment = 'HOUR(log_visit.visit_last_action_time)';
+ protected $segmentName = 'visitServerHour';
+ protected $acceptValues = '0, 1, 2, 3, ..., 20, 21, 22, 23';
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ return \Piwik\Plugins\VisitTime\getTimeLabel($value);
+ }
+
// we do not install or define column definition here as we need to create this column when installing as there is
// an index on it. Currently we do not define the index here... although we could overwrite the install() method
// and add column 'visit_last_action_time' and add index. Problem is there is also an index
diff --git a/plugins/CoreHome/Columns/VisitTotalTime.php b/plugins/CoreHome/Columns/VisitTotalTime.php
index 87025a90f9..44bdc39958 100644
--- a/plugins/CoreHome/Columns/VisitTotalTime.php
+++ b/plugins/CoreHome/Columns/VisitTotalTime.php
@@ -19,15 +19,9 @@ class VisitTotalTime extends VisitDimension
{
protected $columnName = 'visit_total_time';
protected $columnType = 'INT(11) UNSIGNED NOT NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('visitDuration');
- $segment->setName('General_ColumnVisitDuration');
- $segment->setType(Segment::TYPE_METRIC);
- $this->addSegment($segment);
- }
+ protected $segmentName = 'visitDuration';
+ protected $nameSingular = 'General_ColumnVisitDuration';
+ protected $type = self::TYPE_DURATION_S;
/**
* @param Request $request
diff --git a/plugins/CoreHome/Columns/VisitorDaysSinceFirst.php b/plugins/CoreHome/Columns/VisitorDaysSinceFirst.php
index 3445f21f59..e0ce8fa5be 100644
--- a/plugins/CoreHome/Columns/VisitorDaysSinceFirst.php
+++ b/plugins/CoreHome/Columns/VisitorDaysSinceFirst.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\CoreHome\Columns;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\CoreHome\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -18,15 +17,9 @@ class VisitorDaysSinceFirst extends VisitDimension
{
protected $columnName = 'visitor_days_since_first';
protected $columnType = 'SMALLINT(5) UNSIGNED NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setType(Segment::TYPE_METRIC);
- $segment->setSegment('daysSinceFirstVisit');
- $segment->setName('General_DaysSinceFirstVisit');
- $this->addSegment($segment);
- }
+ protected $segmentName = 'daysSinceFirstVisit';
+ protected $nameSingular = 'General_DaysSinceFirstVisit';
+ protected $type = self::TYPE_NUMBER;
/**
* @param Request $request
diff --git a/plugins/CoreHome/Columns/VisitorDaysSinceOrder.php b/plugins/CoreHome/Columns/VisitorDaysSinceOrder.php
index c126b5957c..ad6334e838 100644
--- a/plugins/CoreHome/Columns/VisitorDaysSinceOrder.php
+++ b/plugins/CoreHome/Columns/VisitorDaysSinceOrder.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\CoreHome\Columns;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\CoreHome\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -18,16 +17,10 @@ class VisitorDaysSinceOrder extends VisitDimension
{
protected $columnName = 'visitor_days_since_order';
protected $columnType = 'SMALLINT(5) UNSIGNED NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('daysSinceLastEcommerceOrder');
- $segment->setName('General_DaysSinceLastEcommerceOrder');
- $segment->setType(Segment::TYPE_METRIC);
-
- $this->addSegment($segment);
- }
+ protected $segmentName = 'daysSinceLastEcommerceOrder';
+ protected $nameSingular = 'General_DaysSinceLastEcommerceOrder';
+ protected $category = 'General_Visitors'; // todo put into ecommerce category?
+ protected $type = self::TYPE_NUMBER;
/**
* @param Request $request
diff --git a/plugins/CoreHome/Columns/VisitorId.php b/plugins/CoreHome/Columns/VisitorId.php
index ce797ae57a..728e1e3d94 100644
--- a/plugins/CoreHome/Columns/VisitorId.php
+++ b/plugins/CoreHome/Columns/VisitorId.php
@@ -8,9 +8,12 @@
namespace Piwik\Plugins\CoreHome\Columns;
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
+use Piwik\Metrics\Formatter;
use Piwik\Piwik;
+use Piwik\Plugin\ArchivedMetric;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugin\Segment;
/**
* Dimension for the log_visit.idvisitor column. This column is added in the CREATE TABLE
@@ -18,19 +21,21 @@ use Piwik\Plugin\Segment;
*/
class VisitorId extends VisitDimension
{
- protected function configureSegments()
- {
- parent::configureSegments();
+ protected $columnName = 'idvisitor';
+ protected $metricId = 'visitors';
+ protected $nameSingular = 'General_VisitorID';
+ protected $namePlural = 'General_Visitors';
+ protected $segmentName = 'visitorId';
+ protected $acceptValues = '34c31e04394bdc63 - any 16 Hexadecimal chars ID, which can be fetched using the Tracking API function getVisitorId()';
+ protected $allowAnonymous = false;
+ protected $sqlFilterValue = array('Piwik\Common', 'convertVisitorIdToBin');
+ protected $type = self::TYPE_BINARY;
- $segment = new Segment();
- $segment->setType('dimension');
- $segment->setCategory(Piwik::translate('General_Visit'));
- $segment->setName('General_VisitorID');
- $segment->setSegment('visitorId');
- $segment->setAcceptedValues('34c31e04394bdc63 - any 16 Hexadecimal chars ID, which can be fetched using the Tracking API function getVisitorId()');
- $segment->setSqlSegment('log_visit.idvisitor');
- $segment->setSqlFilterValue(array('Piwik\Common', 'convertVisitorIdToBin'));
- $segment->setRequiresAtLeastViewAccess(true);
- $this->addSegment($segment);
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ $metric = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_UNIQUE);
+ $metric->setTranslatedName(Piwik::translate('General_ColumnNbUniqVisitors'));
+ $metric->setName('nb_uniq_visitors');
+ $metricsList->addMetric($metric);
}
}
diff --git a/plugins/CoreHome/Columns/VisitorReturning.php b/plugins/CoreHome/Columns/VisitorReturning.php
index ca1ef11652..862fb12c6e 100644
--- a/plugins/CoreHome/Columns/VisitorReturning.php
+++ b/plugins/CoreHome/Columns/VisitorReturning.php
@@ -8,9 +8,9 @@
*/
namespace Piwik\Plugins\CoreHome\Columns;
+use Piwik\Metrics\Formatter;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\CoreHome\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -23,22 +23,44 @@ class VisitorReturning extends VisitDimension
protected $columnName = 'visitor_returning';
protected $columnType = 'TINYINT(1) NULL';
+ protected $segmentName = 'visitorType';
+ protected $nameSingular = 'General_VisitType';
+ protected $namePlural = 'General_VisitTypes';
protected $conversionField = true;
+ protected $type = self::TYPE_ENUM;
- protected function configureSegments()
+ public function __construct()
{
- $acceptedValues = 'new, returning, returningCustomer. ';
- $acceptedValues .= Piwik::translate('General_VisitTypeExample', '"&segment=visitorType==returning,visitorType==returningCustomer"');
-
- $segment = new Segment();
- $segment->setSegment('visitorType');
- $segment->setName('General_VisitType');
- $segment->setAcceptedValues($acceptedValues);
- $segment->setSqlFilterValue(function ($type) {
+ $this->acceptValues = 'new, returning, returningCustomer. ';
+ $this->acceptValues .= Piwik::translate('General_VisitTypeExample', '"&segment=visitorType==returning,visitorType==returningCustomer"');
+ $this->sqlFilterValue = function ($type) {
+ if (is_numeric($type)) {
+ return $type;
+ }
return $type == "new" ? 0 : ($type == "returning" ? 1 : 2);
- });
+ };
+ }
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ if ($value === 1 || $value === '1' || $value === 'returning') {
+ return Piwik::translate('CoreHome_VisitTypeReturning');
+ } elseif ($value === 2 || $value === '2' || $value === 'returningCustomer'){
+ return Piwik::translate('CoreHome_VisitTypeReturningCustomer');
+ } elseif ($value === 0 || $value === '0' || $value === 'new'){
+ return Piwik::translate('General_New');
+ }
- $this->addSegment($segment);
+ return $value;
+ }
+
+ public function getEnumColumnValues()
+ {
+ return array(
+ self::IS_RETURNING_CUSTOMER => 'returningCustomer',
+ self::IS_RETURNING => 'returning',
+ self::IS_NEW => 'new',
+ );
}
/**
@@ -49,7 +71,6 @@ class VisitorReturning extends VisitDimension
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
-
$daysSinceLastOrder = $request->getDaysSinceLastOrder();
$isReturningCustomer = ($daysSinceLastOrder !== false);
diff --git a/plugins/CoreHome/Columns/VisitsCount.php b/plugins/CoreHome/Columns/VisitsCount.php
index 584b242ae4..c334f175bb 100644
--- a/plugins/CoreHome/Columns/VisitsCount.php
+++ b/plugins/CoreHome/Columns/VisitsCount.php
@@ -8,8 +8,9 @@
*/
namespace Piwik\Plugins\CoreHome\Columns;
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\CoreHome\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -18,14 +19,13 @@ class VisitsCount extends VisitDimension
{
protected $columnName = 'visitor_count_visits';
protected $columnType = 'INT(11) UNSIGNED NOT NULL';
+ protected $segmentName = 'visitCount';
+ protected $nameSingular = 'General_NumberOfVisits';
+ protected $type = self::TYPE_NUMBER;
- protected function configureSegments()
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
{
- $segment = new Segment();
- $segment->setType(Segment::TYPE_METRIC);
- $segment->setSegment('visitCount');
- $segment->setName('General_NumberOfVisits');
- $this->addSegment($segment);
+ // no metrics for this dimension, it would be rather confusing I think
}
/**
diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php
index be56c144f8..ff800ebe1e 100644
--- a/plugins/CoreHome/CoreHome.php
+++ b/plugins/CoreHome/CoreHome.php
@@ -7,6 +7,10 @@
*
*/
namespace Piwik\Plugins\CoreHome;
+use Piwik\Columns\ComputedMetricFactory;
+use Piwik\Columns\MetricsList;
+use Piwik\Plugin\ArchivedMetric;
+use Piwik\Plugin\ComputedMetric;
/**
*
@@ -21,7 +25,7 @@ class CoreHome extends \Piwik\Plugin
const WIDGET_CONTAINER_LAYOUT_BY_DIMENSION = 'ByDimension';
/**
- * @see Piwik\Plugin::registerEvents
+ * @see \Piwik\Plugin::registerEvents
*/
public function registerEvents()
{
@@ -30,9 +34,27 @@ class CoreHome extends \Piwik\Plugin
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'AssetManager.filterMergedJavaScripts' => 'filterMergedJavaScripts',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
+ 'Metric.addComputedMetrics' => 'addComputedMetrics'
);
}
+ public function addComputedMetrics(MetricsList $list, ComputedMetricFactory $computedMetricFactory)
+ {
+ $metrics = $list->getMetrics();
+ foreach ($metrics as $metric) {
+ if ($metric instanceof ArchivedMetric && $metric->getDimension()) {
+ $metricName = $metric->getName();
+ if ($metric->getDbTableName() === 'log_visit'
+ && $metricName !== 'nb_uniq_visitors'
+ && $metricName !== 'nb_visits'
+ && strpos($metricName, ArchivedMetric::AGGREGATION_SUM_PREFIX) === 0) {
+ $metric = $computedMetricFactory->createComputedMetric($metric->getName(), 'nb_visits', ComputedMetric::AGGREGATION_AVG);
+ $list->addMetric($metric);
+ }
+ }
+ }
+ }
+
public function filterMergedJavaScripts(&$mergedContent)
{
$mergedContent = preg_replace('/(sourceMappingURL=(.*?).map)/', '', $mergedContent);
diff --git a/plugins/CoreHome/Tracker/LogTable/Conversion.php b/plugins/CoreHome/Tracker/LogTable/Conversion.php
index b579b32d81..2a75d52c41 100644
--- a/plugins/CoreHome/Tracker/LogTable/Conversion.php
+++ b/plugins/CoreHome/Tracker/LogTable/Conversion.php
@@ -26,4 +26,9 @@ class Conversion extends LogTable
{
return 'idvisit';
}
+
+ public function getPrimaryKey()
+ {
+ return array('idvisit', 'idgoal', 'buster');
+ }
} \ No newline at end of file
diff --git a/plugins/CoreHome/Tracker/LogTable/ConversionItem.php b/plugins/CoreHome/Tracker/LogTable/ConversionItem.php
index cf24614458..8423ff8010 100644
--- a/plugins/CoreHome/Tracker/LogTable/ConversionItem.php
+++ b/plugins/CoreHome/Tracker/LogTable/ConversionItem.php
@@ -26,5 +26,10 @@ class ConversionItem extends LogTable
{
return 'idvisit';
}
-
+
+ public function getPrimaryKey()
+ {
+ return array('idvisit', 'idorder', 'idaction_sku');
+ }
+
}
diff --git a/plugins/CoreHome/Tracker/LogTable/LinkVisitAction.php b/plugins/CoreHome/Tracker/LogTable/LinkVisitAction.php
index 8dabf66a66..c2090a1c8c 100644
--- a/plugins/CoreHome/Tracker/LogTable/LinkVisitAction.php
+++ b/plugins/CoreHome/Tracker/LogTable/LinkVisitAction.php
@@ -31,4 +31,9 @@ class LinkVisitAction extends LogTable
{
return 'idvisit';
}
+
+ public function getPrimaryKey()
+ {
+ return array('idlink_va');
+ }
}
diff --git a/plugins/CoreHome/Tracker/LogTable/Visit.php b/plugins/CoreHome/Tracker/LogTable/Visit.php
index a72fb24d11..62877f1cd1 100644
--- a/plugins/CoreHome/Tracker/LogTable/Visit.php
+++ b/plugins/CoreHome/Tracker/LogTable/Visit.php
@@ -32,4 +32,8 @@ class Visit extends LogTable
return true;
}
+ public function getPrimaryKey()
+ {
+ return array('idvisit');
+ }
} \ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/services/piwik-api.js b/plugins/CoreHome/angularjs/common/services/piwik-api.js
index 67f9756f4f..65127ece8a 100644
--- a/plugins/CoreHome/angularjs/common/services/piwik-api.js
+++ b/plugins/CoreHome/angularjs/common/services/piwik-api.js
@@ -214,7 +214,7 @@ var hasBlockedContent = false;
}
for (var key in defaultParams) {
- if (!getParamsToMixin[key] && !postParams[key] && defaultParams[key]) {
+ if (!(key in getParamsToMixin) && !(key in postParams) && defaultParams[key]) {
getParamsToMixin[key] = defaultParams[key];
}
}
diff --git a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js
index 1c94136827..d284034cd6 100644
--- a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js
+++ b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js
@@ -133,6 +133,12 @@
}
}
});
+ if ('object' === typeof widgetsHelper && widgetsHelper.availableWidgets) {
+ // lets also update widgetslist so will be easier to update list of available widgets in dashboard selector
+ // immediately
+ delete widgetsHelper.availableWidgets;
+ widgetsHelper.getAvailableWidgets();
+ }
});
$rootScope.$on('$locationChangeSuccess', function () {
diff --git a/plugins/CoreHome/lang/en.json b/plugins/CoreHome/lang/en.json
index a013ab30ae..1677e05d28 100644
--- a/plugins/CoreHome/lang/en.json
+++ b/plugins/CoreHome/lang/en.json
@@ -29,6 +29,10 @@
"InjectedHostSuperUserWarning": "Piwik may be misconfigured (for example, if Piwik was recently moved to a new server or URL). You can either %1$sclick here and add %2$s as the valid Piwik hostname (if you trust it)%3$s, or %4$sclick here and go to %5$s to access Piwik safely%6$s.",
"InjectedHostWarningIntro": "You are now accessing Piwik from %1$s, but Piwik has been configured to run at this address: %2$s.",
"JavascriptDisabled": "JavaScript must be enabled in order for you to use Piwik in standard view.<br \/>However, it seems JavaScript is either disabled or not supported by your browser.<br \/>To use standard view, enable JavaScript by changing your browser options, then %1$stry again%2$s.<br \/>",
+ "VisitStatusOrdered": "Ordered",
+ "VisitStatusOrderedThenAbandoned": "Ordered then Abandoned Cart",
+ "VisitTypeReturning": "Returning",
+ "VisitTypeReturningCustomer": "Returning Customer",
"MainNavigation": "Main navigation",
"MakeOneTimeDonation": "Make a one time donation, instead.",
"Menu": "Menu",
diff --git a/plugins/CoreHome/templates/_dataTableActions.twig b/plugins/CoreHome/templates/_dataTableActions.twig
index dca99c47c7..537fdffd97 100644
--- a/plugins/CoreHome/templates/_dataTableActions.twig
+++ b/plugins/CoreHome/templates/_dataTableActions.twig
@@ -46,9 +46,11 @@
{{ visualizationIcons|raw }}
{% endif %}
+ {% if properties.show_export %}
<a class='dropdown-button dataTableAction activateExportSelection'
href='javascript:;' title="{{ 'General_ExportThisReport'|translate|e('html_attr') }}"
data-activates='dropdownExport{{ randomIdForDropdown }}'><span class="icon-export"></span></a>
+ {% endif %}
{% if isPluginLoaded('Annotations') and not properties.hide_annotations_view %}
<a class='dataTableAction annotationView'
@@ -68,6 +70,7 @@
</a>
{% endif %}
+ {% if properties.show_export %}
<ul id='dropdownExport{{ randomIdForDropdown }}' class='dropdown-content exportToFormatItems'>
{% set requestParams = properties.request_parameters_to_modify|json_encode %}
<li><a target="_blank" requestParams="{{ requestParams|e('html_attr') }}" methodToCall="{{ properties.apiMethodToRequestDataTable }}" format="CSV" filter_limit="{{ properties.filter_limit }}">CSV</a></li>
@@ -89,6 +92,8 @@
</li>
{% endif %}
</ul>
+ {% endif %}
+
<ul id='dropdownConfigure{{ randomIdForDropdown }}' class='dropdown-content tableConfiguration'>
{% if properties.show_flatten_table %}
{% if clientSideParameters.flat is defined and clientSideParameters.flat == 1 %}
diff --git a/plugins/CorePluginsAdmin/CorePluginsAdmin.php b/plugins/CorePluginsAdmin/CorePluginsAdmin.php
index 8008fe529c..c12ad281bd 100644
--- a/plugins/CorePluginsAdmin/CorePluginsAdmin.php
+++ b/plugins/CorePluginsAdmin/CorePluginsAdmin.php
@@ -38,6 +38,7 @@ class CorePluginsAdmin extends Plugin
{
$stylesheets[] = "plugins/CorePluginsAdmin/stylesheets/plugins_admin.less";
$stylesheets[] = "plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.directive.less";
+ $stylesheets[] = "plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.less";
}
public static function isPluginsAdminEnabled()
diff --git a/plugins/CorePluginsAdmin/angularjs/field/field.directive.js b/plugins/CorePluginsAdmin/angularjs/field/field.directive.js
index 1268fb881f..fb07808201 100644
--- a/plugins/CorePluginsAdmin/angularjs/field/field.directive.js
+++ b/plugins/CorePluginsAdmin/angularjs/field/field.directive.js
@@ -134,6 +134,12 @@
}
});
+ $scope.$watch('title', function (val, oldVal) {
+ if (val !== oldVal) {
+ $scope.field.title = val;
+ }
+ });
+
if ('undefined' !== typeof $scope.placeholder && $scope.placeholder !== null) {
$scope.$watch('placeholder', function (val, oldVal) {
if (val !== oldVal) {
diff --git a/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.html b/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.html
new file mode 100644
index 0000000000..2854e8b134
--- /dev/null
+++ b/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.html
@@ -0,0 +1,24 @@
+<div class="expandableSelector" piwik-focus-anywhere-but-here="formField.showSelect = false">
+ <div ng-click="formField.showSelect = !formField.showSelect" class="select-wrapper"
+ ><span class="caret">â–¼</span><input type="text" class="select-dropdown"
+ readonly="true" value="{{ formField.title }}">
+ </div>
+
+ <div ng-show="formField.showSelect" class="expandableList z-depth-2">
+
+ <div class="searchContainer">
+ <input type="text" placeholder="Search"
+ ng-model="formField.searchTerm" class="expandableSearch browser-default"
+ piwik-focus-if="formField.showSelect">
+ </div>
+ <ul class="collection firstLevel">
+ <li ng-repeat="options in formField.availableOptions" class="collection-item" ng-show="options.values|filter:formField.searchTerm|length">
+ <h4 class="expandableListCategory" ng-click="formField.showCategory == options.group ? formField.showCategory = '' : formField.showCategory = options.group">{{ options.group }} <span class="secondary-content" ng-class='{"icon-arrow-right": formField.showCategory != options.group, "icon-arrow-bottom": formField.showCategory == options.group}'></span></h4>
+
+ <ul ng-show="formField.showCategory == options.group || formField.searchTerm" class="collection secondLevel">
+ <li class="expandableListItem collection-item valign-wrapper" ng-repeat="children in options.values|filter:formField.searchTerm" ng-click="formField.value = children.key;formField.showSelect = false;"><span class="primary-content">{{ children.value }}</span> <span ng-show="children.tooltip" title="{{ children.tooltip }}" class="secondary-content icon-help"></span></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+</div> \ No newline at end of file
diff --git a/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.less b/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.less
new file mode 100644
index 0000000000..75a8c2428c
--- /dev/null
+++ b/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.less
@@ -0,0 +1,88 @@
+.expandableSelector {
+
+ position: relative;
+
+ .secondary-content {
+ font-size: 16px;
+ margin-top: -3px;
+ color: @theme-color-link;
+ cursor: help;
+ }
+
+ ul {
+ min-width: 250px;
+
+ &.collection.firstLevel {
+ border-top: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+ font-size: 12px;
+
+ > li {
+ padding: 0 !important;
+ }
+ }
+
+ .expandableListCategory {
+ padding: 10px 20px;
+ color: @theme-color-link;
+ }
+
+ li {
+ &:hover {
+ background: #f2f2f2 !important;
+ }
+
+ &.collection-item {
+ cursor: pointer;
+ }
+ }
+
+ ul {
+ margin-top: 0;
+ margin-bottom: 0;
+
+ .primary-content {
+ width: 100%;
+ }
+ .secondary-content {
+ margin-top: 3px;
+ }
+
+ li {
+ padding-top: 6px !important;
+ padding-bottom: 6px !important;
+ padding-left: 30px !important;
+ min-width: 200px;
+
+ &:hover {
+ background: #f2f2f2 !important;
+ }
+ }
+ }
+ }
+
+ .searchContainer {
+ padding: 5px;
+ border-left: 1px solid #e0e0e0;
+ border-right: 1px solid #e0e0e0;
+ border-top: 1px solid #e0e0e0;
+ }
+
+ .expandableSearch {
+ vertical-align: top;
+ padding: 7px 6px !important;
+ border: 1px solid #d0d0d0 !important;
+ background: #fff !important;
+ font-size: 11px !important;
+ color: #454545 !important;
+ width: 100% !important;
+ }
+
+ .expandableList {
+ position: absolute;
+ z-index: 9999;
+ margin-top: -48px;
+ background: #fff;
+ }
+} \ No newline at end of file
diff --git a/plugins/CorePluginsAdmin/angularjs/form-field/field-multiselect.html b/plugins/CorePluginsAdmin/angularjs/form-field/field-multiselect.html
index b6dd7bcd94..72a0379f28 100644
--- a/plugins/CorePluginsAdmin/angularjs/form-field/field-multiselect.html
+++ b/plugins/CorePluginsAdmin/angularjs/form-field/field-multiselect.html
@@ -2,7 +2,7 @@
<select multiple
name="{{ formField.name }}"
ng-model="formField.value"
- ng-options="t.key as t.value for t in formField.availableOptions"
+ ng-options="t.key as t.value group by t.group for t in formField.availableOptions"
piwik-attributes="{{formField.uiControlAttributes}}">
</select>
<label for="{{ formField.name }}" ng-bind-html="formField.title"></label>
diff --git a/plugins/CorePluginsAdmin/angularjs/form-field/field-radio.html b/plugins/CorePluginsAdmin/angularjs/form-field/field-radio.html
index 449d09621f..1363f4192a 100644
--- a/plugins/CorePluginsAdmin/angularjs/form-field/field-radio.html
+++ b/plugins/CorePluginsAdmin/angularjs/form-field/field-radio.html
@@ -8,7 +8,7 @@
type="radio"
id="{{ formField.name + radioModel.key }}"
name="{{ formField.name }}"
- ng-disabled="radioModel.disabled"
+ ng-disabled="radioModel.disabled || formField.disabled"
piwik-attributes="{{formField.uiControlAttributes}}"
>
<label for="{{ formField.name + radioModel.key }}">{{ radioModel.value }}
diff --git a/plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.js b/plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.js
index 00fe79523f..ebfc0df6cb 100644
--- a/plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.js
+++ b/plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.js
@@ -214,6 +214,39 @@
return flatValues;
}
+ if (hasUiControl(field, 'expandable-select')) {
+ var availableValues = field.availableValues;
+ var flatValues = [];
+
+ var groups = {};
+ angular.forEach(availableValues, function (value) {
+
+ if (!value.group) {
+ value.group = '';
+ }
+
+ if (!(value.group in groups) || !groups[value.group]) {
+ groups[value.group] = {values: [], group: value.group}
+ }
+
+ var formatted = {key: value.key, value: value.value};
+
+ if ('tooltip' in value && value.tooltip) {
+ formatted.tooltip = value.tooltip;
+ }
+
+ groups[value.group].values.push(formatted);
+ });
+
+ angular.forEach(groups, function (group) {
+ if (group.values.length) {
+ flatValues.push(group);
+ }
+ });
+
+ return flatValues;
+ }
+
if (isSelectControl(field)) {
var availableValues = field.availableValues;
diff --git a/plugins/CustomDimensions b/plugins/CustomDimensions
-Subproject 453568bb424628b0759db99dd93acfe88222187
+Subproject 2926fb575a7e55c1ff9f2573694dd8908737ccb
diff --git a/plugins/CustomVariables/Categories/CustomVariablesCategory.php b/plugins/CustomVariables/Categories/CustomVariablesCategory.php
new file mode 100644
index 0000000000..ced9de0563
--- /dev/null
+++ b/plugins/CustomVariables/Categories/CustomVariablesCategory.php
@@ -0,0 +1,18 @@
+<?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\Categories;
+
+use Piwik\Category\Category;
+
+class CustomVariablesCategory extends Category
+{
+ protected $id = 'CustomVariables_CustomVariables';
+ protected $order = 8;
+
+}
diff --git a/plugins/CustomVariables/Columns/SearchCategory.php b/plugins/CustomVariables/Columns/SearchCategory.php
new file mode 100644
index 0000000000..abeac9f865
--- /dev/null
+++ b/plugins/CustomVariables/Columns/SearchCategory.php
@@ -0,0 +1,26 @@
+<?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\Columns;
+
+use Piwik\Columns\Discriminator;
+use Piwik\Plugin\Dimension\ActionDimension;
+use Piwik\Plugins\Actions\Actions\ActionSiteSearch;
+
+class SearchCategory extends ActionDimension
+{
+ protected $type = self::TYPE_TEXT;
+ protected $columnName = 'custom_var_v4';
+ protected $nameSingular = 'Actions_SiteSearchCategory';
+ protected $namePlural = 'Actions_SiteSearchCategories';
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator($this->dbTableName, 'custom_var_k4', ActionSiteSearch::CVAR_KEY_SEARCH_CATEGORY);
+ }
+} \ No newline at end of file
diff --git a/plugins/CustomVariables/CustomDimension.php b/plugins/CustomVariables/CustomDimension.php
new file mode 100644
index 0000000000..cd899503cf
--- /dev/null
+++ b/plugins/CustomVariables/CustomDimension.php
@@ -0,0 +1,36 @@
+<?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\Columns\Dimension;
+use Piwik\Piwik;
+
+class CustomDimension extends Dimension
+{
+ protected $type = self::TYPE_TEXT;
+
+ private $id;
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function initCustomDimension($index, Model $scope)
+ {
+ $category = $scope->getScopeDescription();
+
+ $this->id = 'CustomVariables.CustomVariable' . ucfirst($scope->getScope()) . $index;
+ $this->nameSingular = Piwik::translate('CustomVariables_ColumnCustomVariableValue') . ' ' . $index . ' (' . $category .')';
+ $this->columnName = 'custom_var_v' . (int) $index;
+ $this->category = 'CustomVariables_CustomVariables';
+ $this->dbTableName = $scope->getUnprefixedTableName();
+ }
+
+} \ No newline at end of file
diff --git a/plugins/CustomVariables/CustomVariables.php b/plugins/CustomVariables/CustomVariables.php
index e5a13bc52a..c18eaf946c 100644
--- a/plugins/CustomVariables/CustomVariables.php
+++ b/plugins/CustomVariables/CustomVariables.php
@@ -23,6 +23,7 @@ class CustomVariables extends \Piwik\Plugin
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
+ 'Dimension.addDimensions' => 'addDimensions',
'Actions.getCustomActionDimensionFieldsAndJoins' => 'provideActionDimensionFields'
);
}
@@ -37,6 +38,24 @@ class CustomVariables extends \Piwik\Plugin
Model::uninstall();
}
+ public function addDimensions(&$instances)
+ {
+ foreach (Model::getScopes() as $scope) {
+ $model = new Model($scope);
+ try {
+ $highestIndex = $model->getHighestCustomVarIndex();
+ } catch (\Exception $e) {
+ continue; // ignore error for tests to work as this might be executed before Piwik tables are installed
+ }
+
+ foreach (range(1, $highestIndex) as $index) {
+ $custom = new CustomDimension();
+ $custom->initCustomDimension($index, $model);
+ $instances[] = $custom;
+ }
+ }
+ }
+
/**
* There are also some hardcoded places in JavaScript
* @return int
diff --git a/plugins/CustomVariables/Model.php b/plugins/CustomVariables/Model.php
index 235809e1da..5abb327f0e 100644
--- a/plugins/CustomVariables/Model.php
+++ b/plugins/CustomVariables/Model.php
@@ -12,6 +12,7 @@ use Piwik\Common;
use Piwik\DataTable;
use Piwik\Db;
use Piwik\Log;
+use Piwik\Piwik;
class Model
{
@@ -23,6 +24,7 @@ class Model
private $scope = null;
private $table = null;
+ private $tableUnprefixed = null;
public function __construct($scope)
{
@@ -31,7 +33,13 @@ class Model
}
$this->scope = $scope;
- $this->table = Common::prefixTable($this->getTableNameFromScope($scope));
+ $this->tableUnprefixed = $this->getTableNameFromScope($scope);
+ $this->table = Common::prefixTable($this->tableUnprefixed);
+ }
+
+ public function getUnprefixedTableName()
+ {
+ return $this->tableUnprefixed;
}
private function getTableNameFromScope($scope)
@@ -47,11 +55,30 @@ class Model
}
}
+ public function getScope()
+ {
+ return $this->scope;
+ }
+
public function getScopeName()
{
return ucfirst($this->scope);
}
+ public function getScopeDescription()
+ {
+ switch ($this->scope) {
+ case Model::SCOPE_PAGE:
+ return Piwik::translate('CustomVariables_ScopePage');
+ case Model::SCOPE_VISIT:
+ return Piwik::translate('CustomVariables_ScopeVisit');
+ case Model::SCOPE_CONVERSION:
+ return Piwik::translate('CustomVariables_ScopeConversion');
+ }
+
+ return ucfirst($this->scope);
+ }
+
/**
* @see getHighestCustomVarIndex()
* @return int
diff --git a/plugins/CustomVariables/lang/en.json b/plugins/CustomVariables/lang/en.json
index e065886759..56a6d3380b 100644
--- a/plugins/CustomVariables/lang/en.json
+++ b/plugins/CustomVariables/lang/en.json
@@ -7,6 +7,7 @@
"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",
+ "ScopeConversion": "scope conversion",
"ManageDescription": "This overview shows all custom variable slots and their usages for website '%s'. The names within each slot are ordered by how often they were used in total.",
"ScopeX": "Scope %s",
"Index": "Index",
diff --git a/plugins/CustomVariables/tests/Integration/ModelTest.php b/plugins/CustomVariables/tests/Integration/ModelTest.php
index 905a5f6a1d..6f504f9525 100644
--- a/plugins/CustomVariables/tests/Integration/ModelTest.php
+++ b/plugins/CustomVariables/tests/Integration/ModelTest.php
@@ -102,6 +102,26 @@ class ModelTest extends IntegrationTestCase
$this->assertEquals('Conversion', $this->getConversionScope()->getScopeName());
}
+ public function testGetScopeDescription()
+ {
+ $this->assertEquals('scope page', $this->getPageScope()->getScopeDescription());
+ $this->assertEquals('scope visit', $this->getVisitScope()->getScopeDescription());
+ $this->assertEquals('scope conversion', $this->getConversionScope()->getScopeDescription());
+ }
+
+ public function testGetUnprefixedTableName()
+ {
+ $this->assertEquals('log_link_visit_action', $this->getPageScope()->getUnprefixedTableName());
+ $this->assertEquals('log_visit', $this->getVisitScope()->getUnprefixedTableName());
+ $this->assertEquals('log_conversion', $this->getConversionScope()->getUnprefixedTableName());
+ }
+
+ public function testGetScope()
+ {
+ $this->assertEquals(Model::SCOPE_PAGE, $this->getPageScope()->getScope());
+ $this->assertEquals(Model::SCOPE_VISIT, $this->getVisitScope()->getScope());
+ }
+
public function test_getCurrentNumCustomVars()
{
$this->assertEquals(5, $this->getPageScope()->getCurrentNumCustomVars());
diff --git a/plugins/DevicePlugins/Columns/Plugin.php b/plugins/DevicePlugins/Columns/Plugin.php
index 0066c5ce19..a01d01c57c 100644
--- a/plugins/DevicePlugins/Columns/Plugin.php
+++ b/plugins/DevicePlugins/Columns/Plugin.php
@@ -13,8 +13,5 @@ use Piwik\Piwik;
class Plugin extends Dimension
{
- public function getName()
- {
- return Piwik::translate('General_Plugin');
- }
+ protected $nameSingular = 'General_Plugin';
} \ No newline at end of file
diff --git a/plugins/DevicePlugins/Columns/PluginCookie.php b/plugins/DevicePlugins/Columns/PluginCookie.php
index 19dd1e226d..b07aad3587 100644
--- a/plugins/DevicePlugins/Columns/PluginCookie.php
+++ b/plugins/DevicePlugins/Columns/PluginCookie.php
@@ -17,6 +17,7 @@ class PluginCookie extends DevicePluginColumn
{
protected $columnName = 'config_cookie';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicePlugins/Columns/PluginDirector.php b/plugins/DevicePlugins/Columns/PluginDirector.php
index b1b479d92d..209e718c6e 100644
--- a/plugins/DevicePlugins/Columns/PluginDirector.php
+++ b/plugins/DevicePlugins/Columns/PluginDirector.php
@@ -17,6 +17,7 @@ class PluginDirector extends DevicePluginColumn
{
protected $columnName = 'config_director';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicePlugins/Columns/PluginFlash.php b/plugins/DevicePlugins/Columns/PluginFlash.php
index e307ef0c84..2b17c70681 100644
--- a/plugins/DevicePlugins/Columns/PluginFlash.php
+++ b/plugins/DevicePlugins/Columns/PluginFlash.php
@@ -17,6 +17,7 @@ class PluginFlash extends DevicePluginColumn
{
protected $columnName = 'config_flash';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicePlugins/Columns/PluginGears.php b/plugins/DevicePlugins/Columns/PluginGears.php
index c0845f0904..c8b40235f4 100644
--- a/plugins/DevicePlugins/Columns/PluginGears.php
+++ b/plugins/DevicePlugins/Columns/PluginGears.php
@@ -17,6 +17,7 @@ class PluginGears extends DevicePluginColumn
{
protected $columnName = 'config_gears';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicePlugins/Columns/PluginJava.php b/plugins/DevicePlugins/Columns/PluginJava.php
index bd9877a1b5..d23c3a3c3e 100644
--- a/plugins/DevicePlugins/Columns/PluginJava.php
+++ b/plugins/DevicePlugins/Columns/PluginJava.php
@@ -17,6 +17,7 @@ class PluginJava extends DevicePluginColumn
{
protected $columnName = 'config_java';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicePlugins/Columns/PluginPdf.php b/plugins/DevicePlugins/Columns/PluginPdf.php
index bd1fccfad3..69945b3d66 100644
--- a/plugins/DevicePlugins/Columns/PluginPdf.php
+++ b/plugins/DevicePlugins/Columns/PluginPdf.php
@@ -17,6 +17,7 @@ class PluginPdf extends DevicePluginColumn
{
protected $columnName = 'config_pdf';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicePlugins/Columns/PluginQuickTime.php b/plugins/DevicePlugins/Columns/PluginQuickTime.php
index a203dedccb..57e6bc754e 100644
--- a/plugins/DevicePlugins/Columns/PluginQuickTime.php
+++ b/plugins/DevicePlugins/Columns/PluginQuickTime.php
@@ -17,6 +17,7 @@ class PluginQuickTime extends DevicePluginColumn
{
protected $columnName = 'config_quicktime';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicePlugins/Columns/PluginRealPlayer.php b/plugins/DevicePlugins/Columns/PluginRealPlayer.php
index d805aafccd..2de970caa4 100644
--- a/plugins/DevicePlugins/Columns/PluginRealPlayer.php
+++ b/plugins/DevicePlugins/Columns/PluginRealPlayer.php
@@ -17,6 +17,7 @@ class PluginRealPlayer extends DevicePluginColumn
{
protected $columnName = 'config_realplayer';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicePlugins/Columns/PluginSilverlight.php b/plugins/DevicePlugins/Columns/PluginSilverlight.php
index 897d2939da..154aea8975 100644
--- a/plugins/DevicePlugins/Columns/PluginSilverlight.php
+++ b/plugins/DevicePlugins/Columns/PluginSilverlight.php
@@ -17,6 +17,7 @@ class PluginSilverlight extends DevicePluginColumn
{
protected $columnName = 'config_silverlight';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicePlugins/Columns/PluginWindowsMedia.php b/plugins/DevicePlugins/Columns/PluginWindowsMedia.php
index 99e25f4bdc..6318fd0f55 100644
--- a/plugins/DevicePlugins/Columns/PluginWindowsMedia.php
+++ b/plugins/DevicePlugins/Columns/PluginWindowsMedia.php
@@ -17,6 +17,7 @@ class PluginWindowsMedia extends DevicePluginColumn
{
protected $columnName = 'config_windowsmedia';
protected $columnType = 'TINYINT(1) NULL';
+ protected $type = self::TYPE_BOOL;
/**
* @param Request $request
diff --git a/plugins/DevicesDetection/Columns/BrowserEngine.php b/plugins/DevicesDetection/Columns/BrowserEngine.php
index 1639ec59fe..c9f60cd73e 100644
--- a/plugins/DevicesDetection/Columns/BrowserEngine.php
+++ b/plugins/DevicesDetection/Columns/BrowserEngine.php
@@ -8,8 +8,7 @@
*/
namespace Piwik\Plugins\DevicesDetection\Columns;
-use Piwik\Piwik;
-use Piwik\Plugins\DevicesDetection\Segment;
+use Piwik\Metrics\Formatter;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -18,20 +17,16 @@ class BrowserEngine extends Base
{
protected $columnName = 'config_browser_engine';
protected $columnType = 'VARCHAR(10) NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('browserEngine');
- $segment->setName('DevicesDetection_BrowserEngine');
- $segment->setAcceptedValues('Trident, WebKit, Presto, Gecko, Blink, etc.');
- $segment->setSuggestedValuesCallback('\DeviceDetector\Parser\Client\Browser\Engine::getAvailableEngines');
- $this->addSegment($segment);
- }
-
- public function getName()
+ protected $segmentName = 'browserEngine';
+ protected $nameSingular = 'DevicesDetection_BrowserEngine';
+ protected $namePlural = 'DevicesDetection_BrowserEngines';
+ protected $acceptValues = 'Trident, WebKit, Presto, Gecko, Blink, etc.';
+ protected $suggestedValuesCallback = '\DeviceDetector\Parser\Client\Browser\Engine::getAvailableEngines';
+ protected $type = self::TYPE_TEXT;
+
+ public function formatValue($value, $idSite, Formatter $formatter)
{
- return Piwik::translate('DevicesDetection_BrowserEngine');
+ return \Piwik\Plugins\DevicesDetection\getBrowserEngineName($value);
}
/**
diff --git a/plugins/DevicesDetection/Columns/BrowserName.php b/plugins/DevicesDetection/Columns/BrowserName.php
index b60b87f5af..0fe0d724d5 100644
--- a/plugins/DevicesDetection/Columns/BrowserName.php
+++ b/plugins/DevicesDetection/Columns/BrowserName.php
@@ -8,8 +8,7 @@
*/
namespace Piwik\Plugins\DevicesDetection\Columns;
-use Piwik\Piwik;
-use Piwik\Plugins\DevicesDetection\Segment;
+use Piwik\Metrics\Formatter;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -18,19 +17,15 @@ class BrowserName extends Base
{
protected $columnName = 'config_browser_name';
protected $columnType = 'VARCHAR(10) NULL';
+ protected $segmentName = 'browserCode';
+ protected $nameSingular = 'DevicesDetection_ColumnBrowser';
+ protected $namePlural = 'DevicesDetection_Browsers';
+ protected $acceptValues = 'FF, IE, CH, SF, OP, etc.';
+ protected $type = self::TYPE_TEXT;
- protected function configureSegments()
+ public function formatValue($value, $idSite, Formatter $formatter)
{
- $segment = new Segment();
- $segment->setSegment('browserCode');
- $segment->setName('DevicesDetection_ColumnBrowser');
- $segment->setAcceptedValues('FF, IE, CH, SF, OP, etc.');
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('DevicesDetection_ColumnBrowser');
+ return \Piwik\Plugins\DevicesDetection\getBrowserName($value);
}
/**
diff --git a/plugins/DevicesDetection/Columns/BrowserVersion.php b/plugins/DevicesDetection/Columns/BrowserVersion.php
index aabca4e9fb..9fd4593aac 100644
--- a/plugins/DevicesDetection/Columns/BrowserVersion.php
+++ b/plugins/DevicesDetection/Columns/BrowserVersion.php
@@ -8,8 +8,6 @@
*/
namespace Piwik\Plugins\DevicesDetection\Columns;
-use Piwik\Piwik;
-use Piwik\Plugins\DevicesDetection\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -18,20 +16,11 @@ class BrowserVersion extends Base
{
protected $columnName = 'config_browser_version';
protected $columnType = 'VARCHAR(20) NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('browserVersion');
- $segment->setName('DevicesDetection_BrowserVersion');
- $segment->setAcceptedValues('1.0, 8.0, etc.');
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('DevicesDetection_BrowserVersion');
- }
+ protected $segmentName = 'browserVersion';
+ protected $nameSingular = 'DevicesDetection_BrowserVersion';
+ protected $namePlural = 'DevicesDetection_BrowserVersions';
+ protected $acceptValues = '1.0, 8.0, etc.';
+ protected $type = self::TYPE_TEXT;
/**
* @param Request $request
diff --git a/plugins/DevicesDetection/Columns/DeviceBrand.php b/plugins/DevicesDetection/Columns/DeviceBrand.php
index 8b0bfdc35e..ee4db69954 100644
--- a/plugins/DevicesDetection/Columns/DeviceBrand.php
+++ b/plugins/DevicesDetection/Columns/DeviceBrand.php
@@ -9,8 +9,8 @@
namespace Piwik\Plugins\DevicesDetection\Columns;
use DeviceDetector\Parser\Device\DeviceParserAbstract;
+use Piwik\Metrics\Formatter;
use Piwik\Piwik;
-use Piwik\Plugins\DevicesDetection\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -19,23 +19,25 @@ class DeviceBrand extends Base
{
protected $columnName = 'config_device_brand';
protected $columnType = 'VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL';
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'DevicesDetection_DeviceBrand';
+ protected $namePlural = 'DevicesDetection_DeviceBrands';
+ protected $segmentName = 'deviceBrand';
- public function getName()
+
+ public function formatValue($value, $idSite, Formatter $formatter)
{
- return Piwik::translate('DevicesDetection_DeviceBrand');
+ return \Piwik\Plugins\DevicesDetection\getDeviceBrandLabel($value);
}
- protected function configureSegments()
+ public function __construct()
{
$brands = DeviceParserAbstract::$deviceBrands;
natcasesort ($brands);
$brandList = implode(", ", $brands);
+ $this->acceptValues = $brandList;
- $segment = new Segment();
- $segment->setSegment('deviceBrand');
- $segment->setName('DevicesDetection_DeviceBrand');
- $segment->setAcceptedValues($brandList);
- $segment->setSqlFilter(function ($brand) use ($brandList, $brands) {
+ $this->sqlFilter = function ($brand) use ($brandList, $brands) {
if ($brand == Piwik::translate('General_Unknown')) {
return '';
}
@@ -44,8 +46,7 @@ class DeviceBrand extends Base
throw new \Exception("deviceBrand segment must be one of: $brandList");
}
return $index;
- });
- $this->addSegment($segment);
+ };
}
/**
diff --git a/plugins/DevicesDetection/Columns/DeviceModel.php b/plugins/DevicesDetection/Columns/DeviceModel.php
index 5f74686795..4ac962f0e1 100644
--- a/plugins/DevicesDetection/Columns/DeviceModel.php
+++ b/plugins/DevicesDetection/Columns/DeviceModel.php
@@ -8,7 +8,6 @@
*/
namespace Piwik\Plugins\DevicesDetection\Columns;
-use Piwik\Piwik;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -17,11 +16,9 @@ class DeviceModel extends Base
{
protected $columnName = 'config_device_model';
protected $columnType = 'VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL';
-
- public function getName()
- {
- return Piwik::translate('DevicesDetection_DeviceModel');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'DevicesDetection_DeviceModel';
+ protected $namePlural = 'DevicesDetection_DeviceModels';
/**
* @param Request $request
diff --git a/plugins/DevicesDetection/Columns/DeviceType.php b/plugins/DevicesDetection/Columns/DeviceType.php
index 6e18d7b3b0..10233e7c92 100644
--- a/plugins/DevicesDetection/Columns/DeviceType.php
+++ b/plugins/DevicesDetection/Columns/DeviceType.php
@@ -8,8 +8,7 @@
*/
namespace Piwik\Plugins\DevicesDetection\Columns;
-use Piwik\Piwik;
-use Piwik\Plugin\Segment;
+use Piwik\Metrics\Formatter;
use Piwik\Tracker\Request;
use Exception;
use Piwik\Tracker\Visitor;
@@ -20,31 +19,28 @@ class DeviceType extends Base
{
protected $columnName = 'config_device_type';
protected $columnType = 'TINYINT( 100 ) NULL DEFAULT NULL';
+ protected $segmentName = 'deviceType';
+ protected $type = self::TYPE_ENUM;
+ protected $nameSingular = 'DevicesDetection_DeviceType';
+ protected $namePlural = 'DevicesDetection_DeviceTypes';
- protected function configureSegments()
+ public function __construct()
{
$deviceTypes = DeviceParser::getAvailableDeviceTypeNames();
$deviceTypeList = implode(", ", $deviceTypes);
- $segment = new Segment();
- $segment->setCategory('General_Visit');
- $segment->setSegment('deviceType');
- $segment->setName('DevicesDetection_DeviceType');
- $segment->setAcceptedValues($deviceTypeList);
- $segment->setSqlFilter(function ($type) use ($deviceTypeList, $deviceTypes) {
- $index = array_search(strtolower(trim(urldecode($type))), $deviceTypes);
- if ($index === false) {
- throw new Exception("deviceType segment must be one of: $deviceTypeList");
- }
- return $index;
- });
+ $this->acceptValues = $deviceTypeList;
+ }
- $this->addSegment($segment);
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ return \Piwik\Plugins\DevicesDetection\getDeviceTypeLabel($value);
}
- public function getName()
+ public function getEnumColumnValues()
{
- return Piwik::translate('DevicesDetection_DeviceType');
+ $values = DeviceParser::getAvailableDeviceTypes();
+ return array_flip($values);
}
/**
diff --git a/plugins/DevicesDetection/Columns/Os.php b/plugins/DevicesDetection/Columns/Os.php
index a787340dc2..455b971486 100644
--- a/plugins/DevicesDetection/Columns/Os.php
+++ b/plugins/DevicesDetection/Columns/Os.php
@@ -8,8 +8,8 @@
*/
namespace Piwik\Plugins\DevicesDetection\Columns;
+use Piwik\Metrics\Formatter;
use Piwik\Piwik;
-use Piwik\Plugins\DevicesDetection\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Settings;
use Piwik\Tracker\Visitor;
@@ -19,14 +19,15 @@ class Os extends Base
{
protected $columnName = 'config_os';
protected $columnType = 'CHAR(3) NULL';
+ protected $segmentName = 'operatingSystemCode';
+ protected $nameSingular = 'DevicesDetection_ColumnOperatingSystem';
+ protected $namePlural = 'DevicesDetection_OperatingSystems';
+ protected $acceptValues = 'WIN, MAC, LIN, AND, IPD, etc.';
+ protected $type = self::TYPE_TEXT;
- protected function configureSegments()
+ public function formatValue($value, $idSite, Formatter $formatter)
{
- $segment = new Segment();
- $segment->setSegment('operatingSystemCode');
- $segment->setName('DevicesDetection_ColumnOperatingSystem');
- $segment->setAcceptedValues('WIN, MAC, LIN, AND, IPD, etc.');
- $this->addSegment($segment);
+ return \Piwik\Plugins\DevicesDetection\getOSFamilyFullName($value);
}
public function getName()
diff --git a/plugins/DevicesDetection/Columns/OsVersion.php b/plugins/DevicesDetection/Columns/OsVersion.php
index d1c3cb422a..ef7d9b6dca 100644
--- a/plugins/DevicesDetection/Columns/OsVersion.php
+++ b/plugins/DevicesDetection/Columns/OsVersion.php
@@ -8,8 +8,6 @@
*/
namespace Piwik\Plugins\DevicesDetection\Columns;
-use Piwik\Piwik;
-use Piwik\Plugins\DevicesDetection\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -18,20 +16,11 @@ class OsVersion extends Base
{
protected $columnName = 'config_os_version';
protected $columnType = 'VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('operatingSystemVersion');
- $segment->setName('DevicesDetection_ColumnOperatingSystemVersion');
- $segment->setAcceptedValues('XP, 7, 2.3, 5.1, ...');
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('DevicesDetection_OperatingSystemVersions');
- }
+ protected $nameSingular = 'DevicesDetection_ColumnOperatingSystemVersion';
+ protected $namePlural = 'DevicesDetection_OperatingSystemVersions';
+ protected $segmentName = 'operatingSystemVersion';
+ protected $acceptValues = 'XP, 7, 2.3, 5.1, ...';
+ protected $type = self::TYPE_TEXT;
/**
* @param Request $request
diff --git a/plugins/DevicesDetection/Segment.php b/plugins/DevicesDetection/Segment.php
deleted file mode 100644
index 8f0858facb..0000000000
--- a/plugins/DevicesDetection/Segment.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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\DevicesDetection;
-
-/**
- * UserSettings segment base class.
- *
- */
-class Segment extends \Piwik\Plugin\Segment
-{
- protected function init()
- {
- $this->setCategory('General_Visit');
- }
-}
diff --git a/plugins/DevicesDetection/lang/en.json b/plugins/DevicesDetection/lang/en.json
index 7015cefe04..c31c5726be 100644
--- a/plugins/DevicesDetection/lang/en.json
+++ b/plugins/DevicesDetection/lang/en.json
@@ -20,10 +20,13 @@
"dataTableLabelTypes": "Type",
"Device": "Device",
"DeviceBrand": "Device brand",
+ "DeviceBrands": "Device brands",
"DeviceDetection": "Device detection",
"DeviceModel": "Device model",
+ "DeviceModels": "Device models",
"DevicesDetection": "Visitor Devices",
"DeviceType": "Device type",
+ "DeviceTypes": "Device types",
"FeaturePhone": "Feature phone",
"OperatingSystemFamilies": "Operating System families",
"OperatingSystemFamily": "Operating system family",
diff --git a/plugins/Ecommerce/Columns/Items.php b/plugins/Ecommerce/Columns/Items.php
new file mode 100644
index 0000000000..834b020577
--- /dev/null
+++ b/plugins/Ecommerce/Columns/Items.php
@@ -0,0 +1,18 @@
+<?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\Ecommerce\Columns;
+
+class Items extends BaseConversion
+{
+ protected $columnName = 'items';
+ protected $type = self::TYPE_NUMBER;
+ protected $category = 'Goals_Ecommerce';
+ protected $nameSingular = 'Ecommerce_NumberOfItems';
+
+} \ No newline at end of file
diff --git a/plugins/Ecommerce/Columns/Order.php b/plugins/Ecommerce/Columns/Order.php
new file mode 100644
index 0000000000..346c474753
--- /dev/null
+++ b/plugins/Ecommerce/Columns/Order.php
@@ -0,0 +1,37 @@
+<?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\Ecommerce\Columns;
+
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\MetricsList;
+use Piwik\Plugin\ArchivedMetric;
+use Piwik\Tracker\GoalManager;
+
+class Order extends BaseConversion
+{
+ protected $columnName = 'idorder';
+ protected $type = self::TYPE_NUMBER;
+ protected $category = 'Goals_Ecommerce';
+ protected $nameSingular = 'Ecommerce_Order';
+ protected $namePlural = 'Ecommerce_Orders';
+ protected $metricId = 'orders';
+
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ $metric = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_UNIQUE);
+ $metricsList->addMetric($metric);
+ }
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator($this->dbTableName, 'idgoal', GoalManager::IDGOAL_ORDER);
+ }
+
+} \ No newline at end of file
diff --git a/plugins/Ecommerce/Columns/ProductCategory.php b/plugins/Ecommerce/Columns/ProductCategory.php
index 1b5aa0b2e2..c080dde65a 100644
--- a/plugins/Ecommerce/Columns/ProductCategory.php
+++ b/plugins/Ecommerce/Columns/ProductCategory.php
@@ -13,8 +13,7 @@ use Piwik\Piwik;
class ProductCategory extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Goals_ProductCategory');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'Goals_Ecommerce';
+ protected $nameSingular = 'Goals_ProductCategory';
} \ No newline at end of file
diff --git a/plugins/Ecommerce/Columns/ProductName.php b/plugins/Ecommerce/Columns/ProductName.php
index 8c9d43c8a6..ab7033a507 100644
--- a/plugins/Ecommerce/Columns/ProductName.php
+++ b/plugins/Ecommerce/Columns/ProductName.php
@@ -9,12 +9,27 @@
namespace Piwik\Plugins\Ecommerce\Columns;
use Piwik\Columns\Dimension;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
+use Piwik\Tracker\Action;
class ProductName extends Dimension
{
- public function getName()
+ protected $type = self::TYPE_TEXT;
+ protected $dbTableName = 'log_conversion_item';
+ protected $columnName = 'idaction_name';
+ protected $nameSingular = 'Goals_ProductName';
+ protected $namePlural = 'Goals_ProductNames';
+ protected $category = 'Goals_Ecommerce';
+
+ public function getDbColumnJoin()
{
- return Piwik::translate('Goals_ProductName');
+ return new ActionNameJoin();
}
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator('log_action', 'type', Action::TYPE_ECOMMERCE_ITEM_NAME);
+ }
+
} \ No newline at end of file
diff --git a/plugins/Ecommerce/Columns/ProductPrice.php b/plugins/Ecommerce/Columns/ProductPrice.php
new file mode 100644
index 0000000000..9d935d8253
--- /dev/null
+++ b/plugins/Ecommerce/Columns/ProductPrice.php
@@ -0,0 +1,21 @@
+<?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\Ecommerce\Columns;
+
+use Piwik\Columns\Dimension;
+
+class ProductPrice extends Dimension
+{
+ protected $type = self::TYPE_MONEY;
+ protected $dbTableName = 'log_conversion_item';
+ protected $columnName = 'price';
+ protected $nameSingular = 'Goals_ProductPrice';
+ protected $category = 'Goals_Ecommerce';
+
+} \ No newline at end of file
diff --git a/plugins/Ecommerce/Columns/ProductQuantity.php b/plugins/Ecommerce/Columns/ProductQuantity.php
new file mode 100644
index 0000000000..18d50c94c2
--- /dev/null
+++ b/plugins/Ecommerce/Columns/ProductQuantity.php
@@ -0,0 +1,21 @@
+<?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\Ecommerce\Columns;
+
+use Piwik\Columns\Dimension;
+
+class ProductQuantity extends Dimension
+{
+ protected $type = self::TYPE_NUMBER;
+ protected $dbTableName = 'log_conversion_item';
+ protected $columnName = 'quantity';
+ protected $nameSingular = 'Goals_ProductQuantity';
+ protected $category = 'Goals_Ecommerce';
+
+} \ No newline at end of file
diff --git a/plugins/Ecommerce/Columns/ProductSku.php b/plugins/Ecommerce/Columns/ProductSku.php
index c0a53c503b..2bd97b4988 100644
--- a/plugins/Ecommerce/Columns/ProductSku.php
+++ b/plugins/Ecommerce/Columns/ProductSku.php
@@ -9,12 +9,27 @@
namespace Piwik\Plugins\Ecommerce\Columns;
use Piwik\Columns\Dimension;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
+use Piwik\Tracker\Action;
class ProductSku extends Dimension
{
- public function getName()
+ protected $type = self::TYPE_TEXT;
+ protected $dbTableName = 'log_conversion_item';
+ protected $columnName = 'idaction_sku';
+ protected $nameSingular = 'Goals_ProductSKU';
+ protected $namePlural = 'Goals_ProductSKUs';
+ protected $category = 'Goals_Ecommerce';
+
+ public function getDbColumnJoin()
{
- return Piwik::translate('Goals_ProductSKU');
+ return new ActionNameJoin();
}
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator('log_action', 'type', Action::TYPE_ECOMMERCE_ITEM_SKU);
+ }
+
} \ No newline at end of file
diff --git a/plugins/Ecommerce/Columns/Revenue.php b/plugins/Ecommerce/Columns/Revenue.php
index ae37315ac7..c5b39edd8c 100644
--- a/plugins/Ecommerce/Columns/Revenue.php
+++ b/plugins/Ecommerce/Columns/Revenue.php
@@ -8,6 +8,7 @@
*/
namespace Piwik\Plugins\Ecommerce\Columns;
+use Piwik\Columns\Discriminator;
use Piwik\Tracker\GoalManager;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -17,6 +18,14 @@ class Revenue extends BaseConversion
{
protected $columnName = 'revenue';
protected $columnType = 'float default NULL';
+ protected $type = self::TYPE_MONEY;
+ protected $category = 'Goals_Ecommerce';
+ protected $nameSingular = 'Ecommerce_OrderValue';
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator($this->dbTableName, 'idgoal', GoalManager::IDGOAL_ORDER);
+ }
/**
* @param Request $request
diff --git a/plugins/Ecommerce/Columns/RevenueDiscount.php b/plugins/Ecommerce/Columns/RevenueDiscount.php
index 679d6c4ac7..b734be2235 100644
--- a/plugins/Ecommerce/Columns/RevenueDiscount.php
+++ b/plugins/Ecommerce/Columns/RevenueDiscount.php
@@ -17,6 +17,9 @@ class RevenueDiscount extends BaseConversion
{
protected $columnName = 'revenue_discount';
protected $columnType = 'float default NULL';
+ protected $type = self::TYPE_MONEY;
+ protected $category = 'Goals_Ecommerce';
+ protected $nameSingular = 'General_Discount';
/**
* @param Request $request
diff --git a/plugins/Ecommerce/Columns/RevenueShipping.php b/plugins/Ecommerce/Columns/RevenueShipping.php
index 41591ca2e1..c65a4ca174 100644
--- a/plugins/Ecommerce/Columns/RevenueShipping.php
+++ b/plugins/Ecommerce/Columns/RevenueShipping.php
@@ -17,6 +17,9 @@ class RevenueShipping extends BaseConversion
{
protected $columnName = 'revenue_shipping';
protected $columnType = 'float default NULL';
+ protected $type = self::TYPE_MONEY;
+ protected $category = 'Goals_Ecommerce';
+ protected $nameSingular = 'General_Shipping';
/**
* @param Request $request
diff --git a/plugins/Ecommerce/Columns/RevenueSubtotal.php b/plugins/Ecommerce/Columns/RevenueSubtotal.php
index 7b09df0014..86409dbb3d 100644
--- a/plugins/Ecommerce/Columns/RevenueSubtotal.php
+++ b/plugins/Ecommerce/Columns/RevenueSubtotal.php
@@ -17,6 +17,9 @@ class RevenueSubtotal extends BaseConversion
{
protected $columnName = 'revenue_subtotal';
protected $columnType = 'float default NULL';
+ protected $type = self::TYPE_MONEY;
+ protected $category = 'Goals_Ecommerce';
+ protected $nameSingular = 'General_Subtotal';
/**
* @param Request $request
diff --git a/plugins/Ecommerce/Columns/RevenueTax.php b/plugins/Ecommerce/Columns/RevenueTax.php
index 4a2df65d64..820ee95037 100644
--- a/plugins/Ecommerce/Columns/RevenueTax.php
+++ b/plugins/Ecommerce/Columns/RevenueTax.php
@@ -17,6 +17,9 @@ class RevenueTax extends BaseConversion
{
protected $columnName = 'revenue_tax';
protected $columnType = 'float default NULL';
+ protected $type = self::TYPE_MONEY;
+ protected $category = 'Goals_Ecommerce';
+ protected $nameSingular = 'General_Tax';
/**
* @param Request $request
diff --git a/plugins/Ecommerce/Ecommerce.php b/plugins/Ecommerce/Ecommerce.php
new file mode 100644
index 0000000000..922c51648b
--- /dev/null
+++ b/plugins/Ecommerce/Ecommerce.php
@@ -0,0 +1,52 @@
+<?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\Ecommerce;
+use Piwik\Columns\ComputedMetricFactory;
+use Piwik\Columns\MetricsList;
+use Piwik\Piwik;
+use Piwik\Plugin\ArchivedMetric;
+use Piwik\Plugin\ComputedMetric;
+
+/**
+ *
+ */
+class Ecommerce extends \Piwik\Plugin
+{
+
+ /**
+ * @see \Piwik\Plugin::registerEvents
+ */
+ public function registerEvents()
+ {
+ $hooks = array(
+ 'Metric.addComputedMetrics' => 'addComputedMetrics'
+ );
+ return $hooks;
+ }
+
+ public function addComputedMetrics(MetricsList $list, ComputedMetricFactory $computedMetricFactory)
+ {
+ $category = 'Goals_Ecommerce';
+
+ $metrics = $list->getMetrics();
+ foreach ($metrics as $metric) {
+ if ($metric instanceof ArchivedMetric && $metric->getDimension()) {
+ $metricName = $metric->getName();
+ if ($metric->getDbTableName() === 'log_conversion'
+ && $metricName !== 'nb_uniq_orders'
+ && strpos($metricName, ArchivedMetric::AGGREGATION_SUM_PREFIX) === 0
+ && $metric->getCategoryId() === $category) {
+ $metric = $computedMetricFactory->createComputedMetric($metric->getName(), 'nb_uniq_orders', ComputedMetric::AGGREGATION_AVG);
+ $list->addMetric($metric);
+ }
+ }
+ }
+ }
+
+}
diff --git a/plugins/Ecommerce/lang/en.json b/plugins/Ecommerce/lang/en.json
index 82419ad05c..850ecfb661 100644
--- a/plugins/Ecommerce/lang/en.json
+++ b/plugins/Ecommerce/lang/en.json
@@ -2,8 +2,12 @@
"Ecommerce": {
"PluginDescription": "Ecommerce lets you track when users add products to carts, and when they convert to a ecommerce sale. Also track products and product categories views and abandoned carts.",
"Sales": "Sales",
+ "Order": "Order",
+ "Orders": "Orders",
"SalesBy": "Sales by %s",
"SalesAdjective": "Sales %s",
+ "NumberOfItems": "Number of Items in Cart",
+ "OrderValue": "Order value",
"LifeTimeValue": "Ecommerce Life Time Value",
"LifeTimeValueDescription": "Total Ecommerce revenue attributed to this customer across all visits: the sum of revenue of all Ecommerce orders for Visitor ID %s.",
"VisitorProfileLTV": "Generated a Life Time Revenue of %1$s.",
diff --git a/plugins/Events/Categories/EventsCategory.php b/plugins/Events/Categories/EventsCategory.php
new file mode 100644
index 0000000000..3e82e4887c
--- /dev/null
+++ b/plugins/Events/Categories/EventsCategory.php
@@ -0,0 +1,19 @@
+<?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\Events\Categories;
+
+use Piwik\Category\Category;
+
+// Needed for dimensions and metrics
+class EventsCategory extends Category
+{
+ protected $id = 'Events_Events';
+ protected $order = 12;
+
+}
diff --git a/plugins/Events/Columns/EventAction.php b/plugins/Events/Columns/EventAction.php
index 30c33fe8da..e08325e0b7 100644
--- a/plugins/Events/Columns/EventAction.php
+++ b/plugins/Events/Columns/EventAction.php
@@ -8,10 +8,10 @@
*/
namespace Piwik\Plugins\Events\Columns;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Exception\InvalidRequestParameterException;
-use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Events\Segment;
use Piwik\Plugins\Events\Actions\ActionEvent;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -20,18 +20,21 @@ class EventAction extends ActionDimension
{
protected $columnName = 'idaction_event_action';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
-
- protected function configureSegments()
+ protected $type = self::TYPE_TEXT;
+ protected $segmentName = 'eventAction';
+ protected $nameSingular = 'Events_EventAction';
+ protected $namePlural = 'Events_EventActions';
+ protected $category = 'Events_Events';
+ protected $sqlFilter = '\Piwik\Tracker\TableLogAction::getIdActionFromSegment';
+
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('eventAction');
- $segment->setName('Events_EventAction');
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('Events_EventAction');
+ return new Discriminator('log_action', 'type', $this->getActionId());
}
public function getActionId()
diff --git a/plugins/Events/Columns/EventCategory.php b/plugins/Events/Columns/EventCategory.php
index 731dd9615c..b10b1a8406 100644
--- a/plugins/Events/Columns/EventCategory.php
+++ b/plugins/Events/Columns/EventCategory.php
@@ -8,10 +8,10 @@
*/
namespace Piwik\Plugins\Events\Columns;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Exception\InvalidRequestParameterException;
-use Piwik\Piwik;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Events\Segment;
use Piwik\Plugins\Events\Actions\ActionEvent;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -20,18 +20,21 @@ class EventCategory extends ActionDimension
{
protected $columnName = 'idaction_event_category';
protected $columnType = 'INTEGER(10) UNSIGNED DEFAULT NULL';
-
- protected function configureSegments()
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'Events_Events';
+ protected $sqlFilter = '\Piwik\Tracker\TableLogAction::getIdActionFromSegment';
+ protected $segmentName = 'eventCategory';
+ protected $nameSingular = 'Events_EventCategory';
+ protected $namePlural = 'Events_EventCategories';
+
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('eventCategory');
- $segment->setName('Events_EventCategory');
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('Events_EventCategory');
+ return new Discriminator('log_action', 'type', $this->getActionId());
}
public function getActionId()
diff --git a/plugins/Events/Columns/EventName.php b/plugins/Events/Columns/EventName.php
index bbe01ae0ff..71876dfc28 100644
--- a/plugins/Events/Columns/EventName.php
+++ b/plugins/Events/Columns/EventName.php
@@ -8,9 +8,9 @@
*/
namespace Piwik\Plugins\Events\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\Join\ActionNameJoin;
use Piwik\Plugin\Dimension\ActionDimension;
-use Piwik\Plugins\Events\Segment;
use Piwik\Plugins\Events\Actions\ActionEvent;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -18,18 +18,21 @@ use Piwik\Tracker\Request;
class EventName extends ActionDimension
{
protected $columnName = 'idaction_name';
-
- protected function configureSegments()
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'Events_Events';
+ protected $sqlFilter = '\Piwik\Tracker\TableLogAction::getIdActionFromSegment';
+ protected $segmentName = 'eventName';
+ protected $nameSingular = 'Events_EventName';
+ protected $namePlural = 'Events_EventNames';
+
+ public function getDbColumnJoin()
{
- $segment = new Segment();
- $segment->setSegment('eventName');
- $segment->setName('Events_EventName');
- $this->addSegment($segment);
+ return new ActionNameJoin();
}
- public function getName()
+ public function getDbDiscriminator()
{
- return Piwik::translate('Events_EventName');
+ return new Discriminator('log_action', 'type', $this->getActionId());
}
public function getActionId()
diff --git a/plugins/Events/Columns/EventValue.php b/plugins/Events/Columns/EventValue.php
new file mode 100644
index 0000000000..1a174553a0
--- /dev/null
+++ b/plugins/Events/Columns/EventValue.php
@@ -0,0 +1,56 @@
+<?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\Events\Columns;
+
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\Discriminator;
+use Piwik\Columns\MetricsList;
+use Piwik\Piwik;
+use Piwik\Plugin\ArchivedMetric;
+use Piwik\Plugin\ComputedMetric;
+use Piwik\Plugin\Dimension\ActionDimension;
+use Piwik\Tracker\Action;
+
+class EventValue extends ActionDimension
+{
+ protected $nameSingular = 'Events_EventValue';
+ protected $columnName = 'custom_float';
+ protected $category = 'Events_Events';
+ protected $type = self::TYPE_FLOAT;
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator('log_action', 'type', Action::TYPE_EVENT);
+ }
+
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ $metric1 = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_SUM);
+ $metricsList->addMetric($metric1);
+
+ $metric2 = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_MAX);
+ $metric2->setDocumentation(Piwik::translate('Events_MaxValueDocumentation'));
+ $metricsList->addMetric($metric2);
+
+ $metric4 = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_MIN);
+ $metric4->setDocumentation(Piwik::translate('Events_MinValueDocumentation'));
+ $metricsList->addMetric($metric4);
+
+ $metric3 = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_COUNT_WITH_NUMERIC_VALUE);
+ $metric3->setName('events_with_event_value');
+ $metric3->setTranslatedName(Piwik::translate('Events_EventsWithValue'));
+ $metric3->setDocumentation(Piwik::translate('Events_EventsWithValueDocumentation'));
+ $metricsList->addMetric($metric3);
+
+ $metric = $dimensionMetricFactory->createComputedMetric($metric1->getName(), $metric3->getName(), ComputedMetric::AGGREGATION_AVG);
+ $metric->setName('avg_event_value');
+ $metric->setTranslatedName(Piwik::translate('Events_AvgValue'));
+ $metricsList->addMetric($metric);
+ }
+}
diff --git a/plugins/Events/Columns/TotalEvents.php b/plugins/Events/Columns/TotalEvents.php
index 410144e3a9..f96392c194 100644
--- a/plugins/Events/Columns/TotalEvents.php
+++ b/plugins/Events/Columns/TotalEvents.php
@@ -8,9 +8,7 @@
*/
namespace Piwik\Plugins\Events\Columns;
-use Piwik\Piwik;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugin\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -19,22 +17,11 @@ class TotalEvents extends VisitDimension
{
protected $columnName = 'visit_total_events';
protected $columnType = 'INT(11) UNSIGNED NULL';
+ protected $segmentName = 'events';
+ protected $nameSingular = 'Events_TotalEvents';
+ protected $acceptValues = 'To select all visits who triggered an Event, use: &segment=events>0';
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('events');
- $segment->setName('Events_TotalEvents');
- $segment->setAcceptedValues('To select all visits who triggered an Event, use: &segment=events>0');
- $segment->setCategory('General_Visit');
- $segment->setType(Segment::TYPE_METRIC);
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('Events_EventName');
- }
+ protected $type = self::TYPE_NUMBER;
/**
* @param Request $request
diff --git a/plugins/Events/Segment.php b/plugins/Events/Segment.php
deleted file mode 100644
index aa586e3987..0000000000
--- a/plugins/Events/Segment.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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\Events;
-
-/**
- * Events segment base class.
- *
- */
-class Segment extends \Piwik\Plugin\Segment
-{
- protected function init()
- {
- $this->setCategory('Events_Events');
- $this->setSqlFilter('\Piwik\Tracker\TableLogAction::getIdActionFromSegment');
- }
-}
diff --git a/plugins/ExampleTracker/Columns/ExampleActionDimension.php b/plugins/ExampleTracker/Columns/ExampleActionDimension.php
index b0ce98f7c9..3710659d6d 100644
--- a/plugins/ExampleTracker/Columns/ExampleActionDimension.php
+++ b/plugins/ExampleTracker/Columns/ExampleActionDimension.php
@@ -27,6 +27,12 @@ use Piwik\Tracker\Action;
class ExampleActionDimension extends ActionDimension
{
/**
+ * The name of the dimension which will be visible for instance in the UI of a related report and in the mobile app.
+ * @return string
+ */
+ protected $nameSingular = 'ExampleTracker_DimensionName';
+
+ /**
* This will be the name of the column in the log_link_visit_action table if a $columnType is specified.
* @var string
*/
@@ -41,28 +47,21 @@ class ExampleActionDimension extends ActionDimension
protected $columnType = 'VARCHAR(255) DEFAULT NULL';
/**
- * The name of the dimension which will be visible for instance in the UI of a related report and in the mobile app.
- * @return string
+ * The type of the dimension is automatically detected by the columnType. If the type of the dimension is not
+ * detected correctly, you may want to adjust the type manually. The configured type will affect how the dimension
+ * is formatted in the UI.
+ * @var string
*/
- public function getName()
- {
- return Piwik::translate('ExampleTracker_DimensionName');
- }
+ // protected $type = self::TYPE_TEXT;
/**
- * By defining one or multiple segments a user will be able to filter their visitors by this column. For instance
+ * By defining a segment a user will be able to filter their visitors by this column. For instance
* show all actions only considering users having more than 10 achievement points. If you do not want to define a
- * segment for this dimension just remove the column.
+ * segment for this dimension, simply leave the name empty.
*/
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('keywords');
- $segment->setCategory('General_Actions');
- $segment->setName('ExampleTracker_DimensionName');
- $segment->setAcceptedValues('Here you should explain which values are accepted/useful: Any word, for instance MyKeyword1, MyKeyword2');
- $this->addSegment($segment);
- }
+ protected $segmentName = 'keywords';
+
+ protected $acceptValues = 'Here you should explain which values are accepted/useful for segments: Any word, for instance MyKeyword1, MyKeyword2';
/**
* This event is triggered before a new action is logged to the log_link_visit_action table. It overwrites any
diff --git a/plugins/ExampleTracker/Columns/ExampleConversionDimension.php b/plugins/ExampleTracker/Columns/ExampleConversionDimension.php
index 6b6bf3d51f..752104c1c8 100644
--- a/plugins/ExampleTracker/Columns/ExampleConversionDimension.php
+++ b/plugins/ExampleTracker/Columns/ExampleConversionDimension.php
@@ -43,28 +43,27 @@ class ExampleConversionDimension extends ConversionDimension
protected $columnType = 'INTEGER(11) DEFAULT 0 NULL';
/**
+ * The type of the dimension is automatically detected by the columnType. If the type of the dimension is not
+ * detected correctly, you may want to adjust the type manually. The configured type will affect how the dimension
+ * is formatted in the UI.
+ * @var string
+ */
+ // protected $type = self::TYPE_NUMBER;
+
+ /**
* The name of the dimension which will be visible for instance in the UI of a related report and in the mobile app.
* @return string
*/
- public function getName()
- {
- return Piwik::translate('ExampleTracker_DimensionName');
- }
+ protected $nameSingular = 'ExampleTracker_DimensionName';
/**
- * By defining one or multiple segments a user will be able to filter their visitors by this column. For instance
+ * By defining a segment a user will be able to filter their visitors by this column. For instance
* show all reports only considering users having more than 10 achievement points. If you do not want to define a
- * segment for this dimension just remove the column.
+ * segment for this dimension, simply leave the name empty.
*/
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('myConversionSegmentName');
- $segment->setCategory('General_Visit');
- $segment->setName('ExampleTracker_DimensionName');
- $segment->setAcceptedValues('Here you should explain which values are accepted/useful: Any number, for instance 1, 2, 3 , 99');
- $this->addSegment($segment);
- }
+ protected $segmentName = 'myConversionSegmentName';
+
+ protected $acceptValues = 'Here you should explain which values are accepted/useful for segments: Any number, for instance 1, 2, 3 , 99';
/**
* This event is triggered when an ecommerce order is converted. In this example we would store a "0" in case it
diff --git a/plugins/ExampleTracker/Columns/ExampleDimension.php b/plugins/ExampleTracker/Columns/ExampleDimension.php
index 738d0be9e1..25e48bb306 100644
--- a/plugins/ExampleTracker/Columns/ExampleDimension.php
+++ b/plugins/ExampleTracker/Columns/ExampleDimension.php
@@ -23,8 +23,6 @@ class ExampleDimension extends Dimension
* The name of the dimension which will be visible for instance in the UI of a related report and in the mobile app.
* @return string
*/
- public function getName()
- {
- return Piwik::translate('ExampleTracker_DimensionName');
- }
+ protected $nameSingular = 'ExampleTracker_DimensionName';
+
} \ No newline at end of file
diff --git a/plugins/ExampleTracker/Columns/ExampleVisitDimension.php b/plugins/ExampleTracker/Columns/ExampleVisitDimension.php
index 15d32592a6..0997a18ee7 100644
--- a/plugins/ExampleTracker/Columns/ExampleVisitDimension.php
+++ b/plugins/ExampleTracker/Columns/ExampleVisitDimension.php
@@ -41,28 +41,27 @@ class ExampleVisitDimension extends VisitDimension
protected $columnType = 'INTEGER(11) DEFAULT 0 NULL';
/**
+ * The type of the dimension is automatically detected by the columnType. If the type of the dimension is not
+ * detected correctly, you may want to adjust the type manually. The configured type will affect how the dimension
+ * is formatted in the UI.
+ * @var string
+ */
+ // protected $type = self::TYPE_NUMBER;
+
+ /**
* The name of the dimension which will be visible for instance in the UI of a related report and in the mobile app.
* @return string
*/
- public function getName()
- {
- return Piwik::translate('ExampleTracker_DimensionName');
- }
+ protected $nameSingular = 'ExampleTracker_DimensionName';
/**
- * By defining one or multiple segments a user will be able to filter their visitors by this column. For instance
+ * By defining a segment a user will be able to filter their visitors by this column. For instance
* show all reports only considering users having more than 10 achievement points. If you do not want to define a
- * segment for this dimension just remove the column.
+ * segment for this dimension, simply leave the name empty.
*/
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('achievementPoints');
- $segment->setCategory('General_Visit');
- $segment->setName('ExampleTracker_DimensionName');
- $segment->setAcceptedValues('Here you should explain which values are accepted/useful: Any number, for instance 1, 2, 3 , 99');
- $this->addSegment($segment);
- }
+ protected $segmentName = 'achievementPoints';
+
+ protected $acceptValues = 'Here you should explain which values are accepted/useful for segments: Any number, for instance 1, 2, 3 , 99';
/**
* The onNewVisit method is triggered when a new visitor is detected. This means here you can define an initial
diff --git a/plugins/Goals/Columns/DaysToConversion.php b/plugins/Goals/Columns/DaysToConversion.php
index e1bd941d6b..576babb8d7 100644
--- a/plugins/Goals/Columns/DaysToConversion.php
+++ b/plugins/Goals/Columns/DaysToConversion.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class DaysToConversion extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Goals_DaysToConv');
- }
+ protected $type = self::TYPE_NUMBER;
+ protected $nameSingular = 'Goals_DaysToConv';
} \ No newline at end of file
diff --git a/plugins/Goals/Columns/IdGoal.php b/plugins/Goals/Columns/IdGoal.php
index 2243dbdb1f..a8ca5ac5b6 100644
--- a/plugins/Goals/Columns/IdGoal.php
+++ b/plugins/Goals/Columns/IdGoal.php
@@ -8,26 +8,27 @@
*/
namespace Piwik\Plugins\Goals\Columns;
-use Piwik\Piwik;
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\Join;
+use Piwik\Columns\MetricsList;
use Piwik\Plugin\Dimension\ConversionDimension;
-use Piwik\Plugin\Segment;
class IdGoal extends ConversionDimension
{
protected $columnName = 'idgoal';
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'General_Visitors'; // todo move into goal category?
+ protected $nameSingular = 'General_VisitConvertedGoalId';
+ protected $segmentName = 'visitConvertedGoalId';
+ protected $acceptValues = '1, 2, 3, etc.';
- protected function configureSegments()
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
{
- $segment = new Segment();
- $segment->setCategory('General_Visit');
- $segment->setName('General_VisitConvertedGoalId');
- $segment->setSegment('visitConvertedGoalId');
- $segment->setAcceptedValues('1, 2, 3, etc.');
- $this->addSegment($segment);
+ // do not create any metrics for this dimension, they don't really make much sense and are rather confusing
}
- public function getName()
+ public function getDbColumnJoin()
{
- return Piwik::translate('General_VisitConvertedGoalId');
+ return new Join\GoalNameJoin();
}
} \ No newline at end of file
diff --git a/plugins/Goals/Columns/Revenue.php b/plugins/Goals/Columns/Revenue.php
new file mode 100644
index 0000000000..d18af2eda9
--- /dev/null
+++ b/plugins/Goals/Columns/Revenue.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals\Columns;
+
+use Piwik\Plugin\Dimension\ConversionDimension;
+
+class Revenue extends ConversionDimension
+{
+ protected $columnName = 'revenue';
+ protected $type = self::TYPE_MONEY;
+ protected $category = 'Goals_Goals';
+ protected $nameSingular = 'Goals_ColumnOverallRevenue';
+
+} \ No newline at end of file
diff --git a/plugins/Goals/Columns/VisitsUntilConversion.php b/plugins/Goals/Columns/VisitsUntilConversion.php
index 13f54e9dd7..05c988a479 100644
--- a/plugins/Goals/Columns/VisitsUntilConversion.php
+++ b/plugins/Goals/Columns/VisitsUntilConversion.php
@@ -13,8 +13,7 @@ use Piwik\Piwik;
class VisitsUntilConversion extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Goals_VisitsUntilConv');
- }
+ protected $type = self::TYPE_NUMBER;
+ protected $nameSingular = 'Goals_VisitsUntilConv';
+
} \ No newline at end of file
diff --git a/plugins/Goals/GoalDimension.php b/plugins/Goals/GoalDimension.php
new file mode 100644
index 0000000000..91cbde16df
--- /dev/null
+++ b/plugins/Goals/GoalDimension.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Goals;
+
+use Piwik\Columns\Dimension;
+use Piwik\Columns\Discriminator;
+
+class GoalDimension extends Dimension
+{
+ protected $type = self::TYPE_TEXT;
+ private $goal;
+ private $id;
+
+ public function __construct($goal, $column, $name)
+ {
+ $this->goal = $goal;
+ $this->category = 'Goals_Goals';
+ $this->dbTableName = 'log_conversion';
+ $this->columnName = $column;
+ $this->nameSingular = $name;
+
+ $this->id = 'Goals.Goal' . ucfirst($column) . $goal['idgoal'];
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getDbDiscriminator()
+ {
+ return new Discriminator('log_conversion', 'idgoal', $this->goal['idgoal']);
+ }
+
+} \ No newline at end of file
diff --git a/plugins/Goals/Goals.php b/plugins/Goals/Goals.php
index 0700d8aa75..b1d10e16f3 100644
--- a/plugins/Goals/Goals.php
+++ b/plugins/Goals/Goals.php
@@ -8,8 +8,13 @@
*/
namespace Piwik\Plugins\Goals;
+use Piwik\Columns\ComputedMetricFactory;
+use Piwik\Columns\Dimension;
+use Piwik\Columns\MetricsList;
use Piwik\Common;
use Piwik\Piwik;
+use Piwik\Plugin\ArchivedMetric;
+use Piwik\Plugin\ComputedMetric;
use Piwik\Plugin\ReportsProvider;
use Piwik\Tracker\GoalManager;
use Piwik\Category\Subcategory;
@@ -77,11 +82,74 @@ class Goals extends \Piwik\Plugin
'SitesManager.deleteSite.end' => 'deleteSiteGoals',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
'Metrics.getDefaultMetricTranslations' => 'addMetricTranslations',
- 'Category.addSubcategories' => 'addSubcategories'
+ 'Category.addSubcategories' => 'addSubcategories',
+ 'Metric.addMetrics' => 'addMetrics',
+ 'Metric.addComputedMetrics' => 'addComputedMetrics'
);
return $hooks;
}
+ public function addComputedMetrics(MetricsList $list, ComputedMetricFactory $computedMetricFactory)
+ {
+ $idSite = Common::getRequestVar('idSite', 0, 'int');
+ $goals = API::getInstance()->getGoals($idSite);
+
+ foreach ($goals as $goal) {
+ $metric = $computedMetricFactory->createComputedMetric('goal_' . $goal['idgoal'] . '_conversion', 'nb_uniq_visitors', ComputedMetric::AGGREGATION_RATE);
+ $goalName = Piwik::translate('Goals_GoalX', $goal['name']);
+ $metricName = Piwik::translate('Goals_ConversionRate', $goalName);
+ $metric->setTranslatedName($metricName);
+ $list->addMetric($metric);
+ }
+ }
+
+ public function addMetrics(MetricsList $metricsList)
+ {
+ $idSite = Common::getRequestVar('idSite', 0, 'int');
+ $goals = API::getInstance()->getGoals($idSite);
+
+ foreach ($goals as $goal) {
+ $custom = new GoalDimension($goal, 'idgoal', 'Conversions goal "' . $goal['name'] . '" (ID ' . $goal['idgoal'] .' )');
+ $custom->setType(Dimension::TYPE_NUMBER);
+ $custom->setSqlSegment('count(distinct log_conversion.idvisit, log_conversion.buster)');
+
+ $metric = new ArchivedMetric($custom, ArchivedMetric::AGGREGATION_SUM);
+ $metric->setQuery('count(distinct log_conversion.idvisit, log_conversion.buster)');
+ $metric->setTranslatedName($custom->getName());
+ $metric->setDocumentation('The number of times this goal was converted.');
+ $metric->setCategory($custom->getCategoryId());
+ $metric->setName('goal_' . $goal['idgoal'] . '_conversion');
+ $metricsList->addMetric($metric);
+
+ $custom = new GoalDimension($goal, 'revenue', 'Revenue goal "' . $goal['name'] . '" (ID ' . $goal['idgoal'] .' )');
+ $custom->setType(Dimension::TYPE_MONEY);
+ $metric = new ArchivedMetric($custom, ArchivedMetric::AGGREGATION_SUM);
+ $metric->setTranslatedName($custom->getName());
+ $metric->setName('goal_' . $goal['idgoal'] . '_revenue');
+ $metric->setDocumentation('The amount of revenue that was generated by converting this goal.');
+ $metric->setCategory($custom->getCategoryId());
+ $metricsList->addMetric($metric);
+
+ $custom = new GoalDimension($goal, 'visitor_days_since_first', 'Days to conversion goal "' . $goal['name'] . '" (ID ' . $goal['idgoal'] .' )');
+ $custom->setType(Dimension::TYPE_NUMBER);
+ $metric = new ArchivedMetric($custom, ArchivedMetric::AGGREGATION_SUM);
+ $metric->setTranslatedName($custom->getName());
+ $metric->setCategory($custom->getCategoryId());
+ $metric->setDocumentation('The number of days it took a visitor to convert this goal.');
+ $metric->setName('goal_' . $goal['idgoal'] . '_daystoconversion');
+ $metricsList->addMetric($metric);
+
+ $custom = new GoalDimension($goal, 'visitor_count_visits', 'Visits to conversion goal "' . $goal['name'] . '" (ID ' . $goal['idgoal'] .' )');
+ $custom->setType(Dimension::TYPE_NUMBER);
+ $metric = new ArchivedMetric($custom, ArchivedMetric::AGGREGATION_SUM);
+ $metric->setTranslatedName($custom->getName());
+ $metric->setCategory($custom->getCategoryId());
+ $metric->setDocumentation('The number of visits it took a visitor to convert this goal.');
+ $metric->setName('goal_' . $goal['idgoal'] . '_visitstoconversion');
+ $metricsList->addMetric($metric);
+ }
+ }
+
public function addSubcategories(&$subcategories)
{
$idSite = Common::getRequestVar('idSite', 0, 'int');
@@ -108,7 +176,6 @@ class Goals extends \Piwik\Plugin
}
}
-
public function addMetricTranslations(&$translations)
{
$metrics = array(
diff --git a/plugins/Goals/lang/en.json b/plugins/Goals/lang/en.json
index d78a22a276..3b72998105 100644
--- a/plugins/Goals/lang/en.json
+++ b/plugins/Goals/lang/en.json
@@ -24,6 +24,7 @@
"ColumnConversionRateDocumentation": "The percentage of visits that triggered the goal %s.",
"ColumnConversionRateProductDocumentation": "The %s conversion rate is the number of orders containing this product divided by number of visits on the product page.",
"ColumnConversions": "Conversions",
+ "Conversion": "Conversion",
"ColumnConversionsDocumentation": "The number of conversions for %s.",
"ColumnOrdersDocumentation": "The total number of Ecommerce orders which contained this %s at least once.",
"ColumnPurchasedProductsDocumentation": "The number of purchased products is the sum of Product quantities sold in all Ecommerce orders.",
@@ -81,14 +82,19 @@
"NeedAccess": "Only an Administrator or a user with Super User access can manage Goals for a given website.",
"Optional": "(optional)",
"OverallConversionRate": "overall conversion rate (visits with a completed goal)",
+ "ColumnOverallRevenue": "Overall revenue",
"OverallRevenue": "overall revenue",
"PageTitle": "Page Title",
"Pattern": "Pattern",
"PluginDescription": "Create Goals and see detailed reports about your goal conversions: evolution over time, revenue per visit, conversions per referrer, per keyword, and more.",
"ProductCategory": "Product Category",
"ProductName": "Product Name",
+ "ProductNames": "Product Names",
+ "ProductPrice": "Product Price",
+ "ProductQuantity": "Product Quantity",
"Products": "Products",
"ProductSKU": "Product SKU",
+ "ProductSKUs": "Product SKUs",
"ReturningVisitorsConversionRateIs": "Returning visitors conversion rate is %s",
"SingleGoalOverviewDocumentation": "This is an overview of the conversions for a single goal. %s The sparklines below the graph can be enlarged by clicking on them.",
"ThereIsNoGoalToManage": "There is no goal to manage for website %s",
diff --git a/plugins/Morpheus/stylesheets/main.less b/plugins/Morpheus/stylesheets/main.less
index 1eaf784455..cbf86d85cd 100644
--- a/plugins/Morpheus/stylesheets/main.less
+++ b/plugins/Morpheus/stylesheets/main.less
@@ -401,10 +401,28 @@ table.dataTable {
background-color: @color-silver-l95;
}
+ // for third level tables
+ td.cellSubDataTable {
+ table {
+ table {
+ tr td {
+ background: @theme-color-background-contrast !important;
+ }
+ tr:hover td {
+ background: @theme-color-background-contrast !important;
+
+ &:not(.cellSubDataTable) {
+ background-color: @color-silver-l95 !important;
+ }
+ }
+ }
+ }
+ }
+
.cellSubDataTable td {
background: @theme-color-background-contrast;
}
- .cellSubDataTable tr:hover td {
+ .cellSubDataTable tr:hover td:not(.cellSubDataTable) {
background-color: @theme-color-background-base;
}
}
diff --git a/plugins/Morpheus/stylesheets/ui/_components.less b/plugins/Morpheus/stylesheets/ui/_components.less
index 675f4a87f6..3508938b71 100644
--- a/plugins/Morpheus/stylesheets/ui/_components.less
+++ b/plugins/Morpheus/stylesheets/ui/_components.less
@@ -81,32 +81,6 @@
}
}
}
- .segment-nav {
- div > ul > li {
- padding: 5px 0;
- a {
- font-weight: normal;
- color: #333333;
- text-shadow: none;
- }
- li {
- padding: 3px 0;
- &:hover {
- background: @theme-color-background-tinyContrast;
- border: 0;
- padding: 4px 0 3px;
-
- a {
- border: 0;
- background-color: @theme-color-background-tinyContrast;
- padding-right: 15px;
-
- }
- }
- }
-
- }
- }
.segment-top {
.font-default(10px, 12px);
diff --git a/plugins/Morpheus/templates/demo.twig b/plugins/Morpheus/templates/demo.twig
index 84d6a2fec4..5c2fdae95a 100644
--- a/plugins/Morpheus/templates/demo.twig
+++ b/plugins/Morpheus/templates/demo.twig
@@ -337,6 +337,14 @@
options='{1: "0123456789",2:"9876543210",3:"5432109876"}'>
</div>
+ <div piwik-field uicontrol="expandable-select" name="selectexpand"
+ title="{{ "{{ view.selectedExpand ? view.selectedExpand : 'Select word' }}"|raw }}"
+ value="Select value"
+ inline-help="Expandable select"
+ ng-model="view.selectedExpand"
+ options='[{group: "Group 1",key:"1",value:"Hello"}, {group: "Group 1",key:"2",value:"How",tooltip: "Help text"}, {group: "Group 1",key:"3",value:"Are"}, {group: "Group 2",key:"4",value:"You"}]'>
+ </div>
+
<div piwik-field uicontrol="checkbox" name="enableFeature"
title="Enable feature"
introduction="Radio and checkboxes"
@@ -441,6 +449,14 @@
options='{1: &quot;0123456789&quot;,2:&quot;9876543210&quot;,3:&quot;5432109876&quot;}'&gt;
&lt;/div&gt;
+ &lt;div piwik-field uicontrol=&quot;expandable-select&quot; name=&quot;selectexpand&quot;
+ title=&quot;{{ "{{ view.selectedExpand ? view.selectedExpand : 'Select word' }}"|raw }}&quot;
+ value=&quot;Select value&quot;
+ inline-help=&quot;Expandable select&quot;
+ ng-model=&quot;view.selectedExpand&quot;
+ options='[{group: &quot;Group 1&quot;,key:&quot;1&quot;,value:&quot;Hello&quot;}, {group: &quot;Group 1&quot;,key:&quot;2&quot;,value:&quot;How&quot;,tooltip: &quot;Help text&quot;}, {group: &quot;Group 1&quot;,key:&quot;3&quot;,value:&quot;Are&quot;}, {group: &quot;Group 2&quot;,key:&quot;4&quot;,value:&quot;You&quot;}]'&gt;
+ &lt;/div&gt;
+
&lt;div piwik-field uicontrol=&quot;checkbox&quot; name=&quot;enableFeature&quot;
title=&quot;Enable feature&quot;
introduction=&quot;Radio and checkboxes&quot;
diff --git a/plugins/Provider/Columns/Provider.php b/plugins/Provider/Columns/Provider.php
index b7ca57e9c9..111bd84aa1 100644
--- a/plugins/Provider/Columns/Provider.php
+++ b/plugins/Provider/Columns/Provider.php
@@ -11,9 +11,7 @@ namespace Piwik\Plugins\Provider\Columns;
use Piwik\Common;
use Piwik\Network\IP;
use Piwik\Network\IPUtils;
-use Piwik\Piwik;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugin\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -23,16 +21,12 @@ use Piwik\Plugins\Provider\Provider as ProviderPlugin;
class Provider extends VisitDimension
{
protected $columnName = 'location_provider';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('provider');
- $segment->setCategory('Visit Location');
- $segment->setName('Provider_ColumnProvider');
- $segment->setAcceptedValues('comcast.net, proxad.net, etc.');
- $this->addSegment($segment);
- }
+ protected $segmentName = 'provider';
+ protected $category = 'UserCountry_VisitLocation';
+ protected $nameSingular = 'Provider_ColumnProvider';
+ protected $namePlural = 'Provider_WidgetProviders';
+ protected $acceptValues = 'comcast.net, proxad.net, etc.';
+ protected $type = self::TYPE_TEXT;
/**
* @param Request $request
@@ -99,9 +93,4 @@ class Provider extends VisitDimension
return trim(strtolower($host));
}
-
- public function getName()
- {
- return Piwik::translate('Provider_ColumnProvider');
- }
} \ No newline at end of file
diff --git a/plugins/Referrers/Columns/Campaign.php b/plugins/Referrers/Columns/Campaign.php
index be42acb34b..158876a7ef 100644
--- a/plugins/Referrers/Columns/Campaign.php
+++ b/plugins/Referrers/Columns/Campaign.php
@@ -24,17 +24,13 @@ class Campaign extends Base
* @var bool
*/
protected $createNewVisitWhenCampaignChanges;
+ protected $nameSingular = 'Referrers_ColumnCampaign';
public function __construct()
{
$this->createNewVisitWhenCampaignChanges = TrackerConfig::getConfigValue('create_new_visit_when_campaign_changes') == 1;
}
- public function getName()
- {
- return Piwik::translate('Referrers_ColumnCampaign');
- }
-
/**
* If we should create a new visit when the campaign changes, check if the campaign info changed and if so
* force the tracker to create a new visit.i
diff --git a/plugins/Referrers/Columns/Keyword.php b/plugins/Referrers/Columns/Keyword.php
index 7c927d6492..e496740c66 100644
--- a/plugins/Referrers/Columns/Keyword.php
+++ b/plugins/Referrers/Columns/Keyword.php
@@ -9,8 +9,6 @@
namespace Piwik\Plugins\Referrers\Columns;
use Piwik\Common;
-use Piwik\Piwik;
-use Piwik\Plugins\Referrers\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -19,20 +17,12 @@ class Keyword extends Base
{
protected $columnName = 'referer_keyword';
protected $columnType = 'VARCHAR(255) NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('referrerKeyword');
- $segment->setName('General_ColumnKeyword');
- $segment->setAcceptedValues('Encoded%20Keyword, keyword');
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('General_ColumnKeyword');
- }
+ protected $nameSingular = 'General_ColumnKeyword';
+ protected $namePlural = 'Referrers_Keywords';
+ protected $segmentName = 'referrerKeyword';
+ protected $acceptValues = 'Encoded%20Keyword, keyword';
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'Referrers_Referrers';
/**
* @param Request $request
diff --git a/plugins/Referrers/Columns/Referrer.php b/plugins/Referrers/Columns/Referrer.php
index 5d1daf16ba..e8afa1a1ac 100644
--- a/plugins/Referrers/Columns/Referrer.php
+++ b/plugins/Referrers/Columns/Referrer.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class Referrer extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Referrers_Referrer');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'Referrers_Referrer';
} \ No newline at end of file
diff --git a/plugins/Referrers/Columns/ReferrerName.php b/plugins/Referrers/Columns/ReferrerName.php
index ef21e7a277..f5989ecaf7 100644
--- a/plugins/Referrers/Columns/ReferrerName.php
+++ b/plugins/Referrers/Columns/ReferrerName.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\Referrers\Columns;
use Piwik\Common;
-use Piwik\Plugins\Referrers\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -18,15 +17,13 @@ class ReferrerName extends Base
{
protected $columnName = 'referer_name';
protected $columnType = 'VARCHAR(70) NULL';
+ protected $type = self::TYPE_TEXT;
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('referrerName');
- $segment->setName('Referrers_ReferrerName');
- $segment->setAcceptedValues('twitter.com, www.facebook.com, Bing, Google, Yahoo, CampaignName');
- $this->addSegment($segment);
- }
+ protected $nameSingular = 'Referrers_ReferrerName';
+ protected $namePlural = 'Referrers_ReferrerNames';
+ protected $segmentName = 'referrerName';
+ protected $acceptValues = 'twitter.com, www.facebook.com, Bing, Google, Yahoo, CampaignName';
+ protected $category = 'Referrers_Referrers';
/**
* @param Request $request
diff --git a/plugins/Referrers/Columns/ReferrerType.php b/plugins/Referrers/Columns/ReferrerType.php
index ef3a66325c..e348d323c2 100644
--- a/plugins/Referrers/Columns/ReferrerType.php
+++ b/plugins/Referrers/Columns/ReferrerType.php
@@ -8,8 +8,8 @@
*/
namespace Piwik\Plugins\Referrers\Columns;
-use Piwik\Piwik;
-use Piwik\Plugins\Referrers\Segment;
+use Piwik\Common;
+use Piwik\Metrics\Formatter;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -18,20 +18,27 @@ class ReferrerType extends Base
{
protected $columnName = 'referer_type';
protected $columnType = 'TINYINT(1) UNSIGNED NULL';
+ protected $type = self::TYPE_ENUM;
+ protected $segmentName = 'referrerType';
+ protected $nameSingular = 'Referrers_Type';
+ protected $namePlural = 'Referrers_ReferrerTypes';
+ protected $sqlFilterValue = 'Piwik\Plugins\Referrers\getReferrerTypeFromShortName';
+ protected $acceptValues = 'direct, search, website, campaign';
+ protected $category = 'Referrers_Referrers';
- protected function configureSegments()
+ public function formatValue($value, $idSite, Formatter $formatter)
{
- $segment = new Segment();
- $segment->setSegment('referrerType');
- $segment->setName('Referrers_Type');
- $segment->setSqlFilterValue('Piwik\Plugins\Referrers\getReferrerTypeFromShortName');
- $segment->setAcceptedValues('direct, search, website, campaign');
- $this->addSegment($segment);
+ return \Piwik\Plugins\Referrers\getReferrerTypeLabel($value);
}
- public function getName()
+ public function getEnumColumnValues()
{
- return Piwik::translate('Referrers_Type');
+ return array(
+ Common::REFERRER_TYPE_DIRECT_ENTRY => 'direct',
+ Common::REFERRER_TYPE_WEBSITE => 'website',
+ Common::REFERRER_TYPE_SEARCH_ENGINE => 'search',
+ Common::REFERRER_TYPE_CAMPAIGN => 'campaign',
+ );
}
/**
diff --git a/plugins/Referrers/Columns/ReferrerUrl.php b/plugins/Referrers/Columns/ReferrerUrl.php
index e70f75c9ef..2e7aa0ba63 100644
--- a/plugins/Referrers/Columns/ReferrerUrl.php
+++ b/plugins/Referrers/Columns/ReferrerUrl.php
@@ -8,7 +8,6 @@
*/
namespace Piwik\Plugins\Referrers\Columns;
-use Piwik\Plugins\Referrers\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -17,15 +16,12 @@ class ReferrerUrl extends Base
{
protected $columnName = 'referer_url';
protected $columnType = 'TEXT NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('referrerUrl');
- $segment->setName('Live_Referrer_URL');
- $segment->setAcceptedValues('http%3A%2F%2Fwww.example.org%2Freferer-page.htm');
- $this->addSegment($segment);
- }
+ protected $type = self::TYPE_TEXT;
+ protected $segmentName = 'referrerUrl';
+ protected $nameSingular = 'Live_Referrer_URL';
+ protected $namePlural = 'Referrers_ReferrerURLs';
+ protected $category = 'Referrers_Referrers';
+ protected $acceptValues = 'http%3A%2F%2Fwww.example.org%2Freferer-page.htm';
/**
* @param Request $request
diff --git a/plugins/Referrers/Columns/SearchEngine.php b/plugins/Referrers/Columns/SearchEngine.php
index c314a801af..d72e169a9a 100644
--- a/plugins/Referrers/Columns/SearchEngine.php
+++ b/plugins/Referrers/Columns/SearchEngine.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class SearchEngine extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Referrers_ColumnSearchEngine');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'Referrers_ColumnSearchEngine';
} \ No newline at end of file
diff --git a/plugins/Referrers/Columns/SocialNetwork.php b/plugins/Referrers/Columns/SocialNetwork.php
index 66478d167f..6655a08e85 100644
--- a/plugins/Referrers/Columns/SocialNetwork.php
+++ b/plugins/Referrers/Columns/SocialNetwork.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class SocialNetwork extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Referrers_ColumnSocial');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'Referrers_ColumnSocial';
} \ No newline at end of file
diff --git a/plugins/Referrers/Columns/Website.php b/plugins/Referrers/Columns/Website.php
index 33484b6de1..80a9cbd10e 100644
--- a/plugins/Referrers/Columns/Website.php
+++ b/plugins/Referrers/Columns/Website.php
@@ -17,6 +17,9 @@ use Piwik\Tracker\Visitor;
class Website extends Base
{
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'General_Website';
+
/**
* Set using the `[Tracker] create_new_visit_when_website_referrer_changes` INI config option.
* If true, will force new visits if the referrer website changes.
@@ -30,11 +33,6 @@ class Website extends Base
$this->createNewVisitWhenWebsiteReferrerChanges = TrackerConfig::getConfigValue('create_new_visit_when_website_referrer_changes') == 1;
}
- public function getName()
- {
- return Piwik::translate('General_Website');
- }
-
public function shouldForceNewVisit(Request $request, Visitor $visitor, Action $action = null)
{
if (!$this->createNewVisitWhenWebsiteReferrerChanges) {
diff --git a/plugins/Referrers/Columns/WebsitePage.php b/plugins/Referrers/Columns/WebsitePage.php
index 963c83414b..0d3fea8e1b 100644
--- a/plugins/Referrers/Columns/WebsitePage.php
+++ b/plugins/Referrers/Columns/WebsitePage.php
@@ -13,8 +13,6 @@ use Piwik\Piwik;
class WebsitePage extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Referrers_ColumnWebsitePage');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $nameSingular = 'Referrers_ColumnWebsitePage';
} \ No newline at end of file
diff --git a/plugins/Referrers/Segment.php b/plugins/Referrers/Segment.php
deleted file mode 100644
index c51b4e8230..0000000000
--- a/plugins/Referrers/Segment.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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\Referrers;
-
-/**
- * Referrers segment base class.
- *
- */
-class Segment extends \Piwik\Plugin\Segment
-{
- protected function init()
- {
- $this->setCategory('Referrers_Referrers');
- }
-}
diff --git a/plugins/Referrers/functions.php b/plugins/Referrers/functions.php
index c91ebc816d..b38c3bb5f6 100644
--- a/plugins/Referrers/functions.php
+++ b/plugins/Referrers/functions.php
@@ -36,15 +36,19 @@ function getPathFromUrl($url)
function getReferrerTypeLabel($label)
{
switch ($label) {
+ case 'direct':
case Common::REFERRER_TYPE_DIRECT_ENTRY:
$indexTranslation = 'Referrers_DirectEntry';
break;
+ case 'search':
case Common::REFERRER_TYPE_SEARCH_ENGINE:
$indexTranslation = 'Referrers_SearchEngines';
break;
+ case 'website':
case Common::REFERRER_TYPE_WEBSITE:
$indexTranslation = 'Referrers_Websites';
break;
+ case 'campaign':
case Common::REFERRER_TYPE_CAMPAIGN:
$indexTranslation = 'Referrers_Campaigns';
break;
diff --git a/plugins/Referrers/lang/en.json b/plugins/Referrers/lang/en.json
index 7cfcb99281..d19cecfde0 100644
--- a/plugins/Referrers/lang/en.json
+++ b/plugins/Referrers/lang/en.json
@@ -23,9 +23,11 @@
"PluginDescription": "Reports the Referrers data: Search Engines, Keywords, Websites, Campaigns, Social media, Direct entry.",
"Referrer": "Referrer",
"ReferrerName": "Referrer Name",
+ "ReferrerNames": "Referrer Names",
"Referrers": "Referrers",
"ReferrersOverview": "Referrers Overview",
"ReferrerTypes": "Referrer Types",
+ "ReferrerURLs": "Referrer URLs",
"SearchEngines": "Search Engines",
"SearchEnginesDocumentation": "A visitor was referred to your website by a search engine. %1$s See the %2$s report for more details.",
"SearchEnginesReportDocumentation": "This report shows which search engines referred users to your website. %s By clicking on a row in the table, you can see what users were searching for using a specific search engine.",
diff --git a/plugins/Resolution/Columns/Configuration.php b/plugins/Resolution/Columns/Configuration.php
index 6929457495..22f2392897 100644
--- a/plugins/Resolution/Columns/Configuration.php
+++ b/plugins/Resolution/Columns/Configuration.php
@@ -13,8 +13,5 @@ use Piwik\Piwik;
class Configuration extends Dimension
{
- public function getName()
- {
- return Piwik::translate('Resolution_ColumnConfiguration');
- }
+ protected $nameSingular = 'Resolution_ColumnConfiguration';
} \ No newline at end of file
diff --git a/plugins/Resolution/Columns/Resolution.php b/plugins/Resolution/Columns/Resolution.php
index 53a5f8cc4d..b13ce11b31 100644
--- a/plugins/Resolution/Columns/Resolution.php
+++ b/plugins/Resolution/Columns/Resolution.php
@@ -10,7 +10,6 @@ namespace Piwik\Plugins\Resolution\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\Resolution\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -19,15 +18,11 @@ class Resolution extends VisitDimension
{
protected $columnName = 'config_resolution';
protected $columnType = 'VARCHAR(18) NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('resolution');
- $segment->setName('Resolution_ColumnResolution');
- $segment->setAcceptedValues('1280x1024, 800x600, etc.');
- $this->addSegment($segment);
- }
+ protected $acceptValues = '1280x1024, 800x600, etc.';
+ protected $segmentName = 'resolution';
+ protected $nameSingular = 'Resolution_ColumnResolution';
+ protected $namePlural = 'Resolution_Resolutions';
+ protected $type = self::TYPE_TEXT;
/**
* @param Request $request
@@ -46,8 +41,4 @@ class Resolution extends VisitDimension
return $resolution;
}
- public function getName()
- {
- return Piwik::translate('Resolution_ColumnResolution');
- }
} \ No newline at end of file
diff --git a/plugins/Resolution/Segment.php b/plugins/Resolution/Segment.php
deleted file mode 100644
index e21a2973d7..0000000000
--- a/plugins/Resolution/Segment.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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\Resolution;
-
-/**
- * Resolution segment base class.
- *
- */
-class Segment extends \Piwik\Plugin\Segment
-{
- protected function init()
- {
- $this->setCategory('General_Visit');
- }
-}
diff --git a/plugins/SegmentEditor/SegmentEditor.php b/plugins/SegmentEditor/SegmentEditor.php
index 63cee53c30..9af29e2194 100644
--- a/plugins/SegmentEditor/SegmentEditor.php
+++ b/plugins/SegmentEditor/SegmentEditor.php
@@ -79,11 +79,15 @@ class SegmentEditor extends \Piwik\Plugin
public function getJsFiles(&$jsFiles)
{
$jsFiles[] = "plugins/SegmentEditor/javascripts/Segmentation.js";
+ $jsFiles[] = "plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator-model.js";
+ $jsFiles[] = "plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.controller.js";
+ $jsFiles[] = "plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.js";
}
public function getStylesheetFiles(&$stylesheets)
{
$stylesheets[] = "plugins/SegmentEditor/stylesheets/segmentation.less";
+ $stylesheets[] = "plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.less";
}
/**
@@ -103,5 +107,20 @@ class SegmentEditor extends \Piwik\Plugin
$translationKeys[] = 'SegmentEditor_SharedWithYou';
$translationKeys[] = 'SegmentEditor_ChooseASegment';
$translationKeys[] = 'SegmentEditor_CurrentlySelectedSegment';
+ $translationKeys[] = 'SegmentEditor_OperatorAND';
+ $translationKeys[] = 'SegmentEditor_OperatorOR';
+ $translationKeys[] = 'SegmentEditor_AddANDorORCondition';
+ $translationKeys[] = 'General_OperationEquals';
+ $translationKeys[] = 'General_OperationNotEquals';
+ $translationKeys[] = 'General_OperationAtMost';
+ $translationKeys[] = 'General_OperationAtLeast';
+ $translationKeys[] = 'General_OperationLessThan';
+ $translationKeys[] = 'General_OperationGreaterThan';
+ $translationKeys[] = 'General_OperationIs';
+ $translationKeys[] = 'General_OperationIsNot';
+ $translationKeys[] = 'General_OperationContains';
+ $translationKeys[] = 'General_OperationDoesNotContain';
+ $translationKeys[] = 'General_OperationStartsWith';
+ $translationKeys[] = 'General_OperationEndsWith';
}
}
diff --git a/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator-model.js b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator-model.js
new file mode 100644
index 0000000000..113352c9d3
--- /dev/null
+++ b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator-model.js
@@ -0,0 +1,69 @@
+/*!
+ * 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('segmentGeneratorModel', segmentGeneratorModel);
+
+ segmentGeneratorModel.$inject = ['piwikApi', 'piwik'];
+
+ function segmentGeneratorModel(piwikApi, piwik) {
+
+ var initialSegments = null;
+ var limitPromise = null;
+ var fetchedSiteId = null;
+
+ var model = {
+ isLoading: false,
+ segments : [],
+ loadSegments: loadSegments
+ };
+
+ return model;
+
+ function loadSegments(siteId) {
+ if (model.isLoading) {
+ if (limitPromise) {
+ limitPromise.abort();
+ limitPromise = null;
+ }
+ }
+
+ model.isLoading = true;
+
+ // we need to clear last limit result because we now fetch different data
+ if (fetchedSiteId != siteId) {
+ limitPromise = null;
+ fetchedSiteId = siteId;
+ }
+
+ if (!limitPromise) {
+ var params = {method: 'API.getSegmentsMetadata',filter_limit: '-1'};
+
+ if (siteId === 'all' || !siteId) {
+ params.idSites = 'all';
+ params.idSite = 'all';
+ } else if (siteId) {
+ params.idSites = siteId;
+ params.idSite = siteId;
+ }
+
+ limitPromise = piwikApi.fetch(params);
+ }
+
+ return limitPromise.then(function (response) {
+ model.isLoading = false;
+
+ if (angular.isDefined(response)) {
+ model.segments = response;
+ }
+
+ return response;
+ }).finally(function () {
+ model.isLoading = false;
+ });
+ }
+ }
+})(); \ No newline at end of file
diff --git a/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.controller.js b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.controller.js
new file mode 100644
index 0000000000..21eed81367
--- /dev/null
+++ b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.controller.js
@@ -0,0 +1,319 @@
+/*!
+ * 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('SegmentGeneratorController', SegmentGeneratorController);
+
+ SegmentGeneratorController.$inject = ['$scope', 'piwik', 'piwikApi', 'segmentGeneratorModel', '$filter', '$timeout'];
+
+ var findAndExplodeByMatch = function(metric){
+ var matches = ["==" , "!=" , "<=", ">=", "=@" , "!@","<",">", "=^", "=$"];
+ var newMetric = {};
+ var minPos = metric.length;
+ var match, index;
+ var singleChar = false;
+
+ for (var key=0; key < matches.length; key++) {
+ match = matches[key];
+ index = metric.indexOf(match);
+ if(index !== -1){
+ if(index < minPos){
+ minPos = index;
+ if(match.length === 1){
+ singleChar = true;
+ }
+ }
+ }
+ }
+
+ if (minPos < metric.length) {
+ // sth found - explode
+ if(singleChar == true){
+ newMetric.segment = metric.substr(0,minPos);
+ newMetric.matches = metric.substr(minPos,1);
+ newMetric.value = metric.substr(minPos+1);
+ } else {
+ newMetric.segment = metric.substr(0,minPos);
+ newMetric.matches = metric.substr(minPos,2);
+ newMetric.value = metric.substr(minPos+2);
+ }
+ // if value is only "" -> change to empty string
+ if(newMetric.value === '""')
+ {
+ newMetric.value = "";
+ }
+ }
+
+ newMetric.value = decodeURIComponent(newMetric.value);
+ return newMetric;
+ };
+
+ function generateUniqueId() {
+ var id = '';
+ var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+
+ for (var i = 1; i <= 10; i++) {
+ id += chars.charAt(Math.floor(Math.random() * chars.length));
+ }
+
+ return id;
+ }
+
+ function stripTags(text) {
+ if (text) {
+ text = ('' + text).replace(/(<([^>]+)>)/ig,"");
+ }
+ return text;
+ }
+
+ function SegmentGeneratorController($scope, piwik, piwikApi, segmentGeneratorModel, $filter, $timeout) {
+ var translate = $filter('translate');
+
+ var self = this;
+ var firstSegment = '';
+ var firstMatch = '';
+ this.conditions = [];
+ this.model = segmentGeneratorModel;
+
+ this.segments = {};
+
+ this.matches = {
+ metric: [
+ {key: '==', value: translate('General_OperationEquals')},
+ {key: '!=', value: translate('General_OperationNotEquals')},
+ {key: '<=', value: translate('General_OperationAtMost')},
+ {key: '>=', value: translate('General_OperationAtLeast')},
+ {key: '<', value: translate('General_OperationLessThan')},
+ {key: '>', value: translate('General_OperationGreaterThan')}
+ ],
+ dimension: [
+ {key: '==', value: translate('General_OperationIs')},
+ {key: '!=', value: translate('General_OperationIsNot')},
+ {key: '=@', value: translate('General_OperationContains')},
+ {key: '!@', value: translate('General_OperationDoesNotContain')},
+ {key: '=^', value: translate('General_OperationStartsWith')},
+ {key: '=$', value: translate('General_OperationEndsWith')}
+ ],
+ };
+ this.matches[''] = this.matches.dimension;
+
+ this.andConditionLabel = '';
+
+ this.addNewAndCondition = function () {
+ var condition = {orConditions: []};
+
+ this.addAndCondition(condition);
+ this.addNewOrCondition(condition);
+
+ return condition;
+ };
+
+ this.addAndCondition = function (condition) {
+ this.andConditionLabel = translate('SegmentEditor_OperatorAND');
+ this.conditions.push(condition);
+ this.updateSegmentDefinition();
+ }
+
+ this.addNewOrCondition = function (condition) {
+ var orCondition = {
+ segment: firstSegment,
+ matches: firstMatch,
+ value: ''
+ };
+
+ this.addOrCondition(condition, orCondition);
+ };
+
+ this.addOrCondition = function (condition, orCondition) {
+ orCondition.isLoading = false;
+ orCondition.id = generateUniqueId();
+
+ condition.orConditions.push(orCondition);
+ this.updateSegmentDefinition();
+
+ $timeout(function () {
+ self.updateAutocomplete(orCondition);
+ });
+ };
+
+ this.updateAutocomplete = function (orCondition) {
+ orCondition.isLoading = true;
+
+ this.updateSegmentDefinition();
+
+ var resolved = false;
+
+ var promise = piwikApi.fetch({
+ module: 'API',
+ format: 'json',
+ method: 'API.getSuggestedValuesForSegment',
+ segmentName: orCondition.segment
+ }, {createErrorNotification: false})
+
+ promise.then(function(response) {
+ orCondition.isLoading = false;
+ resolved = true;
+
+ var inputElement = $('.orCondId' + orCondition.id + " .metricValueBlock input");
+
+ if (response && response.result != 'error') {
+
+ inputElement.autocomplete({
+ source: response,
+ minLength: 0,
+ select: function(event, ui){
+ event.preventDefault();
+ orCondition.value = ui.item.value;
+ self.updateSegmentDefinition();
+ $timeout(function () {
+ $scope.$apply();
+ });
+ }
+ });
+ }
+
+ inputElement.off('click');
+ inputElement.click(function (e) {
+ $(inputElement).autocomplete('search', orCondition.value);
+ });
+ }, function(response) {
+ resolved = true;
+ orCondition.isLoading = false;
+
+ var inputElement = $('.orCondId' + orCondition.id + " .metricValueBlock input");
+ inputElement.autocomplete({
+ source: [],
+ minLength: 0
+ });
+ $(inputElement).autocomplete('search', orCondition.value);
+ });
+
+ $timeout(function () {
+ if (!resolved) {
+ promise.abort();
+ }
+ }, 20000);
+ }
+
+ this.removeOrCondition = function (condition, orCondition) {
+ var index = condition.orConditions.indexOf(orCondition);
+ if (index > -1) {
+ condition.orConditions.splice(index, 1);
+ }
+
+ if (condition.orConditions.length === 0) {
+ var index = self.conditions.indexOf(condition);
+ if (index > -1) {
+ self.conditions.splice(index, 1);
+ }
+ if (self.conditions.length === 0) {
+ self.andConditionLabel = '';
+ }
+ }
+
+ this.updateSegmentDefinition();
+ };
+
+ this.getSegmentString = function () {
+ var segmentStr = '';
+
+ angular.forEach(this.conditions, function (conditions) {
+ var subSegmentStr = '';
+
+ angular.forEach(conditions.orConditions, function (orCondition){
+ if (subSegmentStr !== ''){
+ subSegmentStr += ","; // OR operator
+ }
+
+ subSegmentStr += orCondition.segment + orCondition.matches + encodeURIComponent(orCondition.value);
+ })
+
+ if (segmentStr !== '') {
+ segmentStr += ";"; // add AND operator between segment blocks
+ }
+
+ segmentStr += subSegmentStr;
+ });
+
+ return segmentStr
+ };
+
+ this.setSegmentString = function (segmentStr) {
+ var orCondition, condition;
+
+ this.conditions = [];
+
+ if (!segmentStr) {
+ return;
+ }
+
+ var blocks = segmentStr.split(';');
+
+ for (var key = 0; key < blocks.length; key++) {
+ var condition = {orConditions: []};
+ this.addAndCondition(condition);
+
+ blocks[key] = blocks[key].split(',');
+ for (var innerkey = 0; innerkey < blocks[key].length; innerkey++) {
+ orCondition = findAndExplodeByMatch(blocks[key][innerkey]);
+ this.addOrCondition(condition, orCondition);
+ }
+ }
+ };
+
+ this.updateSegmentDefinition = function () {
+ $scope.segmentDefinition = this.getSegmentString();
+ }
+
+ if ($scope.segmentDefinition) {
+ this.setSegmentString($scope.segmentDefinition);
+ }
+
+ $scope.$watch('idsite', function (newValue, oldValue) {
+ if (newValue != oldValue) {
+ reloadSegments(newValue);
+ }
+ });
+
+ reloadSegments($scope.idsite);
+
+ function reloadSegments(idsite) {
+ segmentGeneratorModel.loadSegments(idsite).then(function (segments) {
+
+ self.segmentList = [];
+
+ var groups = {};
+ angular.forEach(segments, function (segment) {
+ if (!segment.category) {
+ segment.category = 'Others';
+ }
+
+ if (!firstSegment) {
+ firstSegment = segment.segment;
+ if (segment.type && self.matches[segment.type]) {
+ firstMatch = self.matches[segment.type][0].key;
+ } else {
+ firstMatch = self.matches[''][0].key
+ }
+ }
+
+ self.segments[segment.segment] = segment;
+
+ var segmentData = {group: segment.category, key: segment.segment, value: segment.name};
+ if ('acceptedValues' in segment && segment.acceptedValues) {
+ segmentData.tooltip = stripTags(segment.acceptedValues);
+ }
+ self.segmentList.push(segmentData);
+ });
+
+ if ($scope.addInitialCondition && self.conditions.length === 0) {
+ self.addNewAndCondition();
+ }
+ });
+ }
+ }
+
+})();
diff --git a/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.html b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.html
new file mode 100644
index 0000000000..9fd8ab548f
--- /dev/null
+++ b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.html
@@ -0,0 +1,61 @@
+<div class="segment-generator">
+ <div piwik-activity-indicator loading="segmentGenerator.model.isLoading"></div>
+
+ <div ng-repeat="(conditionIndex,condition) in segmentGenerator.conditions" class="segmentRow{{conditionIndex}}">
+ <div class="segment-rows">
+ <div ng-repeat="orCondition in condition.orConditions" class="orCondId{{ orCondition.id }}">
+ <div class="segment-row">
+ <a ng-click="segmentGenerator.removeOrCondition(condition, orCondition)" class="segment-close"></a>
+ <a href="#" class="segment-loading" ng-show="orCondition.isLoading"></a>
+ <div class="segment-row-inputs valign-wrapper">
+ <div class="segment-input metricListBlock valign-wrapper">
+ <div piwik-field uicontrol="expandable-select" name="segments"
+ title="{{ segmentGenerator.segments[orCondition.segment].name }}"
+ full-width="true"
+ style="width: 100%;"
+ ng-change="segmentGenerator.updateAutocomplete(orCondition)"
+ ng-model="orCondition.segment"
+ options="segmentGenerator.segmentList">
+ </div>
+ </div>
+ <div class="segment-input metricMatchBlock valign-wrapper">
+ <div piwik-field uicontrol="select" name="matches"
+ style="display: inline-block"
+ full-width="true"
+ ng-change="segmentGenerator.updateSegmentDefinition()"
+ ng-model="orCondition.matches"
+ options="segmentGenerator.matches[segmentGenerator.segments[orCondition.segment].type]">
+ </div>
+ </div>
+ <div class="segment-input metricValueBlock valign-wrapper">
+ <div class="form-group row" style="width: 100%;">
+ <div class="input-field col s12">
+ <span role="status" aria-live="polite" class="ui-helper-hidden-accessible"></span>
+ <input ng-model="orCondition.value" placeholder="Value"
+ ng-change="segmentGenerator.updateSegmentDefinition()"
+ type="text" class="autocomplete" title="Value" autocomplete="off">
+ </div>
+ </div>
+ </div>
+ <div class="clear"></div>
+ </div>
+ </div>
+
+ <div class="segment-or">{{ 'SegmentEditor_OperatorOR'|translate }}</div>
+ </div>
+
+ <div class="segment-add-or" ng-click="segmentGenerator.addNewOrCondition(condition)">
+ <div>
+ <a ng-bind-html="'+' + ('SegmentEditor_AddANDorORCondition'|translate:'&lt;span>' + ('SegmentEditor_OperatorOR'|translate) + '&lt;/span>')"></a>
+ </div>
+ </div>
+ </div>
+ <div class="segment-and">{{ 'SegmentEditor_OperatorAND'|translate }}</div>
+ </div>
+
+ <div class="segment-add-row initial" ng-click="segmentGenerator.addNewAndCondition()">
+ <div>
+ <a ng-bind-html="'+' + ('SegmentEditor_AddANDorORCondition'|translate:'&lt;span>' + segmentGenerator.andConditionLabel + '&lt;/span>')"></a>
+ </div>
+ </div>
+</div>
diff --git a/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.js b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.js
new file mode 100644
index 0000000000..25a0141f19
--- /dev/null
+++ b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.js
@@ -0,0 +1,64 @@
+/*!
+ * 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-segment-generator>
+ */
+(function () {
+ angular.module('piwikApp').directive('piwikSegmentGenerator', piwikSegmentGenerator);
+
+ piwikSegmentGenerator.$inject = ['$document', 'piwik', '$filter', '$timeout'];
+
+ function piwikSegmentGenerator($document, piwik, $filter, $timeout){
+ var defaults = {
+ segmentDefinition: '',
+ addInitialCondition: false,
+ idsite: piwik.idSite
+ };
+
+ return {
+ restrict: 'A',
+ scope: {
+ segmentDefinition: '@',
+ addInitialCondition: '=',
+ idsite: '='
+ },
+ require: "?ngModel",
+ templateUrl: 'plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.html?cb=' + piwik.cacheBuster,
+ controller: 'SegmentGeneratorController',
+ controllerAs: 'segmentGenerator',
+ compile: function (element, attrs) {
+
+ for (var index in defaults) {
+ if (attrs[index] === undefined) {
+ attrs[index] = defaults[index];
+ }
+ }
+
+ return function (scope, element, attrs, ngModel) {
+ if (ngModel) {
+ ngModel.$render = function() {
+ scope.segmentDefinition = ngModel.$viewValue;
+ if (scope.segmentDefinition) {
+ scope.segmentGenerator.setSegmentString(scope.segmentDefinition);
+ } else {
+ scope.segmentGenerator.setSegmentString('');
+ }
+ };
+ }
+
+ scope.$watch('segmentDefinition', function (newValue) {
+ if (ngModel) {
+ ngModel.$setViewValue(newValue);
+ }
+ });
+ };
+ }
+ };
+ }
+})(); \ No newline at end of file
diff --git a/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.less b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.less
new file mode 100644
index 0000000000..782db0a88e
--- /dev/null
+++ b/plugins/SegmentEditor/angularjs/segment-generator/segmentgenerator.directive.less
@@ -0,0 +1,204 @@
+.segment-generator {
+ width: 900px;
+
+ .segment-row-inputs {
+ .form-group {
+ margin-top: 0;
+ margin-bottom: 0;
+
+ .input-field {
+ margin-top: 0;
+ }
+ }
+ }
+
+ .segment-input input {
+ display: block;
+ width: 96%;
+ padding: 8px 2%;
+ }
+ .segment-input label {
+ display: block;
+ margin: 0 0 5px 0;
+ font-size: 11px;
+ color: #505050;
+ }
+ .segment-input {
+ float: left;
+ padding: 6px 0 5px 3px;
+ border: 2px dashed #EFEFEB;
+ margin-right: 3px;
+ }
+
+ .segment-rows {
+ padding: 4px;
+ margin: 0 3px 0 0;
+ border: 1px solid #a9a399;
+ border-radius: 3px 3px 3px 3px;
+ position: relative;
+ box-shadow: 0 12px 6px -10px rgba(0, 0, 0, 0.42);
+ }
+
+ .segment-add-row,
+ .segment-add-or {
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: bold;
+ background: @theme-color-background-contrast;
+ color: #b9b9b9;
+ text-align: center;
+ position: relative;
+ .border-radius(5px);
+ }
+
+ .segment-add-row > div,
+ .segment-add-or > div {
+ border-radius: 4px;
+ border: 2px dashed #fff;
+ padding: 10px 0;
+ }
+
+ .segment-add-row > div a,
+ .segment-add-or > div a {
+ color: #b9b9b9;
+ text-decoration: none;
+ }
+
+ .segment-input {
+ select, input {
+ .font-default(12px, 14px);
+ color: @theme-color-text;
+ font-weight: 600;
+ margin: 0;
+ height: 32px;
+ }
+ }
+
+ .segment-add-row > div a span,
+ .segment-add-or > div a span {
+ color: @theme-color-brand;
+ text-shadow: none;
+ }
+
+ .segment-add-row {
+ margin: 0 3px 0 0;
+ padding: 0 12px;
+ border: 1px solid #a9a399;
+ border-radius: 3px 3px 3px 3px;
+ box-shadow: 0 12px 6px -10px rgba(0, 0, 0, 0.42);
+ }
+
+ .segment-add-or {
+ text-shadow: 0 1px 0 #fff;
+ display: inline-block;
+ width: 100%;
+ padding: 0 1%;
+ background: #efefeb;
+ border-radius: 3px 3px 3px 3px;
+ }
+
+ .segment-add-or > div {
+ border: 2px dashed #EFEFEB;
+ background-color: #efefeb;
+ }
+
+ .segment-row {
+ border-radius: 3px;
+ display: inline-block;
+ position: relative;
+ width: 887px;
+ padding: 12px 1%;
+ background: #efefeb;
+ padding: 0 5px 0 5px;
+ }
+
+ .segment-row .segment-close {
+ top: 15px;
+ right: 6px;
+ position: absolute;
+ width: 15px;
+ height: 15px;
+ background: url(plugins/SegmentEditor/images/segment-close.png) 0 0 no-repeat;
+ z-index: 9999;
+ }
+
+ .segment-row .segment-loading {
+ top: 25px;
+ right: 30px;
+ position: absolute;
+ width: 15px;
+ height: 15px;
+ background: url(plugins/Morpheus/images/loading-blue.gif) 0 0 no-repeat;
+ }
+
+ .segment-or {
+ display: inline-block;
+ margin: 0 0 0 6%;
+ position: relative;
+ background: #efefeb;
+ padding: 5px 28px;
+ color: #4f4f4f;
+ font-weight: bold;
+ font-size: 14px;
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ .segment-or:before,
+ .segment-or:after {
+ content: '';
+ position: absolute;
+ background: @theme-color-background-base;
+ border: 1px solid #efefeb;
+ width: 10px;
+ top: -1px;
+ bottom: -1px;
+ }
+
+ .segment-or:before {
+ border-left: none;
+ left: 0;
+ border-radius: 0 5px 5px 0;
+ }
+
+ .segment-or:after {
+ border-right: none;
+ right: 0;
+ border-radius: 5px 0 0 5px;
+ }
+
+ .segment-and {
+ display: inline-block;
+ margin: -1px 0 -1px 6%;
+ z-index: 1;
+ position: relative;
+ background: @theme-color-background-contrast;
+ padding: 5px 35px;
+ color: #4f4f4f;
+ font-size: 14px;
+ font-weight: bold;
+ text-shadow: 0 1px 0 #fff;
+ }
+
+ .segment-and:before,
+ .segment-and:after {
+ content: '';
+ position: absolute;
+ background: url(plugins/SegmentEditor/images/bg-inverted-corners.png);
+ border: 1px solid #a9a399;
+ width: 10px;
+ top: 0;
+ bottom: 0;
+ }
+
+ .segment-and:before {
+ border-left: none;
+ left: 0;
+ border-radius: 0 5px 5px 0;
+ }
+
+ .segment-and:after {
+ border-right: none;
+ right: 0;
+ border-radius: 5px 0 0 5px;
+ }
+}
diff --git a/plugins/SegmentEditor/javascripts/Segmentation.js b/plugins/SegmentEditor/javascripts/Segmentation.js
index 0153a6b491..e018fec7cd 100644
--- a/plugins/SegmentEditor/javascripts/Segmentation.js
+++ b/plugins/SegmentEditor/javascripts/Segmentation.js
@@ -19,11 +19,6 @@ Segmentation = (function($) {
$('.segmentListContainer .segmentationContainer .title').trigger('click').focus();
});
- function preselectFirstMetricMatch(rowNode)
- {
- var matchValue = $(rowNode).find('.metricMatchBlock option:first').attr('value');
- $(rowNode).find('.metricMatchBlock select').val(matchValue);
- }
var segmentation = function segmentation(config) {
if (!config.target) {
@@ -128,98 +123,11 @@ Segmentation = (function($) {
}
};
- var getAndDiv = function(){
- if(typeof andDiv === "undefined"){
- var andDiv = self.editorTemplate.find("> div.segment-and").clone();
- }
- return andDiv.clone();
- };
-
- var getOrDiv = function(){
- if(typeof orDiv === "undefined"){
- var orDiv = self.editorTemplate.find("> div.segment-or").clone();
- }
- return orDiv.clone();
- };
-
- var getMockedInputSet = function(){
- var mockedInputSet = self.editorTemplate.find("div.segment-row-inputs").clone();
- var clonedInput = mockedInputSet.clone();
- preselectFirstMetricMatch(clonedInput);
-
- return clonedInput;
- };
-
- var getMockedInputRowHtml = function(){
- return '<div class="segment-row"><a class="segment-close" href="#"></a><div class="segment-row-inputs">'+getMockedInputSet().html()+'</div></div>';
- };
-
- var getMockedFormRow = function(){
- var mockedFormRow = self.editorTemplate.find("div.segment-rows").clone();
- $(mockedFormRow).find(".segment-row").append(getMockedInputSet()).after(getAddOrBlockButtonHtml).after(getOrDiv());
- var clonedRow = mockedFormRow.clone();
- preselectFirstMetricMatch(clonedRow);
-
- return clonedRow;
- };
-
- var getInitialStateRowsHtml = function(){
- if(typeof initialStateRows === "undefined"){
- var content = self.editorTemplate.find("div.initial-state-rows").html();
- var initialStateRows = $(content).clone();
- }
- return initialStateRows;
- };
-
- var revokeInitialStateRows = function(){
- $(self.form).find(".segment-add-row").remove();
- $(self.form).find(".segment-and").remove();
- };
-
- var appendSpecifiedRowHtml= function(metric) {
- var mockedRow = getMockedFormRow();
- $(self.form).find(".segment-content > h3").after(mockedRow);
- $(self.form).find(".segment-content").append(getAndDiv());
- $(self.form).find(".segment-content").append(getAddNewBlockButtonHtml());
- doDragDropBindings();
- $(self.form).find(".metricList").val(metric).trigger("change");
- preselectFirstMetricMatch(mockedRow);
- };
-
- var appendComplexRowHtml = function(block){
- var key;
- var newRow = getMockedFormRow();
-
- var x = $(newRow).find(".metricMatchBlock select");
- $(newRow).find(".metricListBlock select").val(block[0].metric);
- $(newRow).find(".metricMatchBlock select").val(block[0].match);
- $(newRow).find(".metricValueBlock input").val(block[0].value);
-
- if(block.length > 1) {
- $(newRow).find(".segment-add-or").remove();
- for(key = 1; key < block.length;key++) {
- var newSubRow = $(getMockedInputRowHtml()).clone();
- $(newSubRow).find(".metricListBlock select").val(block[key].metric);
- $(newSubRow).find(".metricMatchBlock select").val(block[key].match);
- $(newSubRow).find(".metricValueBlock input").val(block[key].value);
- $(newRow).append(newSubRow).append(getOrDiv());
- }
- $(newRow).append(getAddOrBlockButtonHtml());
- }
- $(self.form).find(".segment-content").append(newRow).append(getAndDiv());
- };
-
- var applyInitialStateModification = function(){
- $(self.form).find(".segment-add-row").remove();
- $(self.form).find(".segment-content").append(getInitialStateRowsHtml());
- doDragDropBindings();
- };
-
var getSegmentFromId = function (id) {
if(self.availableSegments.length > 0) {
for(var i = 0; i < self.availableSegments.length; i++)
{
- segment = self.availableSegments[i];
+ var segment = self.availableSegments[i];
if(segment.idsegment == id) {
return segment;
}
@@ -361,7 +269,7 @@ Segmentation = (function($) {
newOption = '<option data-idsegment="'+segment.idsegment+'" data-definition="'+(segment.definition).replace(/"/g, '&quot;')+'" title="'+getSegmentTooltipEnrichedWithUsername(segment)+'">'+getSegmentName(segment)+'</option>';
segmentsDropdown.append(newOption);
}
- $(html).find(".segment-content > h3").after(getInitialStateRowsHtml()).show();
+ $(html).find(".segment-content > h3").after('<div piwik-segment-generator add-initial-condition="true"></div>').show();
return html;
};
@@ -372,62 +280,6 @@ Segmentation = (function($) {
});
};
- var findAndExplodeByMatch = function(metric){
- var matches = ["==" , "!=" , "<=", ">=", "=@" , "!@","<",">", "=^", "=$"];
- var newMetric = {};
- var minPos = metric.length;
- var match, index;
- var singleChar = false;
-
- for(var key=0; key < matches.length; key++)
- {
- match = matches[key];
- index = metric.indexOf(match);
- if( index != -1){
- if(index < minPos){
- minPos = index;
- if(match.length == 1){
- singleChar = true;
- }
- }
- }
- }
-
- if(minPos < metric.length){
- // sth found - explode
- if(singleChar == true){
- newMetric.metric = metric.substr(0,minPos);
- newMetric.match = metric.substr(minPos,1);
- newMetric.value = metric.substr(minPos+1);
- } else {
- newMetric.metric = metric.substr(0,minPos);
- newMetric.match = metric.substr(minPos,2);
- newMetric.value = metric.substr(minPos+2);
- }
- // if value is only "" -> change to empty string
- if(newMetric.value == '""')
- {
- newMetric.value = "";
- }
- }
-
- newMetric.value = decodeURIComponent(newMetric.value);
- return newMetric;
- };
-
- var parseSegmentStr = function(segmentStr)
- {
- var blocks;
- blocks = segmentStr.split(";");
- for(var key in blocks){
- blocks[key] = blocks[key].split(",");
- for(var innerkey = 0; innerkey < blocks[key].length; innerkey++){
- blocks[key][innerkey] = findAndExplodeByMatch(blocks[key][innerkey]);
- }
- }
- return blocks;
- };
-
var openEditForm = function(segment){
addForm("edit", segment);
@@ -441,24 +293,14 @@ Segmentation = (function($) {
.html( getSegmentName(segment) )
.prop( 'title', getSegmentTooltipEnrichedWithUsername(segment));
- if(segment.definition != ""){
- revokeInitialStateRows();
- var blocks = parseSegmentStr(segment.definition);
- for(var key in blocks){
- appendComplexRowHtml(blocks[key]);
- }
- $(self.form).find(".segment-content").append(getAddNewBlockButtonHtml());
- }
$(self.form).find(".metricList").each( function(){
$(this).trigger("change", true);
});
- doDragDropBindings();
};
var displayFormAddNewSegment = function (e) {
closeAllOpenLists();
addForm("new");
- doDragDropBindings();
};
var filterSegmentList = function (keyword) {
@@ -561,17 +403,6 @@ Segmentation = (function($) {
displayFormAddNewSegment(e);
});
- self.target.on('change', "select.metricList", function (e, persist) {
- if (typeof persist === "undefined") {
- persist = false;
- }
- alterMatchesList(this, true);
-
- doDragDropBindings();
-
- autoSuggestValues(this, persist);
- });
-
// attach event that will clear segment list filtering input after clicking x
self.target.on('click', ".segmentFilterContainer span", function (e) {
$(e.target).parent().find(".segmentFilter").val(self.translations['General_Search']).trigger('keyup');
@@ -613,8 +444,10 @@ Segmentation = (function($) {
//
self.target.on('click', "a.editSegmentName", function (e) {
- var oldName = $(e.currentTarget).parents("h3").find("span").text();
- $(e.currentTarget).parents("h3").find("span").hide();
+ var $h3 = $(e.currentTarget).parents("h3");
+ $h3.css({'margin': '0 0 0 6px'});
+ var oldName = $h3.find("span").text();
+ $h3.find("span").hide();
$(e.currentTarget).hide();
$(e.currentTarget).before('<input class="edit_segment_name" type="text"/>');
$(e.currentTarget).siblings(".edit_segment_name").focus().val(oldName);
@@ -645,48 +478,6 @@ Segmentation = (function($) {
openEditFormGivenSegment(option);
});
- // attach event that shows/hides child elements of each metric category
- self.target.on('click', '.segment-nav a.metric_category', function (e) {
- $(e.currentTarget).siblings("ul").toggle();
- });
-
- self.target.on('click', ".custom_select_search a", function (e) {
- $(self.form).find(".segmentSearch").val("").trigger("keyup").val(self.translations['General_Search']);
- });
-
- // attach event that will clear search input upon focus if its content is default
- self.target.on('focus', '.segmentSearch', function (e) {
- var search = $(e.currentTarget).val();
- if(search == self.translations['General_Search'])
- $(e.currentTarget).val("");
- });
-
- // attach event that will set search input value upon blur if its content is not null
- self.target.on('blur', '.segmentSearch', function (e) {
- var search = $(e.currentTarget).val();
- if(search == ""){
- clearSearchMetricHighlight();
- $(e.currentTarget).val(self.translations['General_Search']);
- }
- });
-
- // bind search action triggering - only when input text is longer than 2 chars
- self.target.on('keyup', '.segmentSearch', function (e) {
- var search = $(e.currentTarget).val();
- if( search.length >= 2)
- {
- clearTimeout(self.timer);
- self.searchAllowed = true;
- self.timer = setTimeout(function(){
- searchSegments(search);
- }, 500);
- }
- else{
- self.searchAllowed = false;
- clearSearchMetricHighlight();
- }
- });
-
self.target.on('click', ".delete", function() {
var segmentName = $(self.form).find(".segment-content > h3 > span").text();
var segmentId = $(self.form).find(".available_segments_select option:selected").attr("data-idsegment");
@@ -709,7 +500,10 @@ Segmentation = (function($) {
});
$("body").on("keyup", function (e) {
- if(e.keyCode == "27"){
+ if(e.keyCode == "27" || e.which === 27) {
+ if (self.target.find('[uicontrol="expandable-select"] .expandableList:visible').length) {
+ return;
+ }
$(".segmentListContainer", self.target).show();
closeForm();
}
@@ -719,146 +513,6 @@ Segmentation = (function($) {
// segment manipulation events
//
- // upon clicking - add new segment block, then bind 'x' action to newly added row
- self.target.on('click', ".segment-add-row a", function(event, data){
- var mockedRow = getMockedFormRow();
- $(self.form).find(".segment-and:last").after(getAndDiv()).after(mockedRow);
- if(typeof data !== "undefined"){
- $(self.form).find(".metricList:last").val(data);
- }
- $(self.form).find(".metricList:last").trigger('change');
- preselectFirstMetricMatch(mockedRow);
- doDragDropBindings();
- });
-
- self.target.on("click", ".segment-add-row span", function(event, data){
- if(typeof data !== "undefined") {
- var mockedRow = getMockedFormRow();
- $(self.form).find(".segment-and:last").after(getAndDiv()).after(mockedRow);
- preselectFirstMetricMatch(mockedRow);
- $(self.form).find(".metricList:last").val(data).trigger('change');
- doDragDropBindings();
- }
- });
-
- // add new OR block
- self.target.on("click", ".segment-add-or a", function(event, data){
- var parentRows = $(event.currentTarget).parents(".segment-rows");
-
- parentRows.find(".segment-or:last").after(getOrDiv()).after(getMockedInputRowHtml());
- if(typeof data !== "undefined"){
- parentRows.find(".metricList:last").val(data);
- }
- parentRows.find(".metricList:last").trigger('change');
-
- var addedRow = parentRows.find('.segment-row:last');
- preselectFirstMetricMatch(addedRow);
- doDragDropBindings();
- });
-
- self.target.on("click", ".segment-close", function (e) {
- var target = e.currentTarget;
- var rowCnt = $(target).parents(".segment-rows").find(".segment-row").length;
- var globalRowCnt = $(self.form).find(".segment-close").length;
- if(rowCnt > 1){
- $(target).parents(".segment-row").next().remove();
- $(target).parents(".segment-row").remove();
- }
- else if(rowCnt == 1){
- $(target).parents(".segment-rows").next().remove();
- $(target).parents(".segment-rows").remove();
- if(globalRowCnt == 1){
- applyInitialStateModification();
- }
- }
- });
- };
-
- // Request auto-suggest values
- var autoSuggestValues = function(select, persist) {
- var type = $(select).find("option:selected").attr("value");
- if(!persist) {
- var parents = $(select).parents('.segment-row');
- var loadingElement = parents.find(".segment-loading");
- loadingElement.show();
- var inputElement = parents.find(".metricValueBlock input");
- var segmentName = $('option:selected',select).attr('value');
-
- var ajaxHandler = new ajaxHelper();
- ajaxHandler.addParams({
- module: 'API',
- format: 'json',
- method: 'API.getSuggestedValuesForSegment',
- segmentName: segmentName
- }, 'GET');
- ajaxHandler.useRegularCallbackInCaseOfError = true;
- ajaxHandler.setTimeout(20000);
- ajaxHandler.setErrorCallback(function(response) {
- loadingElement.hide();
- inputElement.autocomplete({
- source: [],
- minLength: 0
- });
- $(inputElement).autocomplete('search', $(inputElement).val());
- });
- ajaxHandler.setCallback(function(response) {
- loadingElement.hide();
-
- if (response && response.result != 'error') {
-
- inputElement.autocomplete({
- source: response,
- minLength: 0,
- select: function(event, ui){
- event.preventDefault();
- $(inputElement).val(ui.item.value);
- }
- });
- }
-
- inputElement.click(function (e) {
- $(inputElement).autocomplete('search', $(inputElement).val());
- });
- });
- ajaxHandler.send();
- }
- };
-
- var alterMatchesList = function(select, persist){
- var oldMatch;
- var type = $(select).find("option:selected").attr("data-type");
- var matchSelector = $(select).parents(".segment-input").siblings(".metricMatchBlock").find("select");
- if(persist === true){
- oldMatch = matchSelector.find("option:selected").val();
- } else {
- oldMatch = "";
- }
-
- if(type === "dimension" || type === "metric"){
- matchSelector.empty();
- var optionsHtml = "";
- for(var key in self.availableMatches[type]){
- optionsHtml += '<option value="'+key+'">'+self.availableMatches[type][key]+'</option>';
- }
- }
-
- matchSelector.append(optionsHtml);
-
- if (matchSelector.find('option[value="' + oldMatch + '"]').length) {
- matchSelector.val(oldMatch);
- } else {
- preselectFirstMetricMatch(matchSelector.parent());
- }
- };
-
- var getAddNewBlockButtonHtml = function()
- {
- if(typeof addNewBlockButton === "undefined")
- {
- var addNewBlockButton = self.editorTemplate.find("> div.segment-add-row").clone();
- }
- return addNewBlockButton.clone();
-
};
var getAddOrBlockButtonHtml = function(){
@@ -868,16 +522,6 @@ Segmentation = (function($) {
return addOrBlockButton.clone();
};
- var placeSegmentationFormControls = function(){
- doDragDropBindings();
- $(self.form).find(".scrollable").jScrollPane({
- showArrows: true,
- autoReinitialise: true,
- verticalArrowPositions: 'os',
- horizontalArrowPositions: 'os'
- });
- };
-
function openEditFormGivenSegment(option) {
var idsegment = option.attr("data-idsegment");
@@ -890,103 +534,6 @@ Segmentation = (function($) {
}
}
- var doDragDropBindings = function(){
- $(self.form).find(".segment-nav div > ul > li > ul > li").sortable({
- cursor: 'move',
- revert: 10,
- revertDuration: 0,
- snap: false,
- helper: 'clone',
- appendTo: 'body'
- });
-
- $(self.form).find(".metricListBlock").droppable({
- hoverClass: "hovered",
- drop: function( event, ui ) {
- $(this).find("select").val(ui.draggable.parent().attr("data-metric")).trigger("change");
- }
- });
-
- $(self.form).find(".segment-add-row > div").droppable({
- hoverClass: "hovered",
- drop: function( event, ui ) {
- $(this).find("a").trigger("click", [ui.draggable.parent().attr("data-metric")]);
- if($(this).find("a > span").length == 0){
- revokeInitialStateRows();
- appendSpecifiedRowHtml([ui.draggable.parent().attr("data-metric")]);
- }
- }
- });
-
- $(self.form).find(".segment-add-or > div").droppable({
- hoverClass: "hovered",
- drop: function( event, ui ) {
- $(this).find("a").trigger("click", [ui.draggable.parent().attr("data-metric")]);
- }
- });
- };
-
- var searchSegments = function(search){
- // pre-process search string to normalized form
- search = normalizeSearchString(search);
-
- // ---
- // clear all previous search highlights and hide all categories
- // to allow further showing only matching ones, while others remain invisible
- clearSearchMetricHighlight();
- $(self.form).find('.segment-nav div > ul > li').hide();
- var curStr = "";
- var curMetric = "";
-
- // 1 - do most obvious selection -> mark whole categories matching search string
- // also expand whole category
- $(self.form).find('.segment-nav div > ul > li').each( function(){
- curStr = normalizeSearchString($(this).find("a.metric_category").text());
- if(curStr.indexOf(search) > -1) {
- $(this).addClass("searchFound");
- $(this).find("ul").show();
- $(this).find("li").show();
- $(this).show();
- }
- }
- );
-
- // 2 - among all unselected categories find metrics which match and mark parent as search result
- $(self.form).find(".segment-nav div > ul > li:not(.searchFound)").each(function(){
- var parent = this;
- $(this).find("li").each( function(){
- var curStr = normalizeSearchString($(this).text());
- var curMetric = normalizeSearchString($(this).attr("data-metric"));
- $(this).hide();
- if(curStr.indexOf(search) > -1 || curMetric.indexOf(search) > -1){
- $(this).show();
- $(parent).find("ul").show();
- $(parent).addClass("searchFound").show();
- }
- });
- });
-
- if( $(self.form).find("li.searchFound").length == 0)
- {
- $(self.form).find("div > ul").prepend('<li class="no_results"><a>'+self.translations['General_SearchNoResults']+'</a></li>').show();
- }
- // check if search allow flag was revoked - then clear all search results
- if(self.searchAllowed == false)
- {
- clearSearchMetricHighlight();
- self.searchAllowed = true;
- }
-
- };
-
- var clearSearchMetricHighlight = function(){
- $(self.form).find('.no_results').remove();
- $(self.form).find('.segment-nav div > ul > li').removeClass("searchFound").show();
- $(self.form).find('.segment-nav div > ul > li').removeClass("others").show();
- $(self.form).find('.segment-nav div > ul > li > ul > li').show();
- $(self.form).find('.segment-nav div > ul > li > ul').hide();
- };
-
var normalizeSearchString = function(search){
search = search.replace(/^\s+|\s+$/g, ''); // trim
search = search.toLowerCase();
@@ -1012,6 +559,7 @@ Segmentation = (function($) {
}
// remove any remaining forms
+
self.form = getFormHtml();
self.target.prepend(self.form);
@@ -1025,13 +573,8 @@ Segmentation = (function($) {
self.form.addClass('anchorRight');
}
- placeSegmentationFormControls();
-
- // needs to be done before jQuery selects are built, as angular compiler screws up the selected values
- piwikHelper.compileAngularComponents(self.target);
-
if(mode == "edit") {
- $(self.form).find('.enable_all_users_select > option[value="' + segment.enable_all_users + '"]').prop("selected",true);
+ var userSelector = $(self.form).find('.enable_all_users_select > option[value="' + segment.enable_all_users + '"]').prop("selected",true);
// Replace "Visible to me" by "Visible to $login" when user is super user
if(hasSuperUserAccessAndSegmentCreatedByAnotherUser(segment)) {
@@ -1040,6 +583,9 @@ Segmentation = (function($) {
$(self.form).find('.visible_to_website_select > option[value="'+segment.enable_only_idsite+'"]').prop("selected",true);
$(self.form).find('.auto_archive_select > option[value="'+segment.auto_archive+'"]').prop("selected",true);
+ if (segment.definition != ""){
+ self.form.find('[piwik-segment-generator]').attr('segment-definition', segment.definition);
+ }
}
makeDropList(".enable_all_users" , ".enable_all_users_select");
@@ -1058,6 +604,8 @@ Segmentation = (function($) {
$(".segmentListContainer", self.target).hide();
self.target.closest('.segmentEditorPanel').addClass('editing');
+
+ piwikHelper.compileAngularComponents(self.target);
};
var closeForm = function () {
@@ -1065,34 +613,14 @@ Segmentation = (function($) {
self.target.closest('.segmentEditorPanel').removeClass('editing');
};
- var parseForm = function(){
- var segmentStr = "";
- $(self.form).find(".segment-rows").each( function(){
- var subSegmentStr = "";
-
- $(this).find(".segment-row").each( function(){
- if(subSegmentStr != ""){
- subSegmentStr += ","; // OR operator
- }
- $(this).find(".segment-row-inputs").each( function(){
- var metric = $(this).find(".metricList option:selected").val();
- var match = $(this).find(".metricMatchBlock > select option:selected").val();
- var value = $(this).find(".segment-input input").val();
- subSegmentStr += metric + match + encodeURIComponent(value);
- });
- });
- if(segmentStr != "")
- {
- segmentStr += ";"; // add AND operator between segment blocks
- }
- segmentStr += subSegmentStr;
- });
- return segmentStr
- };
+ function getSegmentGeneratorController()
+ {
+ return angular.element(self.form.find('.segment-generator')).scope().segmentGenerator;
+ }
var parseFormAndSave = function(){
var segmentName = $(self.form).find(".segment-content > h3 >span").text();
- var segmentStr = parseForm();
+ var segmentStr = getSegmentGeneratorController().getSegmentString();
var segmentId = $(self.form).find('.available_segments_select > option:selected').attr("data-idsegment");
var user = $(self.form).find(".enable_all_users_select option:selected").val();
var autoArchive = $(self.form).find(".auto_archive_select option:selected").val() || 0;
diff --git a/plugins/SegmentEditor/stylesheets/segmentation.less b/plugins/SegmentEditor/stylesheets/segmentation.less
index a4e291ed46..a38df86939 100644
--- a/plugins/SegmentEditor/stylesheets/segmentation.less
+++ b/plugins/SegmentEditor/stylesheets/segmentation.less
@@ -41,12 +41,11 @@
}
.metricMatchBlock {
- width: 120px;
margin-right: 11px;
}
.metricValueBlock {
- width: 352px;
+ width: 500px;
}
div.scrollable {
@@ -98,81 +97,16 @@ div.scrollable {
background: url(plugins/SegmentEditor/images/reset_search.png);
}
-.segment-element .segment-nav {
- position: absolute;
- top: 7px;
- left: 5px;
- bottom: 135px;
- float: left;
- width: 170px;
-}
-
-.segment-element .segment-nav h4 {
- font-size: 14px;
- font-weight: bold;
- padding: 0 0 8px 0;
-}
-
-.segment-element .segment-nav h4 a {
- color: #255792;
- text-decoration: none;
-}
-
-.segment-element .segment-nav div > ul {
- padding: 0 0 0 15px;
-}
-
-.segment-element .segment-nav div > ul > li {
- padding: 2px 0;
- line-height: 14px;
-}
-
-.segment-element .segment-nav div > ul > li li {
- padding: 1px;
- border-radius: 3px 3px 3px 3px;
-}
-
-.segment-element .segment-nav div > ul > li li:hover {
- padding: 0;
- border: 1px solid #cfccbd;
- border-bottom: 1px solid #7c7a72;
-}
-
-.segment-element .segment-nav div > ul > li li:hover a {
- cursor: move;
- padding: 1px 0 2px 8px;
- border-top: 1px solid #fff;
- background: #eae8e3 url(plugins/SegmentEditor/images/segment-move.png) 100% 50% no-repeat;
-}
-
-.segment-element .segment-nav div > ul > li li a {
- padding: 2px 0 2px 8px;
- font-weight: normal;
- display: block;
-}
-
-.segment-element .segment-nav div > ul > li ul {
- margin: 2px 0 -3px 10px;
-}
-
-.segment-element .segment-nav div > ul > li a {
- color: @theme-color-text-light;
- font-size: 11px;
- font-weight: bold;
- text-decoration: none;
- text-shadow: 0 1px 0 #fff;
-}
-
.segment-element .segment-content {
min-height: 300px;
- padding: 0 0 20px 203px;
+ padding: 0 0 20px 0;
}
.segment-element .segment-content h3 {
font-size: 16px;
font-weight: bold;
color: #505050;
- margin: 11px 0 0 0;
+ margin: 0 0 0 0;
text-shadow: 0 1px 0 #fff;
}
@@ -182,194 +116,10 @@ div.scrollable {
margin: -1px 0 0 0;
}
-.segment-element .segment-content .segment-rows {
- padding: 4px;
- margin: 0 3px 0 0;
- border: 1px solid #a9a399;
- border-radius: 3px 3px 3px 3px;
- position: relative;
- box-shadow: 0 12px 6px -10px rgba(0, 0, 0, 0.42);
-}
-
-.segment-element .segment-content .segment-add-row,
-.segment-element .segment-content .segment-add-or {
- font-size: 14px;
- font-weight: bold;
- background: @theme-color-background-contrast;
- color: #b9b9b9;
- text-align: center;
- position: relative;
-}
-
-.segment-element .segment-content .segment-add-row > div,
-.segment-element .segment-content .segment-add-or > div {
- border-radius: 4px;
- border: 2px dashed #fff;
- padding: 10px 0;
-}
-
-.segment-element .segment-content .segment-add-row > div a,
-.segment-element .segment-content .segment-add-or > div a {
- color: #b9b9b9;
- text-decoration: none;
-}
-
-.segment-element .segment-content .segment-add-row > div a span,
-.segment-element .segment-content .segment-add-or > div a span {
- color: #255792;
-}
-
-.segment-element .segment-content .segment-add-row {
- margin: 0 3px 0 0;
- padding: 0 12px;
- border: 1px solid #a9a399;
- border-radius: 3px 3px 3px 3px;
- box-shadow: 0 12px 6px -10px rgba(0, 0, 0, 0.42);
-}
-
-.segment-element .segment-content .segment-add-or {
- text-shadow: 0 1px 0 #fff;
- display: inline-block;
- width: 100%;
- padding: 0 1%;
- background: #efefeb;
- border-radius: 3px 3px 3px 3px;
-}
-
-.segment-element .segment-content .segment-add-or > div {
- border: 2px dashed #EFEFEB;
- background-color: #efefeb;
-}
-
-.segment-element .segment-content .segment-row {
- border-radius: 3px;
- display: inline-block;
- position: relative;
- width: 811px;
- padding: 12px 1%;
- background: #efefeb;
- padding: 7px 5px 0 5px;
-}
-
-.segment-element .segment-content .segment-row .segment-close {
- top: 15px;
- right: 6px;
- position: absolute;
- width: 15px;
- height: 15px;
- background: url(plugins/SegmentEditor/images/segment-close.png) 0 0 no-repeat;
-}
-
-.segment-element .segment-content .segment-row .segment-loading {
- display: none;
- top: 25px;
- right: 30px;
- position: absolute;
- width: 15px;
- height: 15px;
- background: url(plugins/Morpheus/images/loading-blue.gif) 0 0 no-repeat;
-}
-
-.segment-element .segment-content .segment-or {
- display: inline-block;
- margin: 0 0 0 6%;
- position: relative;
- background: #efefeb;
- padding: 5px 28px;
- color: #4f4f4f;
- font-weight: bold;
- font-size: 14px;
- text-shadow: 0 1px 0 #fff;
-}
-
-.segment-element .segment-content .segment-or:before,
-.segment-element .segment-content .segment-or:after {
- content: '';
- position: absolute;
- background: @theme-color-background-base;
- border: 1px solid #efefeb;
- width: 10px;
- top: -1px;
- bottom: -1px;
-}
-
-.segment-element .segment-content .segment-or:before {
- border-left: none;
- left: 0px;
- border-radius: 0 5px 5px 0;
-}
-
-.segment-element .segment-content .segment-or:after {
- border-right: none;
- right: 0px;
- border-radius: 5px 0 0 5px;
-}
-
.segment-element .edit_segment_name {
width: 200px;
}
-.segment-element .segment-content .segment-and {
- display: inline-block;
- margin: -1px 0 -1px 6%;
- z-index: 1;
- position: relative;
- background: @theme-color-background-contrast;
- padding: 5px 35px;
- color: #4f4f4f;
- font-size: 14px;
- font-weight: bold;
- text-shadow: 0 1px 0 #fff;
-}
-
-.segment-element .segment-content .segment-and:before,
-.segment-element .segment-content .segment-and:after {
- content: '';
- position: absolute;
- background: url(plugins/SegmentEditor/images/bg-inverted-corners.png);
- border: 1px solid #a9a399;
- width: 10px;
- top: 0px;
- bottom: 0px;
-}
-
-.segment-element .segment-content .segment-and:before {
- border-left: none;
- left: 0px;
- border-radius: 0 5px 5px 0;
-}
-
-.segment-element .segment-content .segment-and:after {
- border-right: none;
- right: 0px;
- border-radius: 5px 0 0 5px;
-}
-
-.segment-element .segment-content .segment-input {
- float: left;
- padding: 6px 0 5px 3px;
- border: 2px dashed #EFEFEB;
- margin-right: 3px;
-}
-
-.segment-element .segment-content .segment-input label {
- display: block;
- margin: 0 0 5px 0;
- font-size: 11px;
- color: #505050;
-}
-
-.segment-element .segment-content .segment-input select,
-.segment-element .segment-content .segment-input input {
- display: block;
- width: 96%;
- padding-top: 7px;
- padding-bottom: 7px;
-}
-
-.segment-element .segment-content .segment-input input {
- padding: 8px 2%;
-}
.segment-element .segment-top {
font-size: 11px;
@@ -627,7 +377,7 @@ a.metric_category {
.segment-element {
z-index: 999;
- width: 1040px;
+ width: 908px;
}
.segmentationSelectorContainer {
@@ -688,12 +438,6 @@ a.metric_category {
left: auto;
}
-.available_segments {
- display: inline-block;
- width: 150px;
- padding-left: 5px;
-}
-
.segmentationTitle,
.segment-element .segment-nav a.dropdown,
.segname {
diff --git a/plugins/SegmentEditor/templates/_segmentSelector.twig b/plugins/SegmentEditor/templates/_segmentSelector.twig
index 8a4ae950c8..ae9b9d6c16 100644
--- a/plugins/SegmentEditor/templates/_segmentSelector.twig
+++ b/plugins/SegmentEditor/templates/_segmentSelector.twig
@@ -32,103 +32,15 @@
</div>
</div>
- <div class="initial-state-rows">{# no space here important for jQuery #}<div class="segment-add-row initial"><div>
- <span>+ {{ 'SegmentEditor_DragDropCondition'|translate|raw }}</span>
- </div></div>
- <div class="segment-and">{{ 'SegmentEditor_OperatorAND'|translate|raw }}</div>
- <div class="segment-add-row initial"><div>
- <span>+ {{ 'SegmentEditor_DragDropCondition'|translate|raw }}</span>
- </div></div>
- </div>
-
- <div class="segment-row-inputs">
- <div class="segment-input metricListBlock">
- <select title="{{ 'SegmentEditor_ChooseASegment'|translate }}" class="metricList browser-default">
- {% for category,segmentsInCategory in segmentsByCategory %}
- <optgroup label="{{ category }}">
- {% for segmentInCategory in segmentsInCategory %}
- <option data-type="{{ segmentInCategory.type }}" value="{{ segmentInCategory.segment }}">{{ segmentInCategory.name }}</option>
- {% endfor %}
- </optgroup>
- {% endfor %}
- </select>
- </div>
- <div class="segment-input metricMatchBlock">
- <select title="{{ 'General_Matches'|translate }}" class="browser-default">
- <option value="==">{{ 'General_OperationEquals'|translate }}</option>
- <option value="!=">{{ 'General_OperationNotEquals'|translate }}</option>
- <option value="<=">{{ 'General_OperationAtMost'|translate }}</option>
- <option value=">=">{{ 'General_OperationAtLeast'|translate }}</option>
- <option value="<">{{ 'General_OperationLessThan'|translate }}</option>
- <option value=">">{{ 'General_OperationGreaterThan'|translate }}</option>
- <option value="=@">{{ 'General_OperationContains'|translate }}</option>
- <option value="!@">{{ 'General_OperationDoesNotContain'|translate }}</option>
- <option value="=^">{{ 'General_OperationStartsWith'|translate }}</option>
- <option value="=$">{{ 'General_OperationEndsWith'|translate }}</option>
- </select>
- </div>
- <div class="segment-input metricValueBlock">
- <input type="text" class="browser-default" title="{{ 'General_Value'|translate }}">
- </div>
- <div class="clear"></div>
- </div>
- <div class="segment-rows">
- <div class="segment-row">
- <a href="#" class="segment-close"></a>
- <a href="#" class="segment-loading"></a>
- </div>
- </div>
- <div class="segment-or">{{ 'SegmentEditor_OperatorOR'|translate }}</div>
- <div class="segment-add-or"><div>
- {% set orCondition %}<span>{{ 'SegmentEditor_OperatorOR'|translate }}</span>{% endset %}
- <a href="#"> + {{ 'SegmentEditor_AddANDorORCondition'|translate(orCondition)|raw }} </a>
- </div>
- </div>
- <div class="segment-and">{{ 'SegmentEditor_OperatorAND'|translate }}</div>
- <div class="segment-add-row"><div>
- {% set andCondition %}<span>{{ 'SegmentEditor_OperatorAND'|translate }}</span>{% endset %}
- <a href="#">+ {{ 'SegmentEditor_AddANDorORCondition'|translate(andCondition)|raw }}</a>
- </div>
- </div>
<div class="segment-element borderedControl expanded">
- <div class="segment-nav">
- <h4 class="visits">
- <span class="icon-segment"></span><span class="available_segments"><strong>
- <select class="available_segments_select browser-default"></select>
- </strong></span></h4>
-
- <div class="custom_select_search">
- <a href="#"></a>
- <input type="text" aria-haspopup="true" aria-autocomplete="list" role="textbox" autocomplete="off" class="inp ui-autocomplete-input segmentSearch browser-default" value="{{ 'General_Search'|translate }}" length="15">
- </div>
- <div class="scrollable">
- <ul>
- {% for category,segmentsInCategory in segmentsByCategory %}
- <li data="visit">
- <a class="metric_category" href="#">{{ category }}</a>
- <ul style="display:none;">
- {% for segmentInCategory in segmentsInCategory %}
- {% set title = segmentInCategory.name %}
- {% if segmentInCategory.unionOfSegments is defined and segmentInCategory.unionOfSegments %}
- {% set title = 'SegmentEditor_SegmentXIsAUnionOf'|translate(title) %}
- {% for unionSegment in segmentInCategory.unionOfSegments %}
- {% set title = title ~ ' ' ~ unionSegment %}
- {% if not loop.last %}
- {% set title = title ~ ',' %}
- {% endif %}
- {% endfor %}
- {% endif %}
- <li data-metric="{{ segmentInCategory.segment }}" title="{{ title|e('html_attr') }}"><a class="ddmetric" href="#">{{ segmentInCategory.name }}</a></li>
- {% endfor %}
- </ul>
- </li>
- {% endfor %}
- </ul>
- </div>
- </div>
<div class="segment-content">
<div class="segment-top" {% if not isSuperUser %}style="display:none"{% endif %}>
+
+ <span class="icon-segment"></span><span class="available_segments"><strong>
+ <select class="available_segments_select browser-default"></select>
+ </strong></span>
+
{{ 'SegmentEditor_ThisSegmentIsVisibleTo'|translate }} <span class="enable_all_users"><strong>
<select class="enable_all_users_select">
<option selected="1" value="0">{{ 'SegmentEditor_VisibleToMe'|translate }}</option>
@@ -152,7 +64,7 @@
</strong></span>
</div>
- <h3>{{ 'General_Name'|translate }}: <span class="segmentName"></span> <a class="editSegmentName" href="#">{{ 'General_Edit'|translate|lower }}</a></h3>
+ <h3 style="margin: 12px 6px;">{{ 'General_Name'|translate }}: <span class="segmentName"></span> <a class="editSegmentName" href="#">{{ 'General_Edit'|translate|lower }}</a></h3>
</div>
<div class="segment-footer">
<div piwik-rate-feature title="Segment Editor" style="display:inline-block;float: left;margin-top: 2px;margin-right: 10px;"></div>
diff --git a/plugins/SegmentEditor/tests/Integration/SegmentEditorTest.php b/plugins/SegmentEditor/tests/Integration/SegmentEditorTest.php
index 2635db94f2..37ba8ffb65 100644
--- a/plugins/SegmentEditor/tests/Integration/SegmentEditorTest.php
+++ b/plugins/SegmentEditor/tests/Integration/SegmentEditorTest.php
@@ -200,7 +200,7 @@ class SegmentEditorTest extends IntegrationTestCase
$timestampProperties = array('ts_last_edit', 'ts_created');
foreach ($timestampProperties as $propertyName) {
if (isset($segmentInfo[$propertyName])) {
- $segmentInfo[$propertyName] = substr($segmentInfo[$propertyName], 0, strlen($segmentInfo[$propertyName] - 2));
+ $segmentInfo[$propertyName] = substr($segmentInfo[$propertyName], 0, strlen($segmentInfo[$propertyName]) - 2);
}
}
}
diff --git a/plugins/UserCountry/Categories/LocationsCategory.php b/plugins/UserCountry/Categories/LocationsCategory.php
new file mode 100644
index 0000000000..59bc376906
--- /dev/null
+++ b/plugins/UserCountry/Categories/LocationsCategory.php
@@ -0,0 +1,17 @@
+<?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\UserCountry\Categories;
+
+use Piwik\Category\Category;
+
+class LocationsCategory extends Category
+{
+ protected $id = 'UserCountry_VisitLocation';
+ protected $order = 7;
+}
diff --git a/plugins/UserCountry/Columns/City.php b/plugins/UserCountry/Columns/City.php
index 3521768f4d..8357d3e551 100644
--- a/plugins/UserCountry/Columns/City.php
+++ b/plugins/UserCountry/Columns/City.php
@@ -8,31 +8,21 @@
*/
namespace Piwik\Plugins\UserCountry\Columns;
-use Piwik\Piwik;
use Piwik\Plugins\UserCountry\LocationProvider;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
-use Piwik\Plugins\UserCountry\Segment;
class City extends Base
{
protected $columnName = 'location_city';
protected $columnType = 'varchar(255) DEFAULT NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('city');
- $segment->setName('UserCountry_City');
- $segment->setAcceptedValues('Sydney, Sao Paolo, Rome, etc.');
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('UserCountry_City');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $segmentName = 'city';
+ protected $nameSingular = 'UserCountry_City';
+ protected $namePlural = 'UserCountryMap_Cities';
+ protected $acceptValues = 'Sydney, Sao Paolo, Rome, etc.';
+ protected $category = 'UserCountry_VisitLocation';
/**
* @param Request $request
diff --git a/plugins/UserCountry/Columns/Continent.php b/plugins/UserCountry/Columns/Continent.php
index 089215dcf1..9080a37743 100644
--- a/plugins/UserCountry/Columns/Continent.php
+++ b/plugins/UserCountry/Columns/Continent.php
@@ -9,12 +9,29 @@
namespace Piwik\Plugins\UserCountry\Columns;
use Piwik\Columns\Dimension;
-use Piwik\Piwik;
+use Piwik\Common;
+use Piwik\Metrics\Formatter;
class Continent extends Dimension
{
- public function getName()
+ protected $dbTableName = 'log_visit';
+ protected $columnName = 'location_country';
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'UserCountry_VisitLocation';
+ protected $nameSingular = 'UserCountry_Continent';
+ protected $namePlural = 'UserCountry_Continents';
+ protected $segmentName = 'continentCode';
+ protected $acceptValues = 'eur, asi, amc, amn, ams, afr, ant, oce';
+ protected $sqlFilter = 'Piwik\Plugins\UserCountry\UserCountry::getCountriesForContinent';
+
+ public function groupValue($value, $idSite)
{
- return Piwik::translate('UserCountry_Continent');
+ return Common::getContinent($value);
}
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ return \Piwik\Plugins\UserCountry\continentTranslate($value);
+ }
+
} \ No newline at end of file
diff --git a/plugins/UserCountry/Columns/Country.php b/plugins/UserCountry/Columns/Country.php
index 9ce817ae9d..d6e89d3789 100644
--- a/plugins/UserCountry/Columns/Country.php
+++ b/plugins/UserCountry/Columns/Country.php
@@ -12,41 +12,33 @@ use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Intl\Data\Provider\RegionDataProvider;
+use Piwik\Metrics\Formatter;
use Piwik\Network\IP;
-use Piwik\Piwik;
use Piwik\Plugin\Manager;
use Piwik\Plugins\Provider\Provider as ProviderProvider;
use Piwik\Plugins\UserCountry\LocationProvider;
-use Piwik\Plugins\UserCountry\Segment;
use Piwik\Tracker\Visit;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
+require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/functions.php';
+
class Country extends Base
{
protected $columnName = 'location_country';
protected $columnType = 'CHAR(3) NULL';
+ protected $type = self::TYPE_TEXT;
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('countryCode');
- $segment->setName('UserCountry_Country');
- $segment->setAcceptedValues('de, us, fr, in, es, etc.');
- $this->addSegment($segment);
-
- $segment = new Segment();
- $segment->setSegment('continentCode');
- $segment->setName('UserCountry_Continent');
- $segment->setSqlFilter('Piwik\Plugins\UserCountry\UserCountry::getCountriesForContinent');
- $segment->setAcceptedValues('eur, asi, amc, amn, ams, afr, ant, oce');
- $this->addSegment($segment);
- }
+ protected $category = 'UserCountry_VisitLocation';
+ protected $nameSingular = 'UserCountry_Country';
+ protected $namePlural = 'UserCountryMap_Countries';
+ protected $segmentName = 'countryCode';
+ protected $acceptValues = 'de, us, fr, in, es, etc.';
- public function getName()
+ public function formatValue($value, $idSite, Formatter $formatter)
{
- return Piwik::translate('UserCountry_Country');
+ return \Piwik\Plugins\UserCountry\countryTranslate($value);
}
/**
diff --git a/plugins/UserCountry/Columns/Latitude.php b/plugins/UserCountry/Columns/Latitude.php
index 4cb29bf719..462b4812a1 100644
--- a/plugins/UserCountry/Columns/Latitude.php
+++ b/plugins/UserCountry/Columns/Latitude.php
@@ -8,9 +8,7 @@
*/
namespace Piwik\Plugins\UserCountry\Columns;
-use Piwik\Piwik;
use Piwik\Plugins\UserCountry\LocationProvider;
-use Piwik\Plugins\UserCountry\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -19,20 +17,12 @@ class Latitude extends Base
{
protected $columnName = 'location_latitude';
protected $columnType = 'decimal(9, 6) DEFAULT NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('latitude');
- $segment->setName('UserCountry_Latitude');
- $segment->setAcceptedValues('-33.578, 40.830, etc.<br/>You can select visitors within a lat/long range using &segment=lat&gt;X;lat&lt;Y;long&gt;M;long&lt;N.');
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('UserCountry_Latitude');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'UserCountry_VisitLocation';
+ protected $segmentName = 'latitude';
+ protected $nameSingular = 'UserCountry_Latitude';
+ protected $namePlural = 'UserCountry_Latitudes';
+ protected $acceptValues = '-33.578, 40.830, etc.<br/>You can select visitors within a lat/long range using &segment=lat&gt;X;lat&lt;Y;long&gt;M;long&lt;N.';
/**
* @param Request $request
diff --git a/plugins/UserCountry/Columns/Longitude.php b/plugins/UserCountry/Columns/Longitude.php
index d54a66ce6a..ab46fb27ef 100644
--- a/plugins/UserCountry/Columns/Longitude.php
+++ b/plugins/UserCountry/Columns/Longitude.php
@@ -8,9 +8,7 @@
*/
namespace Piwik\Plugins\UserCountry\Columns;
-use Piwik\Piwik;
use Piwik\Plugins\UserCountry\LocationProvider;
-use Piwik\Plugins\UserCountry\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -19,20 +17,12 @@ class Longitude extends Base
{
protected $columnName = 'location_longitude';
protected $columnType = 'decimal(9, 6) DEFAULT NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('longitude');
- $segment->setName('UserCountry_Longitude');
- $segment->setAcceptedValues('-70.664, 14.326, etc.');
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('UserCountry_Longitude');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'UserCountry_VisitLocation';
+ protected $acceptValues = '-70.664, 14.326, etc.';
+ protected $segmentName = 'longitude';
+ protected $nameSingular = 'UserCountry_Longitude';
+ protected $namePlural = 'UserCountry_Longitudes';
/**
* @param Request $request
diff --git a/plugins/UserCountry/Columns/Provider.php b/plugins/UserCountry/Columns/Provider.php
index 98c5bf97ca..19ce528a2c 100644
--- a/plugins/UserCountry/Columns/Provider.php
+++ b/plugins/UserCountry/Columns/Provider.php
@@ -17,6 +17,8 @@ use Piwik\Tracker\Request;
class Provider extends Base
{
protected $columnName = 'location_provider';
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'UserCountry_VisitLocation';
/**
* @param Request $request
diff --git a/plugins/UserCountry/Columns/Region.php b/plugins/UserCountry/Columns/Region.php
index 5b749673cf..1f14275e7b 100644
--- a/plugins/UserCountry/Columns/Region.php
+++ b/plugins/UserCountry/Columns/Region.php
@@ -8,9 +8,7 @@
*/
namespace Piwik\Plugins\UserCountry\Columns;
-use Piwik\Piwik;
use Piwik\Plugins\UserCountry\LocationProvider;
-use Piwik\Plugins\UserCountry\Segment;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
use Piwik\Tracker\Action;
@@ -19,20 +17,12 @@ class Region extends Base
{
protected $columnName = 'location_region';
protected $columnType = 'char(2) DEFAULT NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('regionCode');
- $segment->setName('UserCountry_Region');
- $segment->setAcceptedValues('01 02, OR, P8, etc.<br/>eg. region=A1;country=fr');
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('UserCountry_Region');
- }
+ protected $type = self::TYPE_TEXT;
+ protected $category = 'UserCountry_VisitLocation';
+ protected $segmentName = 'regionCode';
+ protected $nameSingular = 'UserCountry_Region';
+ protected $namePlural = 'UserCountryMap_Regions';
+ protected $acceptValues = '01 02, OR, P8, etc.<br/>eg. region=A1;country=fr';
/**
* @param Request $request
diff --git a/plugins/UserCountry/Segment.php b/plugins/UserCountry/Segment.php
deleted file mode 100644
index 2bae6f2f28..0000000000
--- a/plugins/UserCountry/Segment.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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\UserCountry;
-
-/**
- * UserCountry segment base class.
- *
- */
-class Segment extends \Piwik\Plugin\Segment
-{
- protected function init()
- {
- $this->setCategory('Visit Location');
- }
-}
diff --git a/plugins/UserCountry/lang/en.json b/plugins/UserCountry/lang/en.json
index 80eafa2349..4355539e83 100644
--- a/plugins/UserCountry/lang/en.json
+++ b/plugins/UserCountry/lang/en.json
@@ -11,11 +11,13 @@
"City": "City",
"CityAndCountry": "%1$s, %2$s",
"Continent": "Continent",
+ "Continents": "Continents",
"Country": "Country",
"country_a1": "Anonymous Proxy",
"country_a2": "Satellite Provider",
"country_cat": "Catalan-speaking communities",
"country_o1": "Other Country",
+ "VisitLocation": "Visit Location",
"CurrentLocationIntro": "According to this provider, your current location is",
"DefaultLocationProviderDesc1": "The default location provider guesses a visitor's country based on the language they use.",
"DefaultLocationProviderDesc2": "This is not very accurate, so %1$swe recommend installing and using %2$sGeoIP%3$s.%4$s",
@@ -67,11 +69,13 @@
"ISPDatabase": "ISP Database",
"IWantToDownloadFreeGeoIP": "I want to download the free GeoIP database...",
"Latitude": "Latitude",
+ "Latitudes": "Latitudes",
"Location": "Location",
"LocationDatabase": "Location Database",
"LocationDatabaseHint": "A location database is either a country, region or city database.",
"LocationProvider": "Location Provider",
"Longitude": "Longitude",
+ "Longitudes": "Longitudes",
"NoDataForGeoIPReport1": "There is no data for this report because there is either no location data available or visitor IP addresses cannot be geolocated.",
"NoDataForGeoIPReport2": "To enable accurate geolocation, change the settings %1$shere%2$s and use a %3$scity level database%4$s.",
"Organization": "Organization",
diff --git a/plugins/UserId/Columns/UserId.php b/plugins/UserId/Columns/UserId.php
index 7ac474cf73..e635f757d6 100644
--- a/plugins/UserId/Columns/UserId.php
+++ b/plugins/UserId/Columns/UserId.php
@@ -17,13 +17,6 @@ use Piwik\Plugin\Dimension\VisitDimension;
class UserId extends VisitDimension
{
- /**
- * The name of the dimension which will be visible for instance in the UI of a related report and in the mobile app.
- * @return string
- */
- public function getName()
- {
- return Piwik::translate('UserId_UserId');
- }
+ protected $nameSingular = 'UserId_UserId';
} \ No newline at end of file
diff --git a/plugins/UserLanguage/Columns/Language.php b/plugins/UserLanguage/Columns/Language.php
index fa665ed998..6d6ab2861b 100644
--- a/plugins/UserLanguage/Columns/Language.php
+++ b/plugins/UserLanguage/Columns/Language.php
@@ -9,7 +9,7 @@
namespace Piwik\Plugins\UserLanguage\Columns;
use Piwik\Common;
-use Piwik\Piwik;
+use Piwik\Metrics\Formatter;
use Piwik\Plugin\Dimension\VisitDimension;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
@@ -19,10 +19,16 @@ class Language extends VisitDimension
{
protected $columnName = 'location_browser_lang';
protected $columnType = 'VARCHAR(20) NULL';
+ protected $category = 'UserCountry_VisitLocation';
+ protected $nameSingular = 'General_Language';
+ protected $namePlural = 'General_Languages';
+ protected $segmentName = 'languageCode';
+ protected $acceptValues = 'de, fr, en-gb, zh-cn, etc.';
+ protected $type = self::TYPE_TEXT;
- public function getName()
+ public function formatValue($value, $idSite, Formatter $formatter)
{
- return Piwik::translate('General_Language');
+ return \Piwik\Plugins\UserLanguage\languageTranslateWithCode($value);
}
/**
@@ -52,13 +58,4 @@ class Language extends VisitDimension
return $languageCode;
}
- protected function configureSegments()
- {
- $segment = new \Piwik\Plugin\Segment();
- $segment->setCategory('Visit Location');
- $segment->setSegment('languageCode');
- $segment->setName('General_Language');
- $segment->setAcceptedValues('de, fr, en-gb, zh-cn, etc.');
- $this->addSegment($segment);
- }
}
diff --git a/plugins/VisitTime/Columns/DayOfTheWeek.php b/plugins/VisitTime/Columns/DayOfTheWeek.php
index 7728c07061..57c0e05856 100644
--- a/plugins/VisitTime/Columns/DayOfTheWeek.php
+++ b/plugins/VisitTime/Columns/DayOfTheWeek.php
@@ -13,8 +13,5 @@ use Piwik\Piwik;
class DayOfTheWeek extends Dimension
{
- public function getName()
- {
- return Piwik::translate('VisitTime_DayOfWeek');
- }
+ protected $nameSingular = 'VisitTime_DayOfWeek';
} \ No newline at end of file
diff --git a/plugins/VisitTime/Columns/LocalMinute.php b/plugins/VisitTime/Columns/LocalMinute.php
new file mode 100644
index 0000000000..e5a48b38c1
--- /dev/null
+++ b/plugins/VisitTime/Columns/LocalMinute.php
@@ -0,0 +1,43 @@
+<?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\VisitTime\Columns;
+
+use Piwik\Columns\DimensionMetricFactory;
+use Piwik\Columns\MetricsList;
+use Piwik\Metrics\Formatter;
+use Piwik\Plugin\Dimension\VisitDimension;
+
+require_once PIWIK_INCLUDE_PATH . '/plugins/VisitTime/functions.php';
+
+class LocalMinute extends VisitDimension
+{
+ protected $columnName = 'visitor_localtime';
+ protected $type = self::TYPE_NUMBER;
+ protected $segmentName = 'visitLocalMinute';
+ protected $nameSingular = 'VisitTime_ColumnLocalMinute';
+ protected $sqlSegment = 'MINUTE(log_visit.visitor_localtime)';
+ protected $acceptValues = '0, 1, 2, 3, ..., 67, 57, 58, 59';
+
+ public function __construct()
+ {
+ $this->suggestedValuesCallback = function ($idSite, $maxValuesToReturn) {
+ return range(0, min(59, $maxValuesToReturn));
+ };
+ }
+
+ public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory)
+ {
+ // no metrics for this dimension
+ }
+
+ public function formatValue($value, $idSite, Formatter $formatter)
+ {
+ return $value;
+ }
+} \ No newline at end of file
diff --git a/plugins/VisitTime/Columns/LocalTime.php b/plugins/VisitTime/Columns/LocalTime.php
index a37367cd6e..aef5f93471 100644
--- a/plugins/VisitTime/Columns/LocalTime.php
+++ b/plugins/VisitTime/Columns/LocalTime.php
@@ -8,31 +8,27 @@
*/
namespace Piwik\Plugins\VisitTime\Columns;
-use Piwik\Piwik;
+use Piwik\Metrics\Formatter;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\VisitTime\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
+require_once PIWIK_INCLUDE_PATH . '/plugins/VisitTime/functions.php';
+
class LocalTime extends VisitDimension
{
protected $columnName = 'visitor_localtime';
protected $columnType = 'TIME NULL';
+ protected $type = self::TYPE_TIME;
+ protected $segmentName = 'visitLocalHour';
+ protected $nameSingular = 'VisitTime_ColumnLocalHour';
+ protected $sqlSegment = 'HOUR(log_visit.visitor_localtime)';
+ protected $acceptValues = '0, 1, 2, 3, ..., 20, 21, 22, 23';
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('visitLocalHour');
- $segment->setName('VisitTime_ColumnLocalTime');
- $segment->setSqlSegment('HOUR(log_visit.visitor_localtime)');
- $segment->setAcceptedValues('0, 1, 2, 3, ..., 20, 21, 22, 23');
- $this->addSegment($segment);
- }
-
- public function getName()
+ public function formatValue($value, $idSite, Formatter $formatter)
{
- return Piwik::translate('VisitTime_ColumnLocalTime');
+ return \Piwik\Plugins\VisitTime\getTimeLabel($value);
}
/**
diff --git a/plugins/VisitTime/Columns/ServerTime.php b/plugins/VisitTime/Columns/ServerTime.php
deleted file mode 100644
index 5ee82706a5..0000000000
--- a/plugins/VisitTime/Columns/ServerTime.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?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\VisitTime\Columns;
-
-use Piwik\Piwik;
-use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\VisitTime\Segment;
-
-class ServerTime extends VisitDimension
-{
- protected $columnName = 'visit_last_action_time';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('visitServerHour');
- $segment->setName('VisitTime_ColumnServerTime');
- $segment->setSqlSegment('HOUR(log_visit.visit_last_action_time)');
- $segment->setAcceptedValues('0, 1, 2, 3, ..., 20, 21, 22, 23');
- $this->addSegment($segment);
- }
-
- public function getName()
- {
- return Piwik::translate('VisitTime_ColumnServerTime');
- }
-} \ No newline at end of file
diff --git a/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php b/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php
index 871f760046..2aa2c89fc5 100644
--- a/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php
+++ b/plugins/VisitTime/Reports/GetVisitInformationPerServerTime.php
@@ -10,8 +10,8 @@ namespace Piwik\Plugins\VisitTime\Reports;
use Piwik\Piwik;
use Piwik\Plugin\ViewDataTable;
+use Piwik\Plugins\CoreHome\Columns\VisitLastActionTime;
use Piwik\Plugins\CoreVisualizations\Visualizations\Graph;
-use Piwik\Plugins\VisitTime\Columns\ServerTime;
class GetVisitInformationPerServerTime extends Base
{
@@ -21,7 +21,7 @@ class GetVisitInformationPerServerTime extends Base
protected function init()
{
parent::init();
- $this->dimension = new ServerTime();
+ $this->dimension = new VisitLastActionTime();
$this->name = Piwik::translate('VisitTime_ServerTime');
$this->documentation = Piwik::translate('VisitTime_WidgetServerTimeDocumentation', array('<strong>', '</strong>'));
$this->constantRowsCount = true;
@@ -38,7 +38,7 @@ class GetVisitInformationPerServerTime extends Base
$view->requestConfig->filter_limit = 24;
$view->requestConfig->request_parameters_to_modify['hideFutureHoursWhenToday'] = 1;
- $view->config->addTranslation('label', $this->dimension->getName());
+ $view->config->addTranslation('label', Piwik::translate('VisitTime_ColumnServerHour'));
if ($view->isViewDataTableId(Graph::ID)) {
$view->config->max_graph_elements = false;
diff --git a/plugins/VisitTime/Segment.php b/plugins/VisitTime/Segment.php
deleted file mode 100644
index 30bc58f608..0000000000
--- a/plugins/VisitTime/Segment.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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\VisitTime;
-
-/**
- * VisitTime segment base class.
- *
- */
-class Segment extends \Piwik\Plugin\Segment
-{
- protected function init()
- {
- $this->setCategory('Visit');
- }
-}
diff --git a/plugins/VisitTime/lang/en.json b/plugins/VisitTime/lang/en.json
index 15fb00915c..e2cba5062a 100644
--- a/plugins/VisitTime/lang/en.json
+++ b/plugins/VisitTime/lang/en.json
@@ -1,7 +1,15 @@
{
"VisitTime": {
"ColumnLocalTime": "Local time",
+ "ColumnLocalHour": "Local time - hour (Start of visit)",
+ "ColumnLocalMinute": "Local time - minute (Start of visit)",
"ColumnServerTime": "Server time",
+ "ColumnServerHour": "Server time - hour",
+ "ColumnVisitEndServerHour": "Server time - hour (End of visit)",
+ "ColumnVisitEndServerMinute": "Server time - minute (End of visit)",
+ "ColumnVisitStartServerHour": "Server time - hour (Start of visit)",
+ "ColumnVisitStartServerMinute": "Server time - minute (Start of visit)",
+ "ColumnServerMinute": "Server time - minute",
"DayOfWeek": "Day of the week",
"LocalTime": "Visits per local time",
"NHour": "%sh",
diff --git a/plugins/VisitorInterest/Columns/PagesPerVisit.php b/plugins/VisitorInterest/Columns/PagesPerVisit.php
index 0d4bbe1a18..1f52ceedb9 100644
--- a/plugins/VisitorInterest/Columns/PagesPerVisit.php
+++ b/plugins/VisitorInterest/Columns/PagesPerVisit.php
@@ -13,8 +13,5 @@ use Piwik\Piwik;
class PagesPerVisit extends Dimension
{
- public function getName()
- {
- return Piwik::translate('VisitorInterest_ColumnPagesPerVisit');
- }
+ protected $nameSingular = 'VisitorInterest_ColumnPagesPerVisit';
} \ No newline at end of file
diff --git a/plugins/VisitorInterest/Columns/VisitDuration.php b/plugins/VisitorInterest/Columns/VisitDuration.php
index d0286bedd2..d3f88d4926 100644
--- a/plugins/VisitorInterest/Columns/VisitDuration.php
+++ b/plugins/VisitorInterest/Columns/VisitDuration.php
@@ -13,8 +13,7 @@ use Piwik\Piwik;
class VisitDuration extends Dimension
{
- public function getName()
- {
- return Piwik::translate('VisitorInterest_ColumnVisitDuration');
- }
+
+ protected $type = self::TYPE_DURATION_S;
+ protected $nameSingular = 'VisitorInterest_ColumnVisitDuration';
} \ No newline at end of file
diff --git a/plugins/VisitorInterest/Columns/VisitsByDaysSinceLastVisit.php b/plugins/VisitorInterest/Columns/VisitsByDaysSinceLastVisit.php
index b83cc9d72a..5415136975 100644
--- a/plugins/VisitorInterest/Columns/VisitsByDaysSinceLastVisit.php
+++ b/plugins/VisitorInterest/Columns/VisitsByDaysSinceLastVisit.php
@@ -10,7 +10,6 @@ namespace Piwik\Plugins\VisitorInterest\Columns;
use Piwik\Piwik;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Plugins\CoreHome\Segment;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visitor;
@@ -19,16 +18,9 @@ class VisitsByDaysSinceLastVisit extends VisitDimension
{
protected $columnName = 'visitor_days_since_last';
protected $columnType = 'SMALLINT(5) UNSIGNED NULL';
-
- protected function configureSegments()
- {
- $segment = new Segment();
- $segment->setSegment('daysSinceLastVisit');
- $segment->setName('General_DaysSinceLastVisit');
- $segment->setType(Segment::TYPE_METRIC);
-
- $this->addSegment($segment);
- }
+ protected $type = self::TYPE_NUMBER;
+ protected $segmentName = 'daysSinceLastVisit';
+ protected $nameSingular = 'General_DaysSinceLastVisit';
public function getName()
{
diff --git a/plugins/VisitorInterest/Columns/VisitsbyVisitNumber.php b/plugins/VisitorInterest/Columns/VisitsbyVisitNumber.php
index 7993fb1c24..9a2640af1f 100644
--- a/plugins/VisitorInterest/Columns/VisitsbyVisitNumber.php
+++ b/plugins/VisitorInterest/Columns/VisitsbyVisitNumber.php
@@ -13,8 +13,5 @@ use Piwik\Piwik;
class VisitsbyVisitNumber extends Dimension
{
- public function getName()
- {
- return Piwik::translate('VisitorInterest_visitsByVisitCount');
- }
+ protected $nameSingular = 'VisitorInterest_visitsByVisitCount';
} \ No newline at end of file