diff options
author | diosmosis <diosmosis@users.noreply.github.com> | 2020-06-26 16:17:54 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-26 16:17:54 +0300 |
commit | de5ae85e7a11f7bbd962256c890a32188c40d000 (patch) | |
tree | 2a5f303c83b6e80369d3ba77b2d9fea797c598d9 /plugins/CoreHome | |
parent | b12946909ff323ea2f7e7af04e4435d2dd503023 (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')
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 |