From 809f45f628aa32e6b3b2323f0a2c8937aecae5a2 Mon Sep 17 00:00:00 2001 From: regevbr Date: Sun, 14 Jul 2019 12:51:21 +0300 Subject: [PATCH 1/3] User timezone should also be evaluated from user details #18 --- Helper/TimingHelper.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Helper/TimingHelper.php b/Helper/TimingHelper.php index e8fea7c..6e8ec42 100644 --- a/Helper/TimingHelper.php +++ b/Helper/TimingHelper.php @@ -240,7 +240,8 @@ private function getNextRunDate( //attempt to use the contact's timezone (if directed) if($timing->useContactTimezone()) { - if( ! $lead->getIpAddresses()->isEmpty()) { + $timezone = $lead->getTimezone(); + if(empty($timezone) && ! $lead->getIpAddresses()->isEmpty()) { /** @var $ipDetails array */ $ipDetails = $lead->getIpAddresses()->first()->getIpDetails(); if( ! empty($ipDetails['timezone'])) { @@ -250,12 +251,12 @@ private function getNextRunDate( } //if no timezone is set yet, try to get it from the Timing settings. - if(($timezone == null) && ($timing->getTimezone() != null)) { + if(empty($timezone) && ($timing->getTimezone() != null)) { $timezone = $timing->getTimezone(); } //if no timezone is set yet, use the system's default timezone. - if($timezone == null) { + if(empty($timezone)) { $timezone = date_default_timezone_get(); } From c6f9bff7de9676e9fca1a369105b06a440c0e4d9 Mon Sep 17 00:00:00 2001 From: regevbr Date: Mon, 15 Jul 2019 10:00:04 +0300 Subject: [PATCH 2/3] User timezone should also be evaluated from user details #18 --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dda5dce..2c33c68 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ For example, you could add a cron expression that only allows sending on weekday Note: newer versions of Mautic just have an "Install/Upgrade Plugins" button (without the dropdown arrow). 5. You should now see the Timing plugin in your list of plugins. -6. Run the following console commands to ensure that the database was updated: +6. Run the following console commands to update the database: ``` php app/console doctrine:schema:update --dump-sql @@ -53,7 +53,11 @@ Example: When this field is enabled, the plugin will evaluate the cron expression off of the Contact's time zone. This allows you to only send emails during the Contact's working hours. -If the Contact's time zone isn't known, the plugin will fall back to the system default time zone or the time zone that you set with the Time Zone field (see below.) +The contact time zone is evaluated in the following order: +1. The timezone field of the contact (e.g. `mautic.lead.field.timezone`), else: +2. The timezone of the last ip address used by the contact, else: +3. The value of the `Time Zone Field` in the action, else: +4. The system default time zone #### Time Zone Field From 6fd53084d5f3163f5aa8e3765e055b87ff163732 Mon Sep 17 00:00:00 2001 From: regevbr Date: Mon, 15 Jul 2019 11:02:44 +0300 Subject: [PATCH 3/3] User timezone should also be evaluated from user details #18 --- README.md | 4 +- Tests/Helper/TimingHelperTest.php | 87 ++++++++++++++++++++++++++++--- 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 2c33c68..143799c 100644 --- a/README.md +++ b/README.md @@ -78,10 +78,10 @@ apk update && apk add ca-certificates && update-ca-certificates && apk add opens #### Running the Tests -Once PHPUnit is installed, you can run the tests by navigating to the root directory of this plugin and running: +Put the plugin dir in mautic plugins dir (`./plugins`) and run in `mautic` root dir: ``` -phpunit +bin/phpunit --bootstrap vendor/autoload.php --configuration app/phpunit.xml.dist 'MauticPlugin\ThirdSetMauticTimingBundle\Tests\Helper\TimingHelperTest' plugins/ThirdSetMauticTimingBundle/Tests/Helper/TimingHelperTest.php ``` ## Credits diff --git a/Tests/Helper/TimingHelperTest.php b/Tests/Helper/TimingHelperTest.php index 3eaef2b..b06843f 100644 --- a/Tests/Helper/TimingHelperTest.php +++ b/Tests/Helper/TimingHelperTest.php @@ -163,6 +163,8 @@ public function testCheckEventTimingCorrectlyReturnsTrueForADueSimpleExpression( $eventData = array(); $eventData['id'] = 1; + $eventData['decisionPath'] = null; + $eventData['triggerMode'] = null; /* @var $timingHelper \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper */ $timingHelper = $this->getTimingHelper($timing); @@ -204,6 +206,8 @@ public function testCheckEventTimingCorrectlyReturnsDateTimeWhenScheduled() $eventData = array(); $eventData['id'] = 1; + $eventData['decisionPath'] = null; + $eventData['triggerMode'] = null; /* @var $timingHelper \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper */ $timingHelper = $this->getTimingHelper($timing); @@ -224,12 +228,12 @@ public function testCheckEventTimingCorrectlyReturnsDateTimeWhenScheduled() } /** - * @testdox checkEventTiming correctly returns true when a *lead's* time + * @testdox checkEventTiming correctly returns true when a *lead's* ip time * zone makes it due. * * @covers \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper::checkEventTiming */ - public function testCheckEventTimingCorrectlyReturnsTrueWhenContactsTimezoneMakesItDue() + public function testCheckEventTimingCorrectlyReturnsTrueWhenContactsIpTimezoneMakesItDue() { //the time and expression would return false, but the offset should //cause them to return true instead. @@ -246,6 +250,8 @@ public function testCheckEventTimingCorrectlyReturnsTrueWhenContactsTimezoneMake $eventData = array(); $eventData['id'] = 1; + $eventData['decisionPath'] = null; + $eventData['triggerMode'] = null; /* @var $timingHelper \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper */ $timingHelper = $this->getTimingHelper($timing); @@ -265,6 +271,50 @@ public function testCheckEventTimingCorrectlyReturnsTrueWhenContactsTimezoneMake $this->assertTrue($eventTriggerDate); } + /** + * @testdox checkEventTiming correctly returns true when a *lead's* field time + * zone makes it due. + * + * @covers \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper::checkEventTiming + */ + public function testCheckEventTimingCorrectlyReturnsTrueWhenContactsFieldTimezoneMakesItDue() + { + //the time and expression would return false, but the offset should + //cause them to return true instead. + $mockNow = '2016-01-01 10:00:00'; + $expression = '* 01-06 * * *'; + $useContactTimezone = true; + $contactTimezone = 'America/New_York'; // -5 + + /* @var $timing \MauticPlugin\ThirdSetMauticTimingBundle\Entity\Timing */ + $timing = $this->getMockTiming( + $expression, + $useContactTimezone + ); + + $eventData = array(); + $eventData['id'] = 1; + $eventData['decisionPath'] = null; + $eventData['triggerMode'] = null; + + /* @var $timingHelper \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper */ + $timingHelper = $this->getTimingHelper($timing); + + /* @var $lead \Mautic\LeadBundle\Entity\Lead */ + $lead = $this->getMockLead(null, $contactTimezone); + + //call the function + $eventTriggerDate = $timingHelper->checkEventTiming( + $eventData, + null, + false, + $lead, + $mockNow + ); + + $this->assertTrue($eventTriggerDate); + } + /** * @testdox checkEventTiming correctly returns a DateTime when a *lead's* * time zone makes it not due. @@ -289,6 +339,8 @@ public function testCheckEventTimingCorrectlyReturnsDateTimeWhenContactsTimezone $eventData = array(); $eventData['id'] = 1; + $eventData['decisionPath'] = null; + $eventData['triggerMode'] = null; /* @var $timingHelper \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper */ $timingHelper = $this->getTimingHelper($timing); @@ -330,6 +382,8 @@ public function testCheckEventTimingCorrectlyReturnsDateTimeWhenContactsTimezone $eventData = array(); $eventData['id'] = 1; + $eventData['decisionPath'] = null; + $eventData['triggerMode'] = null; /* @var $timingHelper \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper */ $timingHelper = $this->getTimingHelper($timing); @@ -376,6 +430,8 @@ public function testCheckEventTimingCorrectlyReturnsTrueWhenTimingTimezoneMakesI $eventData = array(); $eventData['id'] = 1; + $eventData['decisionPath'] = null; + $eventData['triggerMode'] = null; /* @var $timingHelper \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper */ $timingHelper = $this->getTimingHelper($timing); @@ -420,6 +476,8 @@ public function testCheckEventTimingCorrectlyReturnsDateTimeWhenTimingTimezoneMa $eventData = array(); $eventData['id'] = 1; + $eventData['decisionPath'] = null; + $eventData['triggerMode'] = null; /* @var $timingHelper \MauticPlugin\ThirdSetMauticTimingBundle\Helper\TimingHelper */ $timingHelper = $this->getTimingHelper($timing); @@ -465,9 +523,12 @@ public function testCheckEventTimingCorrectlyReturnsNullWhenEventDoesntHaveTimin /** @var $lead \Mautic\LeadBundle\Entity\Lead */ $lead = $this->getMockLead(null); + $eventData = array(); + $eventData['id'] = null; + //call the function $eventTriggerDate = $timingHelper->checkEventTiming( - array(), + $eventData, null, false, $lead, @@ -502,9 +563,12 @@ public function testCheckEventTimingCorrectlyReturnsNullWhenExpressionIsEmpty() /* @var $lead \Mautic\LeadBundle\Entity\Lead */ $lead = $this->getMockLead(null); + $eventData = array(); + $eventData['id'] = null; + //call the function $eventTriggerDate = $timingHelper->checkEventTiming( - array(), + $eventData, null, false, $lead, @@ -543,6 +607,7 @@ public function testCheckEventTimingCorrectlyReturnsNullDecisionPathIsNoAndNotAl $eventData = array(); $eventData['id'] = 1; $eventData['decisionPath'] = 'no'; + $eventData['triggerMode'] = null; $allowNegative = false; @@ -586,6 +651,7 @@ public function testCheckEventTimingReturnsExpectedDateTimeWhenTriggerModeIsInte $eventData = array(); $eventData['id'] = 1; + $eventData['decisionPath'] = null; $eventData['triggerMode'] = $triggerMode; $eventData['triggerInterval'] = $triggerInterval; $eventData['triggerIntervalUnit'] = $triggerIntervalUnit; @@ -636,6 +702,8 @@ public function testCheckEventTimingReturnsExpectedDateTimeWhenTriggerModeIsDate $eventData = array(); $eventData['id'] = 1; + $eventData['decisionPath'] = null; + $eventData['triggerMode'] = null; $eventData['triggerMode'] = $triggerMode; $eventData['triggerDate'] = $triggerDate; @@ -724,21 +792,21 @@ private function getMockTiming( * @param string $timezone A timezone as a string (ex: "America/New_York") * @return Lead Returns a mock Lead. */ - private function getMockLead($timezone = null) + private function getMockLead($ipTimezone = null, $fieldTimezone = null) { //mock the lead $lead = $this->getMockBuilder('\Mautic\LeadBundle\Entity\Lead') ->disableOriginalConstructor() ->getMock(); - if($timezone != null) { + if($ipTimezone != null) { //mock an IpAddress $ipAddress = $this->getMockBuilder('\Mautic\CoreBundle\Entity\IpAddress') ->disableOriginalConstructor() ->getMock(); $ipDetails = array( - 'timezone' => $timezone + 'timezone' => $ipTimezone ); //stub the ipAddress->getIpDetails() function @@ -758,6 +826,11 @@ private function getMockLead($timezone = null) ->method('getIpAddresses') ->will($this->returnValue($ipAddresses)); + //stub the lead->getTimezone() function + $lead->expects($this->any()) + ->method('getTimezone') + ->will($this->returnValue($fieldTimezone)); + return $lead; } }