Compare commits

...

5 Commits

Author SHA1 Message Date
0a766529ef Release 4.12.1 2023-04-19 10:00:26 -05:00
051364fdb4 Add migration fixing newsletter option fields
[MAILPOET-5244]
2023-04-19 09:49:47 -05:00
130e3840cd Fix minute scheduling for post notifications
We recently added minute scheduling in UI, but we forgot to update PostNotificationScheduler.
It caused calculating float number for hours and PN were not scheduled.
[MAILPOET-5244]
2023-04-19 09:49:36 -05:00
3ea147c5ae Add test cases for minute scheduling
[MAILPOET-5244]
2023-04-19 09:49:24 -05:00
3785540954 Release 4.12.0 2023-04-17 12:57:00 -05:00
5 changed files with 151 additions and 9 deletions

View File

@ -0,0 +1,38 @@
<?php declare(strict_types = 1);
namespace MailPoet\Migrations;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Migrator\Migration;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Newsletter\Scheduler\PostNotificationScheduler;
class Migration_20230419_080000 extends Migration {
/** @var NewslettersRepository */
private $newslettersRepository;
/** @var PostNotificationScheduler */
private $postNotificationScheduler;
public function run(): void {
$this->newslettersRepository = $this->container->get(NewslettersRepository::class);
$this->postNotificationScheduler = $this->container->get(PostNotificationScheduler::class);
$this->fixPostNotificationScheduleTime();
}
/**
* Because we released PostNotificationScheduler that didn't schedule notifications with the minute resolution,
* which was added in version 4.10.0, we need to fix the scheduled time for all notifications.
*
* Ticket with bug: https://mailpoet.atlassian.net/browse/MAILPOET-5244
* Ticket with adding minute resolution: https://mailpoet.atlassian.net/browse/MAILPOET-4602
*
* @return void
*/
private function fixPostNotificationScheduleTime() {
$newsletters = $this->newslettersRepository->findBy(['type' => NewsletterEntity::TYPE_NOTIFICATION]);
foreach ($newsletters as $newsletter) {
$this->postNotificationScheduler->processPostNotificationSchedule($newsletter);
}
}
}

View File

@ -20,6 +20,7 @@ use MailPoet\WP\Posts;
class PostNotificationScheduler {
const SECONDS_IN_MINUTE = 60;
const SECONDS_IN_HOUR = 3600;
const LAST_WEEKDAY_FORMAT = 'L';
const INTERVAL_DAILY = 'daily';
@ -162,7 +163,8 @@ class PostNotificationScheduler {
$intervalType = $intervalTypeOption ? $intervalTypeOption->getValue() : null;
$timeOfDayOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_TIME_OF_DAY);
$hour = $timeOfDayOption ? (int)$timeOfDayOption->getValue() / self::SECONDS_IN_HOUR : null;
$hour = $timeOfDayOption ? (int)floor((int)$timeOfDayOption->getValue() / self::SECONDS_IN_HOUR) : null;
$minute = $timeOfDayOption ? ((int)$timeOfDayOption->getValue() - (int)($hour * self::SECONDS_IN_HOUR)) / self::SECONDS_IN_MINUTE : null;
$weekDayOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_WEEK_DAY);
$weekDay = $weekDayOption ? $weekDayOption->getValue() : null;
@ -176,16 +178,16 @@ class PostNotificationScheduler {
switch ($intervalType) {
case self::INTERVAL_IMMEDIATE:
case self::INTERVAL_DAILY:
$schedule = sprintf('0 %s * * *', $hour);
$schedule = sprintf('%s %s * * *', $minute, $hour);
break;
case self::INTERVAL_WEEKLY:
$schedule = sprintf('0 %s * * %s', $hour, $weekDay);
$schedule = sprintf('%s %s * * %s', $minute, $hour, $weekDay);
break;
case self::INTERVAL_NTHWEEKDAY:
$schedule = sprintf('0 %s ? * %s%s', $hour, $weekDay, $nthWeekDay);
$schedule = sprintf('%s %s ? * %s%s', $minute, $hour, $weekDay, $nthWeekDay);
break;
case self::INTERVAL_MONTHLY:
$schedule = sprintf('0 %s %s * *', $hour, $monthDay);
$schedule = sprintf('%s %s %s * *', $minute, $hour, $monthDay);
break;
case self::INTERVAL_IMMEDIATELY:
default:

View File

@ -2,7 +2,7 @@
/*
* Plugin Name: MailPoet
* Version: 4.11.1
* Version: 4.12.1
* Plugin URI: https://www.mailpoet.com
* Description: Create and send newsletters, post notifications and welcome emails from your WordPress.
* Author: MailPoet
@ -20,7 +20,7 @@
*/
$mailpoetPlugin = [
'version' => '4.11.1',
'version' => '4.12.1',
'filename' => __FILE__,
'path' => dirname(__FILE__),
'autoloader' => dirname(__FILE__) . '/vendor/autoload.php',

View File

@ -3,7 +3,7 @@ Contributors: mailpoet
Tags: email, email marketing, post notification, woocommerce emails, email automation, newsletter, newsletter builder, newsletter subscribers
Requires at least: 5.9
Tested up to: 6.1
Stable tag: 4.11.1
Stable tag: 4.12.1
Requires PHP: 7.2
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html
@ -219,6 +219,14 @@ Check our [Knowledge Base](https://kb.mailpoet.com) or contact us through our [s
== Changelog ==
= 4.12.1 - 2023-04-19 =
* Fixed: post notifications not sent if scheduled with minutes.
= 4.12.0 - 2023-04-17 =
* Added: "Order status change" trigger in Automations;
* Improved: messaging when subscriber limit is reached;
* Improved: consistent use of order statuses in segment conditions.
= 4.11.1 - 2023-04-10 =
* Improved: minor changes and fixes.

View File

@ -145,7 +145,7 @@ class PostNotificationTest extends \MailPoetTest {
]);
// queue is created and scheduled for delivery one day later at 5 a.m.
$this->postNotificationScheduler->schedulePostNotification($postId = 10);
$this->postNotificationScheduler->schedulePostNotification(10);
$currentTime = Carbon::createFromTimestamp(WPFunctions::get()->currentTime('timestamp'));
Carbon::setTestNow($currentTime); // mock carbon to return current time
$nextRunDate = ($currentTime->hour < 5) ?
@ -154,6 +154,23 @@ class PostNotificationTest extends \MailPoetTest {
$queue = $this->sendingQueuesRepository->findOneBy(['newsletter' => $newsletter]);
expect($queue->getTask()->getScheduledAt()->format(DateTime::DEFAULT_DATE_TIME_FORMAT))
->equals($nextRunDate->format('Y-m-d 05:00:00'));
// testing scheduling by minutes
$newsletter = $this->createNewsletter();
$this->newsletterOptionsFactory->createMultipleOptions($newsletter, [
NewsletterOptionFieldEntity::NAME_SCHEDULE => '45 5 * * *',
]);
// queue is created and scheduled for delivery one day later at 5 a.m.
$this->postNotificationScheduler->schedulePostNotification(10);
$currentTime = Carbon::createFromTimestamp(WPFunctions::get()->currentTime('timestamp'));
Carbon::setTestNow($currentTime); // mock carbon to return current time
$nextRunDate = ($currentTime->hour < 5) ?
$currentTime :
$currentTime->addDay();
$queue = $this->sendingQueuesRepository->findOneBy(['newsletter' => $newsletter]);
expect($queue->getTask()->getScheduledAt()->format(DateTime::DEFAULT_DATE_TIME_FORMAT))
->equals($nextRunDate->format('Y-m-d 05:45:00'));
}
public function testItProcessesPostNotificationScheduledForDailyDelivery() {
@ -174,6 +191,25 @@ class PostNotificationTest extends \MailPoetTest {
$currentTime = 1483275600; // Sunday, 1 January 2017 @ 1:00pm (UTC)
expect($this->scheduler->getNextRunDate($scheduleOption->getValue(), $currentTime))
->equals('2017-01-01 14:00:00');
// testing scheduling by minutes
$newsletter = $this->createNewsletter();
$this->newsletterOptionsFactory->createMultipleOptions($newsletter, [
NewsletterOptionFieldEntity::NAME_INTERVAL_TYPE => PostNotificationScheduler::INTERVAL_DAILY,
NewsletterOptionFieldEntity::NAME_MONTH_DAY => null,
NewsletterOptionFieldEntity::NAME_NTH_WEEK_DAY => null,
NewsletterOptionFieldEntity::NAME_WEEK_DAY => null,
NewsletterOptionFieldEntity::NAME_TIME_OF_DAY => 51300, // 2:15 p.m.
NewsletterOptionFieldEntity::NAME_SCHEDULE => '* * * * *',
]);
$this->postNotificationScheduler->processPostNotificationSchedule($newsletter);
$scheduleOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_SCHEDULE);
$this->assertInstanceOf(NewsletterOptionEntity::class, $scheduleOption);
$currentTime = 1483275600; // Sunday, 1 January 2017 @ 1:00pm (UTC)
expect($this->scheduler->getNextRunDate($scheduleOption->getValue(), $currentTime))
->equals('2017-01-01 14:15:00');
}
public function testItProcessesPostNotificationScheduledForWeeklyDelivery() {
@ -196,6 +232,26 @@ class PostNotificationTest extends \MailPoetTest {
$currentTime = 1483275600; // Sunday, 1 January 2017 @ 1:00pm (UTC)
expect($this->scheduler->getNextRunDate($scheduleOption->getValue(), $currentTime))
->equals('2017-01-03 14:00:00');
// testing scheduling by minutes
$newsletter = $this->createNewsletter();
// weekly notification is scheduled every Tuesday at 11:45 p.m.
$this->newsletterOptionsFactory->createMultipleOptions($newsletter, [
NewsletterOptionFieldEntity::NAME_INTERVAL_TYPE => PostNotificationScheduler::INTERVAL_WEEKLY,
NewsletterOptionFieldEntity::NAME_MONTH_DAY => null,
NewsletterOptionFieldEntity::NAME_NTH_WEEK_DAY => null,
NewsletterOptionFieldEntity::NAME_WEEK_DAY => Carbon::TUESDAY,
NewsletterOptionFieldEntity::NAME_TIME_OF_DAY => 85500, // 11:45 p.m.
NewsletterOptionFieldEntity::NAME_SCHEDULE => '* * * * *',
]);
$this->postNotificationScheduler->processPostNotificationSchedule($newsletter);
$scheduleOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_SCHEDULE);
$this->assertInstanceOf(NewsletterOptionEntity::class, $scheduleOption);
$currentTime = 1483275600; // Sunday, 1 January 2017 @ 1:00pm (UTC)
expect($this->scheduler->getNextRunDate($scheduleOption->getValue(), $currentTime))
->equals('2017-01-03 23:45:00');
}
public function testItProcessesPostNotificationScheduledForMonthlyDeliveryOnSpecificDay() {
@ -217,6 +273,25 @@ class PostNotificationTest extends \MailPoetTest {
$currentTime = 1483275600; // Sunday, 1 January 2017 @ 1:00pm (UTC)
expect($this->scheduler->getNextRunDate($scheduleOption->getValue(), $currentTime))
->equals('2017-01-19 14:00:00');
// testing scheduling by minutes
$newsletter = $this->createNewsletter();
// monthly notification is scheduled every 20th day at 0:45
$this->newsletterOptionsFactory->createMultipleOptions($newsletter, [
NewsletterOptionFieldEntity::NAME_INTERVAL_TYPE => PostNotificationScheduler::INTERVAL_MONTHLY,
NewsletterOptionFieldEntity::NAME_MONTH_DAY => 19,
NewsletterOptionFieldEntity::NAME_NTH_WEEK_DAY => null,
NewsletterOptionFieldEntity::NAME_WEEK_DAY => null,
NewsletterOptionFieldEntity::NAME_TIME_OF_DAY => 2700, // 0:45 p.m.
NewsletterOptionFieldEntity::NAME_SCHEDULE => '* * * * *',
]);
$this->postNotificationScheduler->processPostNotificationSchedule($newsletter);
$scheduleOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_SCHEDULE);
$this->assertInstanceOf(NewsletterOptionEntity::class, $scheduleOption);
$currentTime = 1483275600; // Sunday, 1 January 2017 @ 1:00pm (UTC)
expect($this->scheduler->getNextRunDate($scheduleOption->getValue(), $currentTime))
->equals('2017-01-19 00:45:00');
}
public function testItProcessesPostNotificationScheduledForMonthlyDeliveryOnLastWeekDay() {
@ -238,6 +313,25 @@ class PostNotificationTest extends \MailPoetTest {
$currentTime = 1485694800; // Sunday, 29 January 2017 @ 1:00pm (UTC)
expect($this->scheduler->getNextRunDate($scheduleOption->getValue(), $currentTime))
->equals('2017-02-25 14:00:00');
// testing scheduling by minutes
$newsletter = $this->createNewsletter();
// monthly notification is scheduled every last Saturday at 14:15
$this->newsletterOptionsFactory->createMultipleOptions($newsletter, [
NewsletterOptionFieldEntity::NAME_INTERVAL_TYPE => PostNotificationScheduler::INTERVAL_NTHWEEKDAY,
NewsletterOptionFieldEntity::NAME_MONTH_DAY => null,
NewsletterOptionFieldEntity::NAME_NTH_WEEK_DAY => 'L', // L = last
NewsletterOptionFieldEntity::NAME_WEEK_DAY => Carbon::SATURDAY,
NewsletterOptionFieldEntity::NAME_TIME_OF_DAY => 51300, // 2:15 p.m.
NewsletterOptionFieldEntity::NAME_SCHEDULE => '* * * * *',
]);
$this->postNotificationScheduler->processPostNotificationSchedule($newsletter);
$scheduleOption = $newsletter->getOption(NewsletterOptionFieldEntity::NAME_SCHEDULE);
$this->assertInstanceOf(NewsletterOptionEntity::class, $scheduleOption);
$currentTime = 1485694800; // Sunday, 29 January 2017 @ 1:00pm (UTC)
expect($this->scheduler->getNextRunDate($scheduleOption->getValue(), $currentTime))
->equals('2017-02-25 14:15:00');
}
public function testItProcessesPostNotificationScheduledForImmediateDelivery() {