Skip to content

Commit 6fba9ef

Browse files
committed
added endpoint journal
1 parent 5bc8d47 commit 6fba9ef

11 files changed

+287
-1
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"php": "7.3"
2323
}
2424
},
25-
"description": "A simple PHP library for requesting the Sms77.io SMS gateway.",
25+
"description": "Official API Client for requesting the Sms77.io SMS Gateway.",
2626
"homepage": "https://github.com/sms77io/php-client",
2727
"keywords": [
2828
"2fa",

src/Client.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Sms77\Api\Constant\ContactsConstants;
66
use Sms77\Api\Constant\HooksConstants;
7+
use Sms77\Api\Constant\JournalConstants;
78
use Sms77\Api\Exception\InvalidOptionalArgumentException;
89
use Sms77\Api\Exception\InvalidRequiredArgumentException;
910
use Sms77\Api\Exception\UnexpectedApiResponseException;
@@ -14,6 +15,11 @@
1415
use Sms77\Api\Response\ContactCreate;
1516
use Sms77\Api\Response\ContactDelete;
1617
use Sms77\Api\Response\ContactEdit;
18+
use Sms77\Api\Response\JournalBase;
19+
use Sms77\Api\Response\JournalInbound;
20+
use Sms77\Api\Response\JournalOutbound;
21+
use Sms77\Api\Response\JournalReplies;
22+
use Sms77\Api\Response\JournalVoice;
1723
use Sms77\Api\Response\LookupCnam;
1824
use Sms77\Api\Response\LookupFormat;
1925
use Sms77\Api\Response\LookupHlr;
@@ -28,6 +34,7 @@
2834
use Sms77\Api\Validator\AnalyticsValidator;
2935
use Sms77\Api\Validator\ContactsValidator;
3036
use Sms77\Api\Validator\HooksValidator;
37+
use Sms77\Api\Validator\JournalValidator;
3138
use Sms77\Api\Validator\LookupValidator;
3239
use Sms77\Api\Validator\PricingValidator;
3340
use Sms77\Api\Validator\SmsValidator;
@@ -197,6 +204,35 @@ public function editContact(array $options = []) {
197204
return (bool)($options['json'] ?? false) ? new ContactEdit($res) : $res;
198205
}
199206

207+
/**
208+
* @param string $type
209+
* @param array $options
210+
* @return JournalBase[]
211+
* @throws InvalidOptionalArgumentException|InvalidRequiredArgumentException
212+
*/
213+
public function journal(string $type, array $options = []): array {
214+
$options['type'] = $type;
215+
216+
(new JournalValidator($options))->validate();
217+
218+
switch ($type) {
219+
case JournalConstants::TYPE_VOICE:
220+
$class = JournalVoice::class;
221+
break;
222+
case JournalConstants::TYPE_OUTBOUND:
223+
$class = JournalOutbound::class;
224+
break;
225+
case JournalConstants::TYPE_REPLIES:
226+
$class = JournalReplies::class;
227+
break;
228+
default:
229+
$class = JournalInbound::class;
230+
}
231+
232+
return Util::toArrayOfObject(
233+
$this->get(JournalConstants::ENDPOINT, $options), $class);
234+
}
235+
200236
/**
201237
* @param string $number
202238
* @return LookupFormat

src/Constant/JournalConstants.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Sms77\Api\Constant;
4+
5+
class JournalConstants {
6+
public const DATE_PATTERN = "/[\d]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][\d]|3[0-1])/";
7+
8+
public const ENDPOINT = 'journal';
9+
10+
public const TYPE_INBOUND = 'inbound';
11+
public const TYPE_OUTBOUND = 'outbound';
12+
public const TYPE_REPLIES = 'replies';
13+
public const TYPE_VOICE = 'voice';
14+
15+
public const TYPES = [
16+
self::TYPE_INBOUND,
17+
self::TYPE_OUTBOUND,
18+
self::TYPE_REPLIES,
19+
self::TYPE_VOICE,
20+
];
21+
}

src/Response/JournalBase.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Sms77\Api\Response;
4+
5+
use Sms77\Api\Library\JsonObject;
6+
7+
/**
8+
* @property string from
9+
* @property string id
10+
* @property string price
11+
* @property string text
12+
* @property string timestamp
13+
* @property string to
14+
*/
15+
abstract class JournalBase extends JsonObject {
16+
}

src/Response/JournalInbound.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Sms77\Api\Response;
4+
5+
class JournalInbound extends JournalBase {}

src/Response/JournalOutbound.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Sms77\Api\Response;
4+
5+
/**
6+
* @property string connection
7+
* @property string|null dlr
8+
* @property string|null dlr_timestamp
9+
* @property string|null foreign_id
10+
* @property string|null label
11+
* @property string|null latency
12+
* @property string|null mccmnc
13+
* @property string type
14+
*/
15+
class JournalOutbound extends JournalBase {}

src/Response/JournalReplies.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Sms77\Api\Response;
4+
5+
/**
6+
* @property string duration
7+
* @property string error
8+
* @property string status
9+
* @property bool xml
10+
*/
11+
class JournalReplies extends JournalBase {}

src/Response/JournalVoice.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Sms77\Api\Response;
4+
5+
/**
6+
* @property string duration
7+
* @property string error
8+
* @property string status
9+
* @property bool xml
10+
*/
11+
class JournalVoice extends JournalBase {}

src/Validator/JournalValidator.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Sms77\Api\Validator;
4+
5+
use Sms77\Api\Constant\JournalConstants;
6+
use Sms77\Api\Exception\InvalidOptionalArgumentException;
7+
use Sms77\Api\Exception\InvalidRequiredArgumentException;
8+
9+
class JournalValidator extends BaseValidator implements ValidatorInterface {
10+
/** @throws InvalidOptionalArgumentException|InvalidRequiredArgumentException */
11+
public function validate(): void {
12+
$this->type();
13+
$this->id();
14+
$this->date_from();
15+
$this->date_to();
16+
$this->to();
17+
$this->state();
18+
}
19+
20+
/** @throws InvalidRequiredArgumentException */
21+
public function type(): void {
22+
$type = $this->fallback('type');
23+
24+
if (!in_array($type, JournalConstants::TYPES)) {
25+
throw new InvalidRequiredArgumentException('missing type.');
26+
}
27+
}
28+
29+
/** @throws InvalidOptionalArgumentException */
30+
public function id(): void {
31+
$id = $this->fallback('id');
32+
33+
if (null !== $id && !is_int($id)) {
34+
throw new InvalidOptionalArgumentException("Invalid type for id $id.");
35+
}
36+
}
37+
38+
/** @throws InvalidOptionalArgumentException */
39+
public function date_from(): void {
40+
$dateFrom = $this->fallback('date_from');
41+
42+
if (null !== $dateFrom && !self::isDateValid($dateFrom)) {
43+
throw new InvalidOptionalArgumentException(
44+
'date_from is not a valid date.');
45+
}
46+
}
47+
48+
public static function isDateValid(string $date): bool {
49+
return (bool)preg_match(JournalConstants::DATE_PATTERN, $date);
50+
}
51+
52+
/** @throws InvalidOptionalArgumentException */
53+
public function date_to(): void {
54+
$dateTo = $this->fallback('date_to');
55+
56+
if (null !== $dateTo && !self::isDateValid($dateTo)) {
57+
throw new InvalidOptionalArgumentException(
58+
'date_to is not a valid date.');
59+
}
60+
}
61+
62+
/** @throws InvalidOptionalArgumentException */
63+
public function to(): void {
64+
$to = $this->fallback('to');
65+
66+
if (null !== $to && !((bool)preg_match('/\\d/', $to))) {
67+
throw new InvalidOptionalArgumentException('to is not a valid number.');
68+
}
69+
}
70+
71+
public function state(): void {
72+
}
73+
}

tests/Client/BaseTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Sms77\Tests\Client;
44

5+
use DateTime;
56
use PHPUnit\Framework\TestCase;
67
use Sms77\Api\Client;
78

@@ -17,4 +18,23 @@ public function __construct(
1718

1819
$this->recipient = getenv('SMS77_RECIPIENT') ?? '+491771783130';
1920
}
21+
22+
public static function assertIsNullOrLengthyString(?string $value): void {
23+
self::assertTrue(is_null($value) || 0 < strlen($value));
24+
}
25+
26+
public static function assertIsLengthyString(string $value): void {
27+
self::assertTrue(0 < strlen($value));
28+
}
29+
30+
public static function assertIsValidDateTime(string $dateTime): void {
31+
$bool = null;
32+
33+
try {
34+
$bool = new DateTime($dateTime);
35+
} catch (\Exception $e) {
36+
}
37+
38+
self::assertInstanceOf(DateTime::class, $bool);
39+
}
2040
}

tests/Client/JournalTest.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Sms77\Tests\Client;
4+
5+
use Sms77\Api\Constant\JournalConstants;
6+
use Sms77\Api\Constant\SmsType;
7+
use Sms77\Api\Exception\InvalidRequiredArgumentException;
8+
use Sms77\Api\Response\JournalBase;
9+
use Sms77\Api\Response\JournalInbound;
10+
use Sms77\Api\Response\JournalOutbound;
11+
use Sms77\Api\Response\JournalReplies;
12+
use Sms77\Api\Response\JournalVoice;
13+
14+
class JournalTest extends BaseTest {
15+
private function request(
16+
string $type,
17+
string $class,
18+
?callable $functionHandler = null,
19+
array $options = []): void {
20+
$journals = $this->client->journal($type, $options);
21+
22+
self::assertIsArray($journals);
23+
24+
foreach ($journals as $j) {
25+
self::assertInstanceOf($class, $j);
26+
self::assertIsLengthyString($j->from);
27+
self::assertIsNumeric($j->id);
28+
self::assertIsNumeric($j->price);
29+
self::assertIsLengthyString($j->text);
30+
self::assertIsValidDateTime($j->timestamp);
31+
self::assertIsLengthyString($j->to);
32+
33+
$functionHandler && $functionHandler($j);
34+
}
35+
}
36+
37+
public function testJournalInbound(): void {
38+
$this->request(JournalConstants::TYPE_INBOUND, JournalInbound::class);
39+
}
40+
41+
public function testJournalOutbound(): void {
42+
$this->request(
43+
JournalConstants::TYPE_OUTBOUND,
44+
JournalOutbound::class,
45+
static function (JournalOutbound $j) {
46+
self::assertIsString($j->connection);
47+
self::assertIsNullOrLengthyString($j->dlr);
48+
self::assertIsNullOrLengthyString($j->dlr_timestamp);
49+
self::assertIsNullOrLengthyString($j->foreign_id);
50+
self::assertIsNullOrLengthyString($j->label);
51+
self::assertIsNullOrLengthyString($j->latency);
52+
self::assertIsNullOrLengthyString($j->mccmnc);
53+
self::assertTrue(in_array($j->type, SmsType::values()));
54+
});
55+
}
56+
57+
public function testJournalVoice(): void {
58+
$this->request(
59+
JournalConstants::TYPE_VOICE,
60+
JournalVoice::class,
61+
static function (JournalVoice $j) {
62+
self::assertIsNumeric($j->duration);
63+
self::assertIsString($j->error);
64+
self::assertIsLengthyString($j->status);
65+
self::assertIsBool($j->xml);
66+
});
67+
}
68+
69+
public function testJournalReplies(): void {
70+
$this->request(JournalConstants::TYPE_REPLIES, JournalReplies::class);
71+
}
72+
73+
public function testJournalInvalidType(): void {
74+
$this->expectException(InvalidRequiredArgumentException::class);
75+
76+
$this->request('INVALID_JOURNAL_TYPE', JournalBase::class);
77+
}
78+
}

0 commit comments

Comments
 (0)