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:
authordiosmosis <diosmosis@users.noreply.github.com>2020-06-26 16:17:54 +0300
committerGitHub <noreply@github.com>2020-06-26 16:17:54 +0300
commitde5ae85e7a11f7bbd962256c890a32188c40d000 (patch)
tree2a5f303c83b6e80369d3ba77b2d9fea797c598d9 /plugins/CoreHome
parentb12946909ff323ea2f7e7af04e4435d2dd503023 (diff)
Track seconds instead of days for "days since" dimensions (#15774)
* Modify dimensions and add tests. * unfinished debugging commit * changes to fix test, remove tracker code, add update code * fix some tests * fix migration issue * fixing some tests * fix some bugs, update some expected test files, remove _idvc from some tests * start replacing _ects * Finish seconds since last ecommerce order change. * fix couple issues * fix a couple tests * fix some more tests * fixing a couple more tests * apply review feedback * unfinished commit * add back dimensions = * fixing tests & removing some code * fix some bugs + tests and remove debugging code * fixing some tests and issues * Some debugging code for the tracker in case of exceptions. * debug and fix another issue when tracking visits in the past * fix test * update JS and fix several tests * Fixing more tests. * Add missing files. * update expected test files * Add some unit tests. * update more expected files * update more test files * update more test files * update changelog and remove _ects query param * apply review feedback * fix merge issue * clearer code * fix migration issue * update expected files * update expected files again * updating tests * fix test * rebuilt piwik.js * unify previous visitor properties / original visit row approach * fixing some tests * Add new column version entries into the option table. * try undoing 1.5 update change * apply review feedback * remove more unused cookie values * rebuilt piwik.js * Fix test count. * update test files * rebuilt piwik.js * removel log analytics submodule update * update submodule * update some expected screenshots * Fix versions in omnifixture since we were probably adding to the beta update after it changed. * update screenshots
Diffstat (limited to 'plugins/CoreHome')
-rw-r--r--plugins/CoreHome/Columns/VisitLastActionTime.php8
-rw-r--r--plugins/CoreHome/Columns/VisitorDaysSinceFirst.php49
-rw-r--r--plugins/CoreHome/Columns/VisitorDaysSinceOrder.php40
-rw-r--r--plugins/CoreHome/Columns/VisitorReturning.php12
-rw-r--r--plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php86
-rw-r--r--plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php80
-rw-r--r--plugins/CoreHome/Columns/VisitsCount.php7
-rw-r--r--plugins/CoreHome/Tracker/VisitRequestProcessor.php2
-rw-r--r--plugins/CoreHome/VisitorDetails.php16
-rw-r--r--plugins/CoreHome/tests/Integration/Column/VisitLastActionTimeTest.php19
-rw-r--r--plugins/CoreHome/tests/Unit/Columns/VisitorReturningTest.php82
-rw-r--r--plugins/CoreHome/tests/Unit/Columns/VisitorSecondsSinceFirstTest.php140
-rw-r--r--plugins/CoreHome/tests/Unit/Columns/VisitorSecondsSinceOrderTest.php86
-rw-r--r--plugins/CoreHome/tests/Unit/Columns/VisitsCountTest.php67
14 files changed, 604 insertions, 90 deletions
diff --git a/plugins/CoreHome/Columns/VisitLastActionTime.php b/plugins/CoreHome/Columns/VisitLastActionTime.php
index 6dadc3a0ad..9b2bbe56d6 100644
--- a/plugins/CoreHome/Columns/VisitLastActionTime.php
+++ b/plugins/CoreHome/Columns/VisitLastActionTime.php
@@ -69,12 +69,12 @@ class VisitLastActionTime extends VisitDimension
return false;
}
- $originalVisit = $visitor->getVisitorColumn(VisitorRecognizer::KEY_ORIGINAL_VISIT_ROW);
+ $originalVisitLastActionTime = $visitor->getPreviousVisitColumn('visit_last_action_time');
- if (!empty($originalVisit['visit_last_action_time'])
- && Date::factory($originalVisit['visit_last_action_time'])->getTimestamp() > $request->getCurrentTimestamp()) {
+ if (!empty($originalVisitLastActionTime)
+ && Date::factory($originalVisitLastActionTime)->getTimestamp() > $request->getCurrentTimestamp()) {
// make sure to not set visit_last_action_time to an earlier time eg if tracking requests aren't sent in order
- return $originalVisit['visit_last_action_time'];
+ return $originalVisitLastActionTime;
}
return $this->onNewVisit($request, $visitor, $action);
diff --git a/plugins/CoreHome/Columns/VisitorDaysSinceFirst.php b/plugins/CoreHome/Columns/VisitorDaysSinceFirst.php
index c36dd78f48..dd0018300c 100644
--- a/plugins/CoreHome/Columns/VisitorDaysSinceFirst.php
+++ b/plugins/CoreHome/Columns/VisitorDaysSinceFirst.php
@@ -6,45 +6,32 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
+
namespace Piwik\Plugins\CoreHome\Columns;
+use Piwik\Columns\DimensionSegmentFactory;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Tracker\Action;
-use Piwik\Tracker\Request;
-use Piwik\Tracker\Visitor;
+use Piwik\Plugin\Segment;
+use Piwik\Segment\SegmentsList;
class VisitorDaysSinceFirst extends VisitDimension
{
- protected $columnName = 'visitor_days_since_first';
- protected $columnType = 'SMALLINT(5) UNSIGNED NULL';
- protected $segmentName = 'daysSinceFirstVisit';
- protected $nameSingular = 'General_DaysSinceFirstVisit';
protected $type = self::TYPE_NUMBER;
+ protected $sqlSegment = 'ROUND(log_visit.visitor_seconds_since_first / 86400)';
+ protected $nameSingular = 'General_DaysSinceFirstVisit';
+ protected $columnName = 'visitor_seconds_since_first';
+ protected $segmentName = 'daysSinceFirstVisit';
- /**
- * @param Request $request
- * @param Visitor $visitor
- * @param Action|null $action
- * @return mixed
- */
- public function onNewVisit(Request $request, Visitor $visitor, $action)
- {
- // if the visitor is new, force days since first to 0, to ignore any potential bad values for _idts
- if (!$visitor->isVisitorKnown()) {
- return 0;
- }
-
- return $request->getDaysSinceFirstVisit();
- }
-
- /**
- * @param Request $request
- * @param Visitor $visitor
- * @param Action|null $action
- * @return mixed
- */
- public function onAnyGoalConversion(Request $request, Visitor $visitor, $action)
+ public function configureSegments(SegmentsList $segmentsList, DimensionSegmentFactory $dimensionSegmentFactory)
{
- return $visitor->getVisitorColumn($this->columnName);
+ $segment = new Segment();
+ $segment->setSegment('daysSinceFirstVisit');
+ $segment->setName('General_DaysSinceFirstVisit');
+ $segment->setCategory('General_Visitors');
+ $segment->setSqlSegment('log_visit.visitor_seconds_since_first');
+ $segment->setSqlFilterValue(function ($value) {
+ return (int)$value * 86400;
+ });
+ $segmentsList->addSegment($dimensionSegmentFactory->createSegment($segment));
}
} \ No newline at end of file
diff --git a/plugins/CoreHome/Columns/VisitorDaysSinceOrder.php b/plugins/CoreHome/Columns/VisitorDaysSinceOrder.php
index 3e5feff5dc..0a033b5c63 100644
--- a/plugins/CoreHome/Columns/VisitorDaysSinceOrder.php
+++ b/plugins/CoreHome/Columns/VisitorDaysSinceOrder.php
@@ -6,47 +6,17 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
+
namespace Piwik\Plugins\CoreHome\Columns;
use Piwik\Plugin\Dimension\VisitDimension;
-use Piwik\Tracker\Action;
-use Piwik\Tracker\Request;
-use Piwik\Tracker\Visitor;
class VisitorDaysSinceOrder extends VisitDimension
{
- protected $columnName = 'visitor_days_since_order';
- protected $columnType = 'SMALLINT(5) UNSIGNED NULL';
- protected $segmentName = 'daysSinceLastEcommerceOrder';
protected $nameSingular = 'General_DaysSinceLastEcommerceOrder';
- protected $category = 'General_Visitors'; // todo put into ecommerce category?
+ protected $category = 'General_Visitors'; // todo put into ecommerce category?
protected $type = self::TYPE_NUMBER;
-
- /**
- * @param Request $request
- * @param Visitor $visitor
- * @param Action|null $action
- * @return mixed
- */
- public function onNewVisit(Request $request, Visitor $visitor, $action)
- {
- $daysSinceLastOrder = $request->getDaysSinceLastOrder();
-
- if ($daysSinceLastOrder === false) {
- $daysSinceLastOrder = 0;
- }
-
- return $daysSinceLastOrder;
- }
-
- /**
- * @param Request $request
- * @param Visitor $visitor
- * @param Action|null $action
- * @return mixed
- */
- public function onAnyGoalConversion(Request $request, Visitor $visitor, $action)
- {
- return $visitor->getVisitorColumn($this->columnName);
- }
+ protected $columnName = 'visitor_seconds_since_order';
+ protected $sqlSegment = 'FLOOR(log_visit.visitor_seconds_since_order / 86400)';
+ protected $segmentName = 'daysSinceLastEcommerceOrder';
} \ No newline at end of file
diff --git a/plugins/CoreHome/Columns/VisitorReturning.php b/plugins/CoreHome/Columns/VisitorReturning.php
index 78138cc02f..b880986b84 100644
--- a/plugins/CoreHome/Columns/VisitorReturning.php
+++ b/plugins/CoreHome/Columns/VisitorReturning.php
@@ -71,18 +71,16 @@ class VisitorReturning extends VisitDimension
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
- $daysSinceLastOrder = $request->getDaysSinceLastOrder();
- $isReturningCustomer = ($daysSinceLastOrder !== false);
+ $hasOrder = $visitor->getVisitorColumn('visitor_seconds_since_order')
+ ?: $visitor->getPreviousVisitColumn('visitor_seconds_since_order')
+ ?: $request->getParam('ec_id');
+ $isReturningCustomer = (bool) $hasOrder;
if ($isReturningCustomer) {
return self::IS_RETURNING_CUSTOMER;
}
- $visitCount = $request->getVisitCount();
- $daysSinceFirstVisit = $request->getDaysSinceFirstVisit();
- $daysSinceLastVisit = $request->getDaysSinceLastVisit();
-
- if ($visitCount > 1 || $visitor->isVisitorKnown() || $daysSinceFirstVisit > 0 || $daysSinceLastVisit > 0) {
+ if ($visitor->isVisitorKnown()) {
return self::IS_RETURNING;
}
diff --git a/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php b/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php
new file mode 100644
index 0000000000..bed71d3328
--- /dev/null
+++ b/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Columns;
+
+use Piwik\Common;
+use Piwik\Date;
+use Piwik\Plugin\Dimension\VisitDimension;
+use Piwik\Plugin\Segment;
+use Piwik\Tracker\Action;
+use Piwik\Tracker\Request;
+use Piwik\Tracker\Visitor;
+
+class VisitorSecondsSinceFirst extends VisitDimension
+{
+ const COLUMN_TYPE = 'INT(11) UNSIGNED NULL';
+
+ protected $columnName = 'visitor_seconds_since_first';
+ protected $columnType = self::COLUMN_TYPE;
+ protected $segmentName = 'secondsSinceFirstVisit';
+ protected $nameSingular = 'General_SecondsSinceFirstVisit';
+ protected $type = self::TYPE_NUMBER;
+
+ /**
+ * @param Request $request
+ * @param Visitor $visitor
+ * @param Action|null $action
+ * @return mixed
+ */
+ public function onNewVisit(Request $request, Visitor $visitor, $action)
+ {
+ if (!$visitor->isVisitorKnown()) {
+ return 0;
+ }
+
+ $prevSecondsSinceFirst = $visitor->getPreviousVisitColumn('visitor_seconds_since_first');
+
+ // no data for previous visit, we can't calculate for this one
+ if ($prevSecondsSinceFirst === null
+ || $prevSecondsSinceFirst === false
+ || $prevSecondsSinceFirst === ''
+ ) {
+ return null;
+ }
+
+ $prevVisitStart = $visitor->getPreviousVisitColumn('visit_first_action_time');
+ $currentVisitStart = $visitor->getVisitorColumn('visit_first_action_time');
+ if (empty($prevVisitStart)
+ || empty($currentVisitStart)
+ ) {
+ Common::printDebug("Unexpected: found empty visit first action time for either previous or current visit (previous = $prevVisitStart, current = $currentVisitStart)");
+ return null;
+ }
+
+ try {
+ $timeBetweenVisitStarts = Date::factory($currentVisitStart)->getTimestamp() - Date::factory($prevVisitStart)->getTimestamp();
+ } catch (\Exception $ex) {
+ Common::printDebug("Error in parsing current/previous visit start datetime values: " . $ex->getMessage());
+ return null;
+ }
+
+ $newVisitorSecondsSinceFirst = $prevSecondsSinceFirst + $timeBetweenVisitStarts;
+
+ if ($newVisitorSecondsSinceFirst < 0) { // visit in the past
+ return null;
+ }
+
+ return $newVisitorSecondsSinceFirst;
+ }
+
+ /**
+ * @param Request $request
+ * @param Visitor $visitor
+ * @param Action|null $action
+ * @return mixed
+ */
+ public function onAnyGoalConversion(Request $request, Visitor $visitor, $action)
+ {
+ return $visitor->getVisitorColumn($this->columnName);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php b/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php
new file mode 100644
index 0000000000..8837bfdd7b
--- /dev/null
+++ b/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreHome\Columns;
+
+use Piwik\Date;
+use Piwik\Plugin\Dimension\VisitDimension;
+use Piwik\Plugin\Segment;
+use Piwik\Tracker\Action;
+use Piwik\Tracker\Request;
+use Piwik\Tracker\Visitor;
+
+class VisitorSecondsSinceOrder extends VisitDimension
+{
+ const COLUMN_TYPE = 'INT(11) UNSIGNED NULL';
+
+ protected $columnName = 'visitor_seconds_since_order';
+ protected $columnType = self::COLUMN_TYPE;
+ protected $segmentName = 'secondsSinceLastEcommerceOrder';
+ protected $nameSingular = 'General_SecondsSinceLastEcommerceOrder';
+ protected $category = 'General_Visitors'; // todo put into ecommerce category?
+ protected $type = self::TYPE_NUMBER;
+
+ /**
+ * @param Request $request
+ * @param Visitor $visitor
+ * @param Action|null $action
+ * @return mixed
+ */
+ public function onNewVisit(Request $request, Visitor $visitor, $action)
+ {
+ return $this->onExistingVisit($request, $visitor, $action);
+ }
+
+ public function onExistingVisit(Request $request, Visitor $visitor, $action)
+ {
+ $idorder = $request->getParam('ec_id');
+ $isOrder = !empty($idorder);
+ if ($isOrder) {
+ return 0;
+ }
+
+ $existingValue = $visitor->getVisitorColumn($this->columnName);
+ if ($existingValue !== null && $existingValue !== false) { // already set
+ return $existingValue;
+ }
+
+ $prevSecondsSinceLastOrder = $visitor->getPreviousVisitColumn($this->columnName);
+ if ($prevSecondsSinceLastOrder === null || $prevSecondsSinceLastOrder === false) { // no order at all for visitor
+ return null;
+ }
+
+ $visitFirstActionTime = $visitor->getPreviousVisitColumn('visit_first_action_time');
+ if ($visitFirstActionTime === null || $visitFirstActionTime === false) { // no previous visit
+ return null;
+ }
+
+ $visitFirstActionTime = Date::factory($visitFirstActionTime)->getTimestamp();
+ $secondsSinceLastAction = $request->getCurrentTimestamp() - $visitFirstActionTime;
+
+ $secondsSinceLastOrder = $prevSecondsSinceLastOrder + $secondsSinceLastAction;
+ return $secondsSinceLastOrder;
+ }
+
+ /**
+ * @param Request $request
+ * @param Visitor $visitor
+ * @param Action|null $action
+ * @return mixed
+ */
+ public function onAnyGoalConversion(Request $request, Visitor $visitor, $action)
+ {
+ return $visitor->getVisitorColumn($this->columnName);
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/Columns/VisitsCount.php b/plugins/CoreHome/Columns/VisitsCount.php
index 54c8050f69..6e1d65840b 100644
--- a/plugins/CoreHome/Columns/VisitsCount.php
+++ b/plugins/CoreHome/Columns/VisitsCount.php
@@ -36,7 +36,12 @@ class VisitsCount extends VisitDimension
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
- return $request->getVisitCount();
+ $previousVisitCount = $visitor->getPreviousVisitColumn($this->columnName);
+ if ($previousVisitCount === false || $previousVisitCount === null || $previousVisitCount === '') {
+ return 1;
+ }
+ $result = $previousVisitCount + 1;
+ return $result;
}
/**
diff --git a/plugins/CoreHome/Tracker/VisitRequestProcessor.php b/plugins/CoreHome/Tracker/VisitRequestProcessor.php
index ade0ab2301..69cef60230 100644
--- a/plugins/CoreHome/Tracker/VisitRequestProcessor.php
+++ b/plugins/CoreHome/Tracker/VisitRequestProcessor.php
@@ -120,6 +120,8 @@ class VisitRequestProcessor extends RequestProcessor
$isNewVisit = $this->isVisitNew($visitProperties, $request, $this->visitorRecognizer->getLastKnownVisit());
$request->setMetadata('CoreHome', 'isNewVisit', $isNewVisit);
+ $request->setMetadata('CoreHome', 'lastKnownVisit', $this->visitorRecognizer->getLastKnownVisit());
+
if (!$isNewVisit) { // only copy over known visitor's information, if this is for an ongoing visit
$this->visitorRecognizer->updateVisitPropertiesFromLastVisitRow($visitProperties);
}
diff --git a/plugins/CoreHome/VisitorDetails.php b/plugins/CoreHome/VisitorDetails.php
index ad6a531d43..2c32a9a1cd 100644
--- a/plugins/CoreHome/VisitorDetails.php
+++ b/plugins/CoreHome/VisitorDetails.php
@@ -25,7 +25,9 @@ class VisitorDetails extends VisitorDetailsAbstract
$visitor['visitEcommerceStatus'] = $this->getVisitEcommerceStatus();
$visitor['visitEcommerceStatusIcon'] = $this->getVisitEcommerceStatusIcon();
$visitor['daysSinceFirstVisit'] = $this->getDaysSinceFirstVisit();
+ $visitor['secondsSinceFirstVisit'] = $this->getSecondsSinceFirstVisit();
$visitor['daysSinceLastEcommerceOrder'] = $this->getDaysSinceLastEcommerceOrder();
+ $visitor['secondsSinceLastEcommerceOrder'] = $this->getSecondsSinceLastEcommerceOrder();
$visitor['visitDuration'] = $this->getVisitLength();
$visitor['visitDurationPretty'] = $this->getVisitLengthPretty();
}
@@ -62,12 +64,22 @@ class VisitorDetails extends VisitorDetailsAbstract
protected function getDaysSinceFirstVisit()
{
- return $this->details['visitor_days_since_first'];
+ return floor($this->details['visitor_seconds_since_first'] / 86400);
+ }
+
+ protected function getSecondsSinceFirstVisit()
+ {
+ return $this->details['visitor_seconds_since_first'];
}
protected function getDaysSinceLastEcommerceOrder()
{
- return $this->details['visitor_days_since_order'];
+ return floor($this->details['visitor_seconds_since_order'] / 86400);
+ }
+
+ protected function getSecondsSinceLastEcommerceOrder()
+ {
+ return $this->details['visitor_seconds_since_order'];
}
protected function getVisitorReturning()
diff --git a/plugins/CoreHome/tests/Integration/Column/VisitLastActionTimeTest.php b/plugins/CoreHome/tests/Integration/Column/VisitLastActionTimeTest.php
index 2d82d93689..6940c9074a 100644
--- a/plugins/CoreHome/tests/Integration/Column/VisitLastActionTimeTest.php
+++ b/plugins/CoreHome/tests/Integration/Column/VisitLastActionTimeTest.php
@@ -16,6 +16,7 @@ use Piwik\Db;
use Piwik\Metrics;
use Piwik\Plugins\CoreHome\Columns\UserId;
use Piwik\Plugins\CoreHome\Columns\VisitLastActionTime;
+use Piwik\Plugins\CoreHome\Tracker\LogTable\Visit;
use Piwik\Tests\Framework\Fixture;
use Piwik\Tests\Framework\Mock\FakeAccess;
use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
@@ -57,12 +58,12 @@ class VisitLastActionTimeTest extends IntegrationTestCase
return new Request($request);
}
- private function getVisitor()
+ private function getVisitor(VisitProperties $previousProperties = null)
{
$visit = new VisitProperties();
$visit->setProperty('idvisit', '321');
$visit->setProperty('idvisitor', Common::hex2bin('1234567890234567'));
- $visitor = new Visitor($visit, $isKnown = false);
+ $visitor = new Visitor($visit, $isKnown = false, $previousProperties);
return $visitor;
}
@@ -93,10 +94,9 @@ class VisitLastActionTimeTest extends IntegrationTestCase
$request = $this->makeRequest(array('cdt' => $now));
$this->assertEquals($now, $request->getCurrentTimestamp());
- $visitor = $this->getVisitor();
- $visitor->setVisitorColumn(VisitorRecognizer::KEY_ORIGINAL_VISIT_ROW,
- array('visit_last_action_time' => Date::factory($previousTime)->getDatetime())
- );
+ $visitor = $this->getVisitor(new VisitProperties([
+ 'visit_last_action_time' => Date::factory($previousTime)->getDatetime(),
+ ]));
$expected = Date::factory($now)->getDatetime();
$this->assertSame($expected, $this->lastAction->onExistingVisit($request, $visitor, $action = null));
@@ -109,10 +109,9 @@ class VisitLastActionTimeTest extends IntegrationTestCase
$request = $this->makeRequest(array('cdt' => $now));
$this->assertEquals($now, $request->getCurrentTimestamp());
- $visitor = $this->getVisitor();
- $visitor->setVisitorColumn(VisitorRecognizer::KEY_ORIGINAL_VISIT_ROW,
- array('visit_last_action_time' => Date::factory($previousTime)->getDatetime())
- );
+ $visitor = $this->getVisitor(new VisitProperties([
+ 'visit_last_action_time' => Date::factory($previousTime)->getDatetime(),
+ ]));
$expected = Date::factory($previousTime)->getDatetime();
// should keep existing visit last action time
diff --git a/plugins/CoreHome/tests/Unit/Columns/VisitorReturningTest.php b/plugins/CoreHome/tests/Unit/Columns/VisitorReturningTest.php
new file mode 100644
index 0000000000..86be732733
--- /dev/null
+++ b/plugins/CoreHome/tests/Unit/Columns/VisitorReturningTest.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+namespace Piwik\Plugins\CoreHome\tests\Unit\Columns;
+
+use PHPUnit\Framework\TestCase;
+use Piwik\Plugins\CoreHome\Columns\VisitorReturning;
+use Piwik\Tracker\Request;
+use Piwik\Tracker\Visit\VisitProperties;
+use Piwik\Tracker\Visitor;
+
+class VisitorReturningTest extends TestCase
+{
+ public function test_onNewVisit_returnsReturningCustomerIfVisitHasOrder()
+ {
+ $dim = new VisitorReturning();
+ $result = $dim->onNewVisit($this->makeMockRequest([ 'ec_id' => 'abcdefg' ]), $this->makeMockVisitor(true), null);
+ $this->assertEquals(VisitorReturning::IS_RETURNING_CUSTOMER, $result);
+ }
+
+ public function test_onNewVisit_returnsReturningCustomerIfVisitHasSecondsSinceLastOrder()
+ {
+ $dim = new VisitorReturning();
+ $result = $dim->onNewVisit($this->makeMockRequest(), $this->makeMockVisitor(true, [ 'visitor_seconds_since_order' => 1234 ]), null);
+ $this->assertEquals(VisitorReturning::IS_RETURNING_CUSTOMER, $result);
+ }
+
+ public function test_onNewVisit_returnsReturningCustomerIfPrevVisitHasSecondsSinceLastOrder()
+ {
+ $dim = new VisitorReturning();
+ $result = $dim->onNewVisit($this->makeMockRequest(), $this->makeMockVisitor(true, [], [ 'visitor_seconds_since_order' => 5678 ]), null);
+ $this->assertEquals(VisitorReturning::IS_RETURNING_CUSTOMER, $result);
+ }
+
+ public function test_onNewVisit_returnsReturningVisitorIfVisitorIsKnown()
+ {
+ $dim = new VisitorReturning();
+ $result = $dim->onNewVisit($this->makeMockRequest(), $this->makeMockVisitor(true), null);
+ $this->assertEquals(VisitorReturning::IS_RETURNING, $result);
+ }
+
+ public function test_onNewVisit_returnsNewVisitIfVisitorIsNotKnown()
+ {
+ $dim = new VisitorReturning();
+ $result = $dim->onNewVisit($this->makeMockRequest(), $this->makeMockVisitor(false), null);
+ $this->assertEquals(VisitorReturning::IS_NEW, $result);
+ }
+
+ /**
+ * @return Request
+ */
+ private function makeMockRequest($params = [], $currentTime = null)
+ {
+ $mockBuilder = $this->getMockBuilder(Request::class)->disableOriginalConstructor();
+ if ($currentTime) {
+ $mockBuilder->onlyMethods(['getCurrentTimestamp']);
+ }
+ $mock = $mockBuilder->getMock();
+ if ($currentTime) {
+ $mock->method('getCurrentTimestamp')->willReturn($currentTime);
+ }
+ $mock->method('getParam')->willReturnCallback(function ($name) use ($params) {
+ return isset($params[$name]) ? $params[$name] : false;
+ });
+
+ /** @var Request $mock */
+ $result = $mock;
+ return $result;
+ }
+
+ private function makeMockVisitor($isKnown, $visitProps = [], $previousVisitProps = [])
+ {
+ $visitor = new Visitor(new VisitProperties($visitProps), $isKnown, new VisitProperties($previousVisitProps));
+ return $visitor;
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/tests/Unit/Columns/VisitorSecondsSinceFirstTest.php b/plugins/CoreHome/tests/Unit/Columns/VisitorSecondsSinceFirstTest.php
new file mode 100644
index 0000000000..71f468a331
--- /dev/null
+++ b/plugins/CoreHome/tests/Unit/Columns/VisitorSecondsSinceFirstTest.php
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+namespace Piwik\Plugins\CoreHome\tests\Unit\Columns;
+
+use PHPUnit\Framework\TestCase;
+use Piwik\Plugins\CoreHome\Columns\VisitorSecondsSinceFirst;
+use Piwik\Tracker\Request;
+use Piwik\Tracker\Visit\VisitProperties;
+use Piwik\Tracker\Visitor;
+
+class VisitorSecondsSinceFirstTest extends TestCase
+{
+ public function test_onNewVisit_returnsZeroIfVisitorIsUnknown()
+ {
+ $request = $this->makeMockRequest();
+ $visitor = $this->makeMockVisitor(false);
+
+ $dim = new VisitorSecondsSinceFirst();
+ $result = $dim->onNewVisit($request, $visitor, null);
+
+ $this->assertEquals(0, $result);
+ }
+
+ /**
+ * @dataProvider getInvalidTestDataForOnNewVisit
+ */
+ public function test_onNewVisit_returnsNullIfPreviousColumnValueOrCurrentColumnValueIsInvalid($currentProps, $oldProps)
+ {
+ $request = $this->makeMockRequest();
+ $visitor = $this->makeMockVisitor(true, $currentProps, $oldProps);
+
+ $dim = new VisitorSecondsSinceFirst();
+ $result = $dim->onNewVisit($request, $visitor, null);
+
+ $this->assertNull($result);
+ }
+
+ public function getInvalidTestDataForOnNewVisit()
+ {
+ return [
+ [
+ ['visit_first_action_time' => ''],
+ ['visit_first_action_time' => '2016-02-03 00:00:00', 'visitor_seconds_since_first' => '250'],
+ ],
+
+ [
+ ['visit_first_action_time' => 0],
+ ['visit_first_action_time' => '2016-02-03 00:00:00', 'visitor_seconds_since_first' => '250'],
+ ],
+
+ [
+ ['visit_first_action_time' => null],
+ ['visit_first_action_time' => '2016-02-03 00:00:00', 'visitor_seconds_since_first' => '250'],
+ ],
+
+ [
+ ['visit_first_action_time' => 'asdlfj alskdjf'],
+ ['visit_first_action_time' => '2016-02-03 00:00:00', 'visitor_seconds_since_first' => '250'],
+ ],
+
+ [
+ ['visit_first_action_time' => '2016-02-03 00:00:00'],
+ ['visit_first_action_time' => '', 'visitor_seconds_since_first' => '250'],
+ ],
+
+ [
+ ['visit_first_action_time' => '2016-02-03 00:00:00'],
+ ['visit_first_action_time' => 0, 'visitor_seconds_since_first' => '250'],
+ ],
+
+ [
+ ['visit_first_action_time' => '2016-02-03 00:00:00'],
+ ['visit_first_action_time' => null, 'visitor_seconds_since_first' => '250'],
+ ],
+
+ [
+ ['visit_first_action_time' => '2016-02-03 00:00:00'],
+ ['visit_first_action_time' => 'asdlfj alskdjf', 'visitor_seconds_since_first' => '250'],
+ ],
+
+ [
+ ['visit_first_action_time' => '2016-02-03 00:00:00'],
+ ['visit_first_action_time' => '2016-04-05 00:00:00', 'visitor_seconds_since_first' => ''],
+ ],
+ [
+ ['visit_first_action_time' => '2016-02-03 00:00:00'],
+ ['visit_first_action_time' => '2016-04-05 00:00:00', 'visitor_seconds_since_first' => null],
+ ],
+ [
+ ['visit_first_action_time' => '2016-02-03 00:00:00'],
+ ['visit_first_action_time' => '2016-04-05 00:00:00', 'visitor_seconds_since_first' => false],
+ ],
+ ];
+ }
+
+ public function test_onNewVisit_returnsCorrectValueWhenVisitorIsKnownAndAllFirstActionTimesPresent()
+ {
+ $currentTime = time();
+
+ $request = $this->makeMockRequest($currentTime);
+ $visitor = $this->makeMockVisitor(true, ['visit_first_action_time' => $currentTime - 200], ['visit_first_action_time' => $currentTime - 300, 'visitor_seconds_since_first' => 500]);
+
+ $dim = new VisitorSecondsSinceFirst();
+ $result = $dim->onNewVisit($request, $visitor, null);
+
+ $this->assertEquals($result, 600);
+ }
+
+ /**
+ * @return Request
+ */
+ private function makeMockRequest($currentTime = null)
+ {
+ $mockBuilder = $this->getMockBuilder(Request::class)->disableOriginalConstructor();
+ if ($currentTime) {
+ $mockBuilder->onlyMethods(['getCurrentTimestamp']);
+ }
+ $mock = $mockBuilder->getMock();
+ if ($currentTime) {
+ $mock->method('getCurrentTimestamp')->willReturn($currentTime);
+ }
+
+ /** @var Request $mock */
+ $result = $mock;
+ return $result;
+ }
+
+ private function makeMockVisitor($isKnown, $visitProps = [], $previousVisitProps = [])
+ {
+ $visitor = new Visitor(new VisitProperties($visitProps), $isKnown, new VisitProperties($previousVisitProps));
+ return $visitor;
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/tests/Unit/Columns/VisitorSecondsSinceOrderTest.php b/plugins/CoreHome/tests/Unit/Columns/VisitorSecondsSinceOrderTest.php
new file mode 100644
index 0000000000..92d3f5b178
--- /dev/null
+++ b/plugins/CoreHome/tests/Unit/Columns/VisitorSecondsSinceOrderTest.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+namespace Piwik\Plugins\CoreHome\tests\Unit\Columns;
+
+use PHPUnit\Framework\TestCase;
+use Piwik\Plugins\CoreHome\Columns\VisitorSecondsSinceOrder;
+use Piwik\Tracker\Request;
+use Piwik\Tracker\Visit\VisitProperties;
+use Piwik\Tracker\Visitor;
+
+class VisitorSecondsSinceOrderTest extends TestCase
+{
+ public function test_onExistingVisit_returnsZeroIfTheVisitHasAnOrder()
+ {
+ $dim = new VisitorSecondsSinceOrder();
+ $result = $dim->onExistingVisit($this->makeMockRequest([ 'ec_id' => 'abljasdf' ]), $this->makeMockVisitor(true), null);
+ $this->assertEquals(0, $result);
+ }
+
+ public function test_onExistingVisit_returnsTheExistingValueIfThereIsOne()
+ {
+ $dim = new VisitorSecondsSinceOrder();
+ $result = $dim->onExistingVisit($this->makeMockRequest(), $this->makeMockVisitor(true, [ 'visitor_seconds_since_order' => 20 ]), null);
+ $this->assertEquals(20, $result);
+ }
+
+ public function test_onExistingVisit_returnsNullIfDimensionValueIsNotSetForPreviousVisit()
+ {
+ $dim = new VisitorSecondsSinceOrder();
+ $result = $dim->onExistingVisit($this->makeMockRequest(), $this->makeMockVisitor(true), null);
+ $this->assertEquals(null, $result);
+ }
+
+ public function test_onExistingVisit_returnsCorrectValueIfPreviousValueWasForOrder()
+ {
+ $dim = new VisitorSecondsSinceOrder();
+ $result = $dim->onExistingVisit($this->makeMockRequest([], '2020-03-04 03:04:28'), $this->makeMockVisitor(true, [], [ 'visitor_seconds_since_order' => 0, 'visit_first_action_time' => '2020-03-04 03:04:20' ]), null);
+ $this->assertEquals(8, $result);
+ }
+
+ public function test_onExistingVisit_returnsCorrectValueIfPreviousValueWasAfterOrder()
+ {
+ $dim = new VisitorSecondsSinceOrder();
+ $result = $dim->onExistingVisit($this->makeMockRequest([], '2020-03-04 03:04:28'), $this->makeMockVisitor(true, [], [ 'visitor_seconds_since_order' => 45, 'visit_first_action_time' => '2020-03-04 03:04:20' ]), null);
+ $this->assertEquals(53, $result);
+ }
+
+ /**
+ * @return Request
+ */
+ private function makeMockRequest($params = [], $currentTime = null)
+ {
+ if (is_string($currentTime)) {
+ $currentTime = strtotime($currentTime);
+ }
+
+ $mockBuilder = $this->getMockBuilder(Request::class)->disableOriginalConstructor();
+ if ($currentTime) {
+ $mockBuilder->onlyMethods(['getCurrentTimestamp', 'getParam']);
+ }
+ $mock = $mockBuilder->getMock();
+ if ($currentTime) {
+ $mock->method('getCurrentTimestamp')->willReturn($currentTime);
+ }
+ $mock->method('getParam')->willReturnCallback(function ($name) use ($params) {
+ return isset($params[$name]) ? $params[$name] : false;
+ });
+
+ /** @var Request $mock */
+ $result = $mock;
+ return $result;
+ }
+
+ private function makeMockVisitor($isKnown, $visitProps = [], $previousVisitProps = [])
+ {
+ $visitor = new Visitor(new VisitProperties($visitProps), $isKnown, new VisitProperties($previousVisitProps));
+ return $visitor;
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreHome/tests/Unit/Columns/VisitsCountTest.php b/plugins/CoreHome/tests/Unit/Columns/VisitsCountTest.php
new file mode 100644
index 0000000000..2a62848159
--- /dev/null
+++ b/plugins/CoreHome/tests/Unit/Columns/VisitsCountTest.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+namespace Piwik\Plugins\CoreHome\tests\Unit\Columns;
+
+
+use PHPUnit\Framework\TestCase;
+use Piwik\Plugins\CoreHome\Columns\VisitsCount;
+use Piwik\Tracker\Request;
+use Piwik\Tracker\Visit\VisitProperties;
+use Piwik\Tracker\Visitor;
+
+class VisitsCountTest extends TestCase
+{
+ public function test_onNewVisit_returnsZeroIfPreviousVisitCountDoesNotExist()
+ {
+ $request = $this->makeMockRequest();
+ $visitor = $this->makeMockVisitor(false);
+
+ $dim = new VisitsCount();
+ $visitCount = $dim->onNewVisit($request, $visitor, null);
+
+ $this->assertEquals(1, $visitCount);
+ }
+
+ public function test_onNewVisit_returnsIncrementedValueIfPreviousVisitCountIsPresent()
+ {
+ $request = $this->makeMockRequest();
+ $visitor = $this->makeMockVisitor(false, [], ['visitor_count_visits' => 10]);
+
+ $dim = new VisitsCount();
+ $visitCount = $dim->onNewVisit($request, $visitor, null);
+
+ $this->assertEquals(11, $visitCount);
+ }
+
+ /**
+ * @return Request
+ */
+ private function makeMockRequest($currentTime = null)
+ {
+ $mockBuilder = $this->getMockBuilder(Request::class)->disableOriginalConstructor();
+ if ($currentTime) {
+ $mockBuilder->onlyMethods(['getCurrentTimestamp']);
+ }
+ $mock = $mockBuilder->getMock();
+ if ($currentTime) {
+ $mock->method('getCurrentTimestamp')->willReturn($currentTime);
+ }
+
+ /** @var Request $mock */
+ $result = $mock;
+ return $result;
+ }
+
+ private function makeMockVisitor($isKnown, $visitProps = [], $previousVisitProps = [])
+ {
+ $visitor = new Visitor(new VisitProperties($visitProps), $isKnown, new VisitProperties($previousVisitProps));
+ return $visitor;
+ }
+} \ No newline at end of file