From a2cff8aac35b71fb8716ce27075d9c5e4d6e6a68 Mon Sep 17 00:00:00 2001
From: James Wagoner <jameswagoner@gmail.com>
Date: Tue, 4 Jun 2024 13:06:05 -0500
Subject: [PATCH 1/5] support message scheduling if messaging service is used
 (#1)

---
 phpunit.xml.dist          | 55 +++++++++++++++++----------------------
 src/Twilio.php            | 17 ++++++++++++
 src/TwilioSmsMessage.php  | 26 ++++++++++++++++++
 tests/Unit/TwilioTest.php | 31 ++++++++++++++++++++++
 4 files changed, 98 insertions(+), 31 deletions(-)

diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index cc5cee4..96c9c8c 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,33 +1,26 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<phpunit bootstrap="vendor/autoload.php"
-         backupGlobals="false"
-         backupStaticAttributes="false"
-         colors="true"
-         verbose="true"
-         convertErrorsToExceptions="true"
-         convertNoticesToExceptions="true"
-         convertWarningsToExceptions="true"
-         processIsolation="false"
-         stopOnFailure="false">
-    <testsuites>
-        <testsuite name="Unit">
-            <directory>tests/Unit</directory>
-        </testsuite>
-        <testsuite name="Integration">
-            <directory>tests/Integration</directory>
-        </testsuite>
-    </testsuites>
-    <filter>
-        <whitelist>
-            <directory suffix=".php">src/</directory>
-        </whitelist>
-    </filter>
-
-    <logging>
-        <log type="tap" target="build/report.tap"/>
-        <log type="junit" target="build/report.junit.xml"/>
-        <log type="coverage-html" target="build/coverage"/>
-        <log type="coverage-text" target="build/coverage.txt"/>
-        <log type="coverage-clover" target="build/logs/clover.xml"/>
-    </logging>
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
+  <coverage>
+    <report>
+      <clover outputFile="build/logs/clover.xml"/>
+      <html outputDirectory="build/coverage"/>
+      <text outputFile="build/coverage.txt"/>
+    </report>
+  </coverage>
+  <testsuites>
+    <testsuite name="Unit">
+      <directory>tests/Unit</directory>
+    </testsuite>
+    <testsuite name="Integration">
+      <directory>tests/Integration</directory>
+    </testsuite>
+  </testsuites>
+  <logging>
+    <junit outputFile="build/report.junit.xml"/>
+  </logging>
+  <source>
+    <include>
+      <directory suffix=".php">src/</directory>
+    </include>
+  </source>
 </phpunit>
diff --git a/src/Twilio.php b/src/Twilio.php
index 76b6d62..7eda0bf 100644
--- a/src/Twilio.php
+++ b/src/Twilio.php
@@ -2,6 +2,7 @@
 
 namespace NotificationChannels\Twilio;
 
+use DateTime;
 use NotificationChannels\Twilio\Exceptions\CouldNotSendNotification;
 use Twilio\Exceptions\TwilioException;
 use Twilio\Rest\Api\V2010\Account\CallInstance;
@@ -74,6 +75,11 @@ protected function sendSmsMessage(TwilioSmsMessage $message, ?string $to): Messa
 
         if ($messagingServiceSid = $this->getMessagingServiceSid($message)) {
             $params['messagingServiceSid'] = $messagingServiceSid;
+
+            if ($sendAt = $this->getSendAt($message)) {
+                $params['sendAt'] = $sendAt;
+                $params['scheduleType'] = 'fixed';
+            }
         }
 
         if ($this->config->isShortenUrlsEnabled()) {
@@ -171,6 +177,17 @@ protected function getMessagingServiceSid(TwilioSmsMessage $message): ?string
         return $message->getMessagingServiceSid() ?: $this->config->getServiceSid();
     }
 
+    /**
+     * Get the send at time from the message.
+     *
+     * @param TwilioSmsMessage $message
+     * @return DateTime|null
+     */
+    protected function getSendAt(TwilioSmsMessage $message): ?DateTime
+    {
+        return $message->getSendAt();
+    }
+
     /**
      * Get the alphanumeric sender from config, if one exists.
      *
diff --git a/src/TwilioSmsMessage.php b/src/TwilioSmsMessage.php
index f97c258..f4f7a96 100755
--- a/src/TwilioSmsMessage.php
+++ b/src/TwilioSmsMessage.php
@@ -2,6 +2,9 @@
 
 namespace NotificationChannels\Twilio;
 
+use DateTime;
+use Illuminate\Support\Facades\Date;
+
 class TwilioSmsMessage extends TwilioMessage
 {
     /**
@@ -34,6 +37,11 @@ class TwilioSmsMessage extends TwilioMessage
      */
     public $provideFeedback;
 
+    /**
+     * @var null|DateTime|string
+     */
+    public $sendAt;
+
     /**
      * @var null|int
      */
@@ -145,6 +153,24 @@ public function provideFeedback(bool $provideFeedback): self
         return $this;
     }
 
+    /**
+     * Set the date and time at which the message will be sent.
+     */
+    public function sendAt(DateTime $sendAt): self
+    {
+        $this->sendAt = $sendAt;
+
+        return $this;
+    }
+
+    /**
+     * Get sendAt of this message.
+     */
+    public function getSendAt(): ?DateTime
+    {
+        return $this->sendAt;
+    }
+
     /**
      * Set the validity period (in seconds).
      *
diff --git a/tests/Unit/TwilioTest.php b/tests/Unit/TwilioTest.php
index b32ae2c..5666c1d 100644
--- a/tests/Unit/TwilioTest.php
+++ b/tests/Unit/TwilioTest.php
@@ -189,6 +189,37 @@ public function it_can_send_a_sms_message_to_twilio_with_messaging_service()
         $this->twilio->sendMessage($message, '+1111111111');
     }
 
+    /** @test */
+    public function it_can_schedule_a_sms_message_to_twilio_with_messaging_service()
+    {
+        $message = new TwilioSmsMessage('Message text');
+
+        $this->config->shouldReceive('getFrom')
+            ->once()
+            ->andReturn('+1234567890');
+
+        $this->config->shouldReceive('getServiceSid')
+            ->once()
+            ->andReturn('service_sid');
+
+        $this->config->shouldReceive('getDebugTo')
+            ->once()
+            ->andReturn(null);
+
+        $this->twilioService->messages->shouldReceive('create')
+            ->atLeast()->once()
+            ->with('+1111111111', [
+                'from' => '+1234567890',
+                'body' => 'Message text',
+                'messagingServiceSid' => 'service_sid',
+                "sendAt" => new \DateTime('+30 min'),
+                "scheduleType" => "fixed"
+            ])
+            ->andReturn(Mockery::mock(MessageInstance::class));
+
+        $this->twilio->sendMessage($message, '+1111111111');
+    }
+
     /** @test */
     public function it_can_send_a_call_to_twilio()
     {

From cc2cd96f2604f111eddfc2044d4058548c60115e Mon Sep 17 00:00:00 2001
From: James Wagoner <jameswagoner@gmail.com>
Date: Tue, 4 Jun 2024 13:14:43 -0500
Subject: [PATCH 2/5] remove unused imports

---
 src/TwilioSmsMessage.php | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/TwilioSmsMessage.php b/src/TwilioSmsMessage.php
index f4f7a96..6c531a5 100755
--- a/src/TwilioSmsMessage.php
+++ b/src/TwilioSmsMessage.php
@@ -3,7 +3,6 @@
 namespace NotificationChannels\Twilio;
 
 use DateTime;
-use Illuminate\Support\Facades\Date;
 
 class TwilioSmsMessage extends TwilioMessage
 {

From c35ea83ba40fdafa7286c99a22fdda1a3b97c741 Mon Sep 17 00:00:00 2001
From: James Wagoner <jameswagoner@gmail.com>
Date: Tue, 4 Jun 2024 13:19:54 -0500
Subject: [PATCH 3/5] add method to README

---
 README.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/README.md b/README.md
index 1eebad4..202b8fc 100644
--- a/README.md
+++ b/README.md
@@ -170,6 +170,7 @@ public function routeNotificationForTwilio()
 - `from('')`: Accepts a phone to use as the notification sender.
 - `content('')`: Accepts a string value for the notification body.
 - `messagingServiceSid('')`: Accepts a messaging service SID to handle configuration.
+- `sendAt(DateTime)`: Accepts a DateTime object to schedule a message. Only is used if messaging service is set.
 
 #### TwilioCallMessage
 

From 382db1f223a61140b924f0bb2fef81784459d183 Mon Sep 17 00:00:00 2001
From: James Wagoner <jameswagoner@gmail.com>
Date: Tue, 4 Jun 2024 13:25:57 -0500
Subject: [PATCH 4/5] remove string type

---
 src/TwilioSmsMessage.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/TwilioSmsMessage.php b/src/TwilioSmsMessage.php
index 6c531a5..5389a9b 100755
--- a/src/TwilioSmsMessage.php
+++ b/src/TwilioSmsMessage.php
@@ -37,7 +37,7 @@ class TwilioSmsMessage extends TwilioMessage
     public $provideFeedback;
 
     /**
-     * @var null|DateTime|string
+     * @var null|DateTime
      */
     public $sendAt;
 

From 6b42105bdb4b5cd6416c1582e092a2c3491649ab Mon Sep 17 00:00:00 2001
From: James Wagoner <jameswagoner@gmail.com>
Date: Tue, 4 Jun 2024 13:26:16 -0500
Subject: [PATCH 5/5] revert change to phpunit config

---
 phpunit.xml.dist | 55 +++++++++++++++++++++++++++---------------------
 1 file changed, 31 insertions(+), 24 deletions(-)

diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 96c9c8c..cc5cee4 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,26 +1,33 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
-  <coverage>
-    <report>
-      <clover outputFile="build/logs/clover.xml"/>
-      <html outputDirectory="build/coverage"/>
-      <text outputFile="build/coverage.txt"/>
-    </report>
-  </coverage>
-  <testsuites>
-    <testsuite name="Unit">
-      <directory>tests/Unit</directory>
-    </testsuite>
-    <testsuite name="Integration">
-      <directory>tests/Integration</directory>
-    </testsuite>
-  </testsuites>
-  <logging>
-    <junit outputFile="build/report.junit.xml"/>
-  </logging>
-  <source>
-    <include>
-      <directory suffix=".php">src/</directory>
-    </include>
-  </source>
+<phpunit bootstrap="vendor/autoload.php"
+         backupGlobals="false"
+         backupStaticAttributes="false"
+         colors="true"
+         verbose="true"
+         convertErrorsToExceptions="true"
+         convertNoticesToExceptions="true"
+         convertWarningsToExceptions="true"
+         processIsolation="false"
+         stopOnFailure="false">
+    <testsuites>
+        <testsuite name="Unit">
+            <directory>tests/Unit</directory>
+        </testsuite>
+        <testsuite name="Integration">
+            <directory>tests/Integration</directory>
+        </testsuite>
+    </testsuites>
+    <filter>
+        <whitelist>
+            <directory suffix=".php">src/</directory>
+        </whitelist>
+    </filter>
+
+    <logging>
+        <log type="tap" target="build/report.tap"/>
+        <log type="junit" target="build/report.junit.xml"/>
+        <log type="coverage-html" target="build/coverage"/>
+        <log type="coverage-text" target="build/coverage.txt"/>
+        <log type="coverage-clover" target="build/logs/clover.xml"/>
+    </logging>
 </phpunit>