@artilingo/artiframe-cli 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/core-stubs/bin/SystemMethod.php +600 -521
  2. package/core-stubs/bin/ViewMethod.php +591 -393
  3. package/core-stubs/docs/de.html +853 -1172
  4. package/core-stubs/docs/en.html +585 -904
  5. package/core-stubs/docs/es.html +934 -1253
  6. package/core-stubs/docs/fr.html +913 -1232
  7. package/core-stubs/docs/tr.html +4212 -5021
  8. package/package.json +1 -1
  9. package/src/App.php +38 -0
  10. package/src/Commands/AddCommand.php +1 -1
  11. package/src/Commands/AuthCommand.php +219 -0
  12. package/src/Commands/IssuesCommand.php +174 -0
  13. package/src/Commands/ListCommand.php +2 -1
  14. package/src/Commands/MakeApiCommand.php +1 -1
  15. package/src/Commands/MakeClassCommand.php +1 -1
  16. package/src/Commands/MakeViewCommand.php +1 -1
  17. package/src/Commands/NewProjectCommand.php +37 -25
  18. package/src/Commands/RemoveCommand.php +21 -10
  19. package/src/Commands/ServeCommand.php +29 -9
  20. package/src/Commands/SuggestCommand.php +143 -0
  21. package/src/Commands/TableCommand.php +2 -1
  22. package/src/Commands/UpgradeCommand.php +209 -0
  23. package/src/Commands/VersionCommand.php +2 -1
  24. package/src/Lang/de.php +9 -1
  25. package/src/Lang/en.php +8 -0
  26. package/src/Lang/es.php +9 -1
  27. package/src/Lang/fr.php +8 -0
  28. package/src/Lang/tr.php +10 -2
  29. package/src/Services/Safeguard.php +25 -0
  30. package/stubs/service/image.stub +334 -334
  31. package/stubs/service/iyzico.stub +637 -637
  32. package/stubs/service/jwt.stub +312 -312
  33. package/stubs/service/phpmailer.stub +143 -143
  34. package/stubs/service/pusher.stub +232 -232
  35. package/stubs/service/qrcode.stub +169 -169
  36. package/stubs/service/redis.stub +361 -361
  37. package/stubs/service/s3.stub +377 -377
  38. package/stubs/service/sentry.stub +76 -106
  39. package/stubs/service/stripe.stub +526 -526
  40. package/stubs/service/twilio.stub +361 -361
  41. package/core-stubs/app/R2Manager.php +0 -130
@@ -1,361 +1,361 @@
1
- <?php
2
-
3
- namespace Service;
4
-
5
- use Twilio\Rest\Client;
6
-
7
- /**
8
- * Twilio Communications Service
9
- *
10
- * Provides a simplified interface for Twilio's messaging, voice,
11
- * and verification APIs using the twilio/sdk. All configuration
12
- * is read from $_ENV.
13
- *
14
- * Required environment variables:
15
- * TWILIO_SID — Your Twilio Account SID
16
- * TWILIO_AUTH_TOKEN — Your Twilio Auth Token
17
- * TWILIO_FROM_NUMBER — Default "from" phone number (E.164 format, e.g., +15551234567)
18
- *
19
- * Optional environment variables:
20
- * TWILIO_VERIFY_SID — Verify Service SID (required for verifyStart/verifyCheck)
21
- *
22
- * @package Service
23
- */
24
- class TwilioService
25
- {
26
- /**
27
- * The Twilio REST API client instance.
28
- *
29
- * @var \Twilio\Rest\Client
30
- */
31
- private Client $client;
32
-
33
- /**
34
- * The default "from" phone number in E.164 format.
35
- *
36
- * @var string
37
- */
38
- private string $fromNumber;
39
-
40
- /**
41
- * Create a new TwilioService instance.
42
- *
43
- * Initializes the Twilio REST client using account credentials
44
- * from environment variables.
45
- *
46
- * @throws \Twilio\Exceptions\ConfigurationException If SID or Auth Token are invalid
47
- */
48
- public function __construct()
49
- {
50
- $this->client = new Client(
51
- $_ENV['TWILIO_SID'],
52
- $_ENV['TWILIO_AUTH_TOKEN']
53
- );
54
- $this->fromNumber = $_ENV['TWILIO_FROM_NUMBER'];
55
- }
56
-
57
- /**
58
- * Send an SMS message.
59
- *
60
- * Sends a text message to the specified phone number using the
61
- * configured "from" number.
62
- *
63
- * @param string $to Recipient phone number in E.164 format (e.g., +905551234567)
64
- * @param string $message The SMS body text (max 1600 characters)
65
- * @return array Result with keys: 'status', 'sid', 'message'
66
- * On error: 'status' => 'error', 'message' => error description
67
- */
68
- public function sendSms(string $to, string $message): array
69
- {
70
- try {
71
- $msg = $this->client->messages->create($to, [
72
- 'from' => $this->fromNumber,
73
- 'body' => $message,
74
- ]);
75
-
76
- return [
77
- 'status' => $msg->status,
78
- 'sid' => $msg->sid,
79
- 'message' => 'SMS sent successfully',
80
- ];
81
- } catch (\Exception $e) {
82
- return [
83
- 'status' => 'error',
84
- 'sid' => null,
85
- 'message' => $e->getMessage(),
86
- ];
87
- }
88
- }
89
-
90
- /**
91
- * Send a WhatsApp message.
92
- *
93
- * Sends a message via the Twilio WhatsApp Business API.
94
- * Both the sender and recipient numbers are prefixed with 'whatsapp:'.
95
- *
96
- * Note: Your Twilio number must be approved for WhatsApp messaging,
97
- * or you must use the Twilio Sandbox for WhatsApp during development.
98
- *
99
- * @param string $to Recipient phone number in E.164 format (e.g., +905551234567)
100
- * @param string $message The message body text
101
- * @return array Result with keys: 'status', 'sid', 'message'
102
- */
103
- public function sendWhatsApp(string $to, string $message): array
104
- {
105
- try {
106
- $msg = $this->client->messages->create("whatsapp:{$to}", [
107
- 'from' => "whatsapp:{$this->fromNumber}",
108
- 'body' => $message,
109
- ]);
110
-
111
- return [
112
- 'status' => $msg->status,
113
- 'sid' => $msg->sid,
114
- 'message' => 'WhatsApp message sent successfully',
115
- ];
116
- } catch (\Exception $e) {
117
- return [
118
- 'status' => 'error',
119
- 'sid' => null,
120
- 'message' => $e->getMessage(),
121
- ];
122
- }
123
- }
124
-
125
- /**
126
- * Initiate a voice call.
127
- *
128
- * Places an outbound call to the specified number. The call behavior
129
- * is defined by the TwiML document at the given URL. The TwiML URL
130
- * should return instructions like <Say>, <Play>, <Gather>, etc.
131
- *
132
- * @param string $to Recipient phone number in E.164 format
133
- * @param string $twimlUrl URL pointing to a TwiML document that controls the call
134
- * @return array Result with keys: 'status', 'sid', 'message'
135
- */
136
- public function call(string $to, string $twimlUrl): array
137
- {
138
- try {
139
- $call = $this->client->calls->create($to, $this->fromNumber, [
140
- 'url' => $twimlUrl,
141
- ]);
142
-
143
- return [
144
- 'status' => $call->status,
145
- 'sid' => $call->sid,
146
- 'message' => 'Call initiated successfully',
147
- ];
148
- } catch (\Exception $e) {
149
- return [
150
- 'status' => 'error',
151
- 'sid' => null,
152
- 'message' => $e->getMessage(),
153
- ];
154
- }
155
- }
156
-
157
- /**
158
- * Start a phone number verification.
159
- *
160
- * Sends a verification code to the specified phone number using
161
- * Twilio's Verify API. Supports SMS, voice call, and email channels.
162
- *
163
- * Requires the TWILIO_VERIFY_SID environment variable to be set
164
- * with a valid Verify Service SID.
165
- *
166
- * @param string $to Phone number to verify in E.164 format
167
- * @param string $channel Delivery channel: 'sms', 'call', or 'email' (default: 'sms')
168
- * @return array Result with keys: 'status', 'sid', 'message'
169
- * status will be 'pending' on success
170
- */
171
- public function verifyStart(string $to, string $channel = 'sms'): array
172
- {
173
- try {
174
- $verifySid = $_ENV['TWILIO_VERIFY_SID'] ?? null;
175
-
176
- if (!$verifySid) {
177
- return [
178
- 'status' => 'error',
179
- 'sid' => null,
180
- 'message' => 'TWILIO_VERIFY_SID environment variable is not set',
181
- ];
182
- }
183
-
184
- $verification = $this->client->verify->v2
185
- ->services($verifySid)
186
- ->verifications
187
- ->create($to, $channel);
188
-
189
- return [
190
- 'status' => $verification->status,
191
- 'sid' => $verification->sid,
192
- 'message' => 'Verification code sent successfully',
193
- ];
194
- } catch (\Exception $e) {
195
- return [
196
- 'status' => 'error',
197
- 'sid' => null,
198
- 'message' => $e->getMessage(),
199
- ];
200
- }
201
- }
202
-
203
- /**
204
- * Check a verification code.
205
- *
206
- * Validates the code entered by the user against the one sent
207
- * via verifyStart(). Returns 'approved' status on a successful match.
208
- *
209
- * Requires the TWILIO_VERIFY_SID environment variable to be set.
210
- *
211
- * @param string $to The phone number that was verified (E.164 format)
212
- * @param string $code The verification code entered by the user
213
- * @return array Result with keys: 'status', 'sid', 'message'
214
- * status will be 'approved' on successful verification
215
- */
216
- public function verifyCheck(string $to, string $code): array
217
- {
218
- try {
219
- $verifySid = $_ENV['TWILIO_VERIFY_SID'] ?? null;
220
-
221
- if (!$verifySid) {
222
- return [
223
- 'status' => 'error',
224
- 'sid' => null,
225
- 'message' => 'TWILIO_VERIFY_SID environment variable is not set',
226
- ];
227
- }
228
-
229
- $check = $this->client->verify->v2
230
- ->services($verifySid)
231
- ->verificationChecks
232
- ->create([
233
- 'to' => $to,
234
- 'code' => $code,
235
- ]);
236
-
237
- return [
238
- 'status' => $check->status,
239
- 'sid' => $check->sid,
240
- 'message' => $check->status === 'approved'
241
- ? 'Verification successful'
242
- : 'Verification failed — invalid code',
243
- ];
244
- } catch (\Exception $e) {
245
- return [
246
- 'status' => 'error',
247
- 'sid' => null,
248
- 'message' => $e->getMessage(),
249
- ];
250
- }
251
- }
252
-
253
- /**
254
- * Get the delivery status of a specific message.
255
- *
256
- * Fetches the current status of a previously sent message
257
- * by its unique SID.
258
- *
259
- * Possible statuses: queued, sending, sent, delivered, undelivered, failed
260
- *
261
- * @param string $messageSid The message SID (e.g., 'SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
262
- * @return array Result with keys: 'status', 'sid', 'to', 'from',
263
- * 'date_sent', 'price', 'error_code', 'error_message'
264
- */
265
- public function getMessageStatus(string $messageSid): array
266
- {
267
- try {
268
- $msg = $this->client->messages($messageSid)->fetch();
269
-
270
- return [
271
- 'status' => $msg->status,
272
- 'sid' => $msg->sid,
273
- 'to' => $msg->to,
274
- 'from' => $msg->from,
275
- 'date_sent' => $msg->dateSent ? $msg->dateSent->format('Y-m-d H:i:s') : null,
276
- 'price' => $msg->price,
277
- 'error_code' => $msg->errorCode,
278
- 'error_message' => $msg->errorMessage,
279
- ];
280
- } catch (\Exception $e) {
281
- return [
282
- 'status' => 'error',
283
- 'sid' => $messageSid,
284
- 'message' => $e->getMessage(),
285
- ];
286
- }
287
- }
288
-
289
- /**
290
- * List recent messages from your Twilio account.
291
- *
292
- * Retrieves the most recent messages ordered by date sent (descending).
293
- * Each message includes its SID, status, direction, body preview,
294
- * and timestamps.
295
- *
296
- * @param int $limit Maximum number of messages to return (default: 20, max: 1000)
297
- * @return array List of message arrays with keys:
298
- * 'sid', 'status', 'direction', 'from', 'to', 'body', 'date_sent'
299
- */
300
- public function listMessages(int $limit = 20): array
301
- {
302
- try {
303
- $messages = $this->client->messages->read([], $limit);
304
- $result = [];
305
-
306
- foreach ($messages as $msg) {
307
- $result[] = [
308
- 'sid' => $msg->sid,
309
- 'status' => $msg->status,
310
- 'direction' => $msg->direction,
311
- 'from' => $msg->from,
312
- 'to' => $msg->to,
313
- 'body' => $msg->body,
314
- 'date_sent' => $msg->dateSent ? $msg->dateSent->format('Y-m-d H:i:s') : null,
315
- ];
316
- }
317
-
318
- return $result;
319
- } catch (\Exception $e) {
320
- return [];
321
- }
322
- }
323
-
324
- /**
325
- * Send the same SMS message to multiple recipients.
326
- *
327
- * Iterates through the list of phone numbers and sends the
328
- * message to each one individually. Returns a summary of
329
- * successes and failures.
330
- *
331
- * @param array $recipients List of phone numbers in E.164 format
332
- * @param string $message The SMS body text
333
- * @return array Summary with keys:
334
- * 'total', 'sent', 'failed', 'results' (per-recipient detail)
335
- */
336
- public function sendBulkSms(array $recipients, string $message): array
337
- {
338
- $results = [];
339
- $sent = 0;
340
- $failed = 0;
341
-
342
- foreach ($recipients as $to) {
343
- $result = $this->sendSms($to, $message);
344
-
345
- if ($result['status'] !== 'error') {
346
- $sent++;
347
- } else {
348
- $failed++;
349
- }
350
-
351
- $results[] = array_merge(['to' => $to], $result);
352
- }
353
-
354
- return [
355
- 'total' => count($recipients),
356
- 'sent' => $sent,
357
- 'failed' => $failed,
358
- 'results' => $results,
359
- ];
360
- }
361
- }
1
+ <?php
2
+
3
+ namespace Src\Service;
4
+
5
+ use Twilio\Rest\Client;
6
+
7
+ /**
8
+ * Twilio Communications Service
9
+ *
10
+ * Provides a simplified interface for Twilio's messaging, voice,
11
+ * and verification APIs using the twilio/sdk. All configuration
12
+ * is read from $_ENV.
13
+ *
14
+ * Required environment variables:
15
+ * TWILIO_SID — Your Twilio Account SID
16
+ * TWILIO_AUTH_TOKEN — Your Twilio Auth Token
17
+ * TWILIO_FROM_NUMBER — Default "from" phone number (E.164 format, e.g., +15551234567)
18
+ *
19
+ * Optional environment variables:
20
+ * TWILIO_VERIFY_SID — Verify Service SID (required for verifyStart/verifyCheck)
21
+ *
22
+ * @package Service
23
+ */
24
+ class TwilioService
25
+ {
26
+ /**
27
+ * The Twilio REST API client instance.
28
+ *
29
+ * @var \Twilio\Rest\Client
30
+ */
31
+ private Client $client;
32
+
33
+ /**
34
+ * The default "from" phone number in E.164 format.
35
+ *
36
+ * @var string
37
+ */
38
+ private string $fromNumber;
39
+
40
+ /**
41
+ * Create a new TwilioService instance.
42
+ *
43
+ * Initializes the Twilio REST client using account credentials
44
+ * from environment variables.
45
+ *
46
+ * @throws \Twilio\Exceptions\ConfigurationException If SID or Auth Token are invalid
47
+ */
48
+ public function __construct()
49
+ {
50
+ $this->client = new Client(
51
+ $_ENV['TWILIO_SID'],
52
+ $_ENV['TWILIO_AUTH_TOKEN']
53
+ );
54
+ $this->fromNumber = $_ENV['TWILIO_FROM_NUMBER'];
55
+ }
56
+
57
+ /**
58
+ * Send an SMS message.
59
+ *
60
+ * Sends a text message to the specified phone number using the
61
+ * configured "from" number.
62
+ *
63
+ * @param string $to Recipient phone number in E.164 format (e.g., +905551234567)
64
+ * @param string $message The SMS body text (max 1600 characters)
65
+ * @return array Result with keys: 'status', 'sid', 'message'
66
+ * On error: 'status' => 'error', 'message' => error description
67
+ */
68
+ public function sendSms(string $to, string $message): array
69
+ {
70
+ try {
71
+ $msg = $this->client->messages->create($to, [
72
+ 'from' => $this->fromNumber,
73
+ 'body' => $message,
74
+ ]);
75
+
76
+ return [
77
+ 'status' => $msg->status,
78
+ 'sid' => $msg->sid,
79
+ 'message' => 'SMS sent successfully',
80
+ ];
81
+ } catch (\Exception $e) {
82
+ return [
83
+ 'status' => 'error',
84
+ 'sid' => null,
85
+ 'message' => $e->getMessage(),
86
+ ];
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Send a WhatsApp message.
92
+ *
93
+ * Sends a message via the Twilio WhatsApp Business API.
94
+ * Both the sender and recipient numbers are prefixed with 'whatsapp:'.
95
+ *
96
+ * Note: Your Twilio number must be approved for WhatsApp messaging,
97
+ * or you must use the Twilio Sandbox for WhatsApp during development.
98
+ *
99
+ * @param string $to Recipient phone number in E.164 format (e.g., +905551234567)
100
+ * @param string $message The message body text
101
+ * @return array Result with keys: 'status', 'sid', 'message'
102
+ */
103
+ public function sendWhatsApp(string $to, string $message): array
104
+ {
105
+ try {
106
+ $msg = $this->client->messages->create("whatsapp:{$to}", [
107
+ 'from' => "whatsapp:{$this->fromNumber}",
108
+ 'body' => $message,
109
+ ]);
110
+
111
+ return [
112
+ 'status' => $msg->status,
113
+ 'sid' => $msg->sid,
114
+ 'message' => 'WhatsApp message sent successfully',
115
+ ];
116
+ } catch (\Exception $e) {
117
+ return [
118
+ 'status' => 'error',
119
+ 'sid' => null,
120
+ 'message' => $e->getMessage(),
121
+ ];
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Initiate a voice call.
127
+ *
128
+ * Places an outbound call to the specified number. The call behavior
129
+ * is defined by the TwiML document at the given URL. The TwiML URL
130
+ * should return instructions like <Say>, <Play>, <Gather>, etc.
131
+ *
132
+ * @param string $to Recipient phone number in E.164 format
133
+ * @param string $twimlUrl URL pointing to a TwiML document that controls the call
134
+ * @return array Result with keys: 'status', 'sid', 'message'
135
+ */
136
+ public function call(string $to, string $twimlUrl): array
137
+ {
138
+ try {
139
+ $call = $this->client->calls->create($to, $this->fromNumber, [
140
+ 'url' => $twimlUrl,
141
+ ]);
142
+
143
+ return [
144
+ 'status' => $call->status,
145
+ 'sid' => $call->sid,
146
+ 'message' => 'Call initiated successfully',
147
+ ];
148
+ } catch (\Exception $e) {
149
+ return [
150
+ 'status' => 'error',
151
+ 'sid' => null,
152
+ 'message' => $e->getMessage(),
153
+ ];
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Start a phone number verification.
159
+ *
160
+ * Sends a verification code to the specified phone number using
161
+ * Twilio's Verify API. Supports SMS, voice call, and email channels.
162
+ *
163
+ * Requires the TWILIO_VERIFY_SID environment variable to be set
164
+ * with a valid Verify Service SID.
165
+ *
166
+ * @param string $to Phone number to verify in E.164 format
167
+ * @param string $channel Delivery channel: 'sms', 'call', or 'email' (default: 'sms')
168
+ * @return array Result with keys: 'status', 'sid', 'message'
169
+ * status will be 'pending' on success
170
+ */
171
+ public function verifyStart(string $to, string $channel = 'sms'): array
172
+ {
173
+ try {
174
+ $verifySid = $_ENV['TWILIO_VERIFY_SID'] ?? null;
175
+
176
+ if (!$verifySid) {
177
+ return [
178
+ 'status' => 'error',
179
+ 'sid' => null,
180
+ 'message' => 'TWILIO_VERIFY_SID environment variable is not set',
181
+ ];
182
+ }
183
+
184
+ $verification = $this->client->verify->v2
185
+ ->services($verifySid)
186
+ ->verifications
187
+ ->create($to, $channel);
188
+
189
+ return [
190
+ 'status' => $verification->status,
191
+ 'sid' => $verification->sid,
192
+ 'message' => 'Verification code sent successfully',
193
+ ];
194
+ } catch (\Exception $e) {
195
+ return [
196
+ 'status' => 'error',
197
+ 'sid' => null,
198
+ 'message' => $e->getMessage(),
199
+ ];
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Check a verification code.
205
+ *
206
+ * Validates the code entered by the user against the one sent
207
+ * via verifyStart(). Returns 'approved' status on a successful match.
208
+ *
209
+ * Requires the TWILIO_VERIFY_SID environment variable to be set.
210
+ *
211
+ * @param string $to The phone number that was verified (E.164 format)
212
+ * @param string $code The verification code entered by the user
213
+ * @return array Result with keys: 'status', 'sid', 'message'
214
+ * status will be 'approved' on successful verification
215
+ */
216
+ public function verifyCheck(string $to, string $code): array
217
+ {
218
+ try {
219
+ $verifySid = $_ENV['TWILIO_VERIFY_SID'] ?? null;
220
+
221
+ if (!$verifySid) {
222
+ return [
223
+ 'status' => 'error',
224
+ 'sid' => null,
225
+ 'message' => 'TWILIO_VERIFY_SID environment variable is not set',
226
+ ];
227
+ }
228
+
229
+ $check = $this->client->verify->v2
230
+ ->services($verifySid)
231
+ ->verificationChecks
232
+ ->create([
233
+ 'to' => $to,
234
+ 'code' => $code,
235
+ ]);
236
+
237
+ return [
238
+ 'status' => $check->status,
239
+ 'sid' => $check->sid,
240
+ 'message' => $check->status === 'approved'
241
+ ? 'Verification successful'
242
+ : 'Verification failed — invalid code',
243
+ ];
244
+ } catch (\Exception $e) {
245
+ return [
246
+ 'status' => 'error',
247
+ 'sid' => null,
248
+ 'message' => $e->getMessage(),
249
+ ];
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Get the delivery status of a specific message.
255
+ *
256
+ * Fetches the current status of a previously sent message
257
+ * by its unique SID.
258
+ *
259
+ * Possible statuses: queued, sending, sent, delivered, undelivered, failed
260
+ *
261
+ * @param string $messageSid The message SID (e.g., 'SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
262
+ * @return array Result with keys: 'status', 'sid', 'to', 'from',
263
+ * 'date_sent', 'price', 'error_code', 'error_message'
264
+ */
265
+ public function getMessageStatus(string $messageSid): array
266
+ {
267
+ try {
268
+ $msg = $this->client->messages($messageSid)->fetch();
269
+
270
+ return [
271
+ 'status' => $msg->status,
272
+ 'sid' => $msg->sid,
273
+ 'to' => $msg->to,
274
+ 'from' => $msg->from,
275
+ 'date_sent' => $msg->dateSent ? $msg->dateSent->format('Y-m-d H:i:s') : null,
276
+ 'price' => $msg->price,
277
+ 'error_code' => $msg->errorCode,
278
+ 'error_message' => $msg->errorMessage,
279
+ ];
280
+ } catch (\Exception $e) {
281
+ return [
282
+ 'status' => 'error',
283
+ 'sid' => $messageSid,
284
+ 'message' => $e->getMessage(),
285
+ ];
286
+ }
287
+ }
288
+
289
+ /**
290
+ * List recent messages from your Twilio account.
291
+ *
292
+ * Retrieves the most recent messages ordered by date sent (descending).
293
+ * Each message includes its SID, status, direction, body preview,
294
+ * and timestamps.
295
+ *
296
+ * @param int $limit Maximum number of messages to return (default: 20, max: 1000)
297
+ * @return array List of message arrays with keys:
298
+ * 'sid', 'status', 'direction', 'from', 'to', 'body', 'date_sent'
299
+ */
300
+ public function listMessages(int $limit = 20): array
301
+ {
302
+ try {
303
+ $messages = $this->client->messages->read([], $limit);
304
+ $result = [];
305
+
306
+ foreach ($messages as $msg) {
307
+ $result[] = [
308
+ 'sid' => $msg->sid,
309
+ 'status' => $msg->status,
310
+ 'direction' => $msg->direction,
311
+ 'from' => $msg->from,
312
+ 'to' => $msg->to,
313
+ 'body' => $msg->body,
314
+ 'date_sent' => $msg->dateSent ? $msg->dateSent->format('Y-m-d H:i:s') : null,
315
+ ];
316
+ }
317
+
318
+ return $result;
319
+ } catch (\Exception $e) {
320
+ return [];
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Send the same SMS message to multiple recipients.
326
+ *
327
+ * Iterates through the list of phone numbers and sends the
328
+ * message to each one individually. Returns a summary of
329
+ * successes and failures.
330
+ *
331
+ * @param array $recipients List of phone numbers in E.164 format
332
+ * @param string $message The SMS body text
333
+ * @return array Summary with keys:
334
+ * 'total', 'sent', 'failed', 'results' (per-recipient detail)
335
+ */
336
+ public function sendBulkSms(array $recipients, string $message): array
337
+ {
338
+ $results = [];
339
+ $sent = 0;
340
+ $failed = 0;
341
+
342
+ foreach ($recipients as $to) {
343
+ $result = $this->sendSms($to, $message);
344
+
345
+ if ($result['status'] !== 'error') {
346
+ $sent++;
347
+ } else {
348
+ $failed++;
349
+ }
350
+
351
+ $results[] = array_merge(['to' => $to], $result);
352
+ }
353
+
354
+ return [
355
+ 'total' => count($recipients),
356
+ 'sent' => $sent,
357
+ 'failed' => $failed,
358
+ 'results' => $results,
359
+ ];
360
+ }
361
+ }