From 1d23bce04bd8a0843587ad7dd6c18c3498e898de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Tue, 23 Apr 2024 11:34:41 +0200 Subject: [PATCH 01/54] dont strip slashes --- src/BaseClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BaseClient.php b/src/BaseClient.php index 0f75166..b4954a9 100644 --- a/src/BaseClient.php +++ b/src/BaseClient.php @@ -67,7 +67,7 @@ protected function request(string $path, string $method, array $options = []): m if (HttpMethod::POST === $method) { var_dump($options); - $params = stripslashes(json_encode($options, JSON_UNESCAPED_UNICODE)); + $params = json_encode($options, JSON_UNESCAPED_UNICODE); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); curl_setopt($ch, CURLOPT_POST, true); From 85c22e9139d5b8f4a5f0a2a5fc2d250ed0c03a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Tue, 23 Apr 2024 12:48:19 +0200 Subject: [PATCH 02/54] implement /groups --- src/BaseClient.php | 91 +++++++++++++++++------------ src/Client.php | 3 + src/Constant/HttpMethod.php | 14 ++--- src/Params/Groups/ListParams.php | 36 ++++++++++++ src/Resource/GroupsResource.php | 44 ++++++++++++++ src/Response/Groups/Group.php | 39 +++++++++++++ src/Response/Groups/GroupDelete.php | 18 ++++++ src/Response/Groups/ListGroups.php | 28 +++++++++ src/Response/PagingMetadata.php | 39 +++++++++++++ tests/Client/GroupsTest.php | 36 ++++++++++++ 10 files changed, 303 insertions(+), 45 deletions(-) create mode 100644 src/Params/Groups/ListParams.php create mode 100644 src/Resource/GroupsResource.php create mode 100644 src/Response/Groups/Group.php create mode 100644 src/Response/Groups/GroupDelete.php create mode 100644 src/Response/Groups/ListGroups.php create mode 100644 src/Response/PagingMetadata.php create mode 100644 tests/Client/GroupsTest.php diff --git a/src/BaseClient.php b/src/BaseClient.php index b4954a9..87a386a 100644 --- a/src/BaseClient.php +++ b/src/BaseClient.php @@ -10,6 +10,10 @@ abstract class BaseClient { public const BASE_URI = 'https://gateway.seven.io/api'; + /** + * @var array|string[] + */ + protected array $headers; /** * @throws Exception @@ -19,12 +23,33 @@ public function __construct( protected string $sentWith = 'php-api' ) { - if ('' === $apiKey) throw new InvalidArgumentException( - "Invalid required constructor argument apiKey: $apiKey"); + 'Invalid required constructor argument apiKey: ' . $apiKey); if ('' === $sentWith || !is_string($sentWith)) throw new InvalidArgumentException( - "Invalid required constructor argument sentWith: $sentWith"); + 'Invalid required constructor argument sentWith: ' . $sentWith); + + $this->headers = [ + 'Accept: application/json', + 'SentWith: ' . $this->sentWith, + 'X-Api-Key:' . $this->apiKey, + ]; + //$this->setContentTypeJson(); + } + + public function setContentTypeJson(): void + { + $this->setContentType('application/json'); + } + + public function setContentType(string $contentType): void + { + $this->headers['Content-Type'] = $contentType; + } + + public function setContentTypeUrlEncoded(): void + { + $this->setContentType('application/x-www-form-urlencoded'); } public function getApiKey(): string @@ -37,54 +62,41 @@ public function getSentWith(): string return $this->sentWith; } - public function delete(string $path, array $options = []): mixed + public function delete(string $path, array $options = [], array $headers = []): mixed { - return $this->request($path, HttpMethod::DELETE, $options); + return $this->request($path, HttpMethod::DELETE, $options, $headers); } - protected function request(string $path, string $method, array $options = []): mixed + protected function request(string $path, HttpMethod $method, array $payload = [], array $headers = []): mixed { - $method = strtoupper($method); - $methods = HttpMethod::values(); - if (!in_array($method, $methods)) { - $methods = implode(',', $methods); - - throw new InvalidArgumentException( - "Invalid method '$method' - valid methods are $methods"); - } - - $headers = [ - 'Accept: application/json', - 'Content-Type: application/json', - 'SentWith: ' . $this->sentWith, - 'X-Api-Key:' . $this->apiKey, - ]; + $headers = array_unique([...$this->headers, ...$headers]); $url = self::BASE_URI . '/' . $path; - $params = http_build_query($options); - if (HttpMethod::GET === $method) $url .= '?' . $params; + $params = http_build_query($payload); + if (HttpMethod::GET === $method) $url .= str_ends_with($url, '?') ? '' : '?' . $params; $ch = curl_init($url); if (HttpMethod::POST === $method) { - var_dump($options); - $params = json_encode($options, JSON_UNESCAPED_UNICODE); - - curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + $value = $headers['Content-Type'] ?? '' === 'application/json' + ? json_encode($payload, JSON_UNESCAPED_UNICODE) + : $params; + curl_setopt($ch, CURLOPT_POSTFIELDS, $value); curl_setopt($ch, CURLOPT_POST, true); - } + } elseif (HttpMethod::PATCH === $method) { + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); - if (HttpMethod::DELETE === $method) - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::DELETE); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::PATCH->name); + } elseif (HttpMethod::DELETE === $method) curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::DELETE->name); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_HTTPHEADER, array_unique($headers)); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $res = curl_exec($ch); - curl_close($ch); - if (false === $res) throw new UnexpectedValueException(curl_error($ch)); + curl_close($ch); + try { $res = json_decode($res, false, 512, JSON_THROW_ON_ERROR); } catch (Exception) { @@ -93,13 +105,18 @@ protected function request(string $path, string $method, array $options = []): m return $res; } - public function post(string $path, array $options = []): mixed + public function patch(string $path, array $payload = [], array $headers = []): mixed + { + return $this->request($path, HttpMethod::PATCH, $payload, $headers); + } + + public function post(string $path, array $payload = [], array $headers = []): mixed { - return $this->request($path, HttpMethod::POST, $options); + return $this->request($path, HttpMethod::POST, $payload, $headers); } - public function get(string $path, array $options = []): mixed + public function get(string $path, array $params = [], array $headers = []): mixed { - return $this->request($path, HttpMethod::GET, $options); + return $this->request($path, HttpMethod::GET, $params, $headers); } } diff --git a/src/Client.php b/src/Client.php index 513ab22..fe749ab 100755 --- a/src/Client.php +++ b/src/Client.php @@ -5,6 +5,7 @@ use Seven\Api\Resource\AnalyticsResource; use Seven\Api\Resource\BalanceResource; use Seven\Api\Resource\ContactsResource; +use Seven\Api\Resource\GroupsResource; use Seven\Api\Resource\HooksResource; use Seven\Api\Resource\JournalResource; use Seven\Api\Resource\LookupResource; @@ -21,6 +22,7 @@ class Client extends BaseClient public AnalyticsResource $analytics; public BalanceResource $balance; public ContactsResource $contacts; + public GroupsResource $groups; public HooksResource $hooks; public JournalResource $journal; public LookupResource $lookup; @@ -39,6 +41,7 @@ public function __construct(string $apiKey, string $sentWith = 'php-api') $this->analytics = new AnalyticsResource($this); $this->balance = new BalanceResource($this); $this->contacts = new ContactsResource($this); + $this->groups = new GroupsResource($this); $this->hooks = new HooksResource($this); $this->journal = new JournalResource($this); $this->lookup = new LookupResource($this); diff --git a/src/Constant/HttpMethod.php b/src/Constant/HttpMethod.php index 7f15872..16fd908 100644 --- a/src/Constant/HttpMethod.php +++ b/src/Constant/HttpMethod.php @@ -2,12 +2,10 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -class HttpMethod { - use Reflectable; - - public const DELETE = 'DELETE'; - public const GET = 'GET'; - public const POST = 'POST'; +enum HttpMethod +{ + case DELETE; + case GET; + case PATCH; + case POST; } diff --git a/src/Params/Groups/ListParams.php b/src/Params/Groups/ListParams.php new file mode 100644 index 0000000..ef81cd6 --- /dev/null +++ b/src/Params/Groups/ListParams.php @@ -0,0 +1,36 @@ +limit; + } + + public function setLimit(int $limit): void + { + $this->limit = $limit; + } + + public function getOffset(): int + { + return $this->offset; + } + + public function setOffset(int $offset): void + { + $this->offset = $offset; + } +} diff --git a/src/Resource/GroupsResource.php b/src/Resource/GroupsResource.php new file mode 100644 index 0000000..b842c44 --- /dev/null +++ b/src/Resource/GroupsResource.php @@ -0,0 +1,44 @@ +client->delete($path)); + } + + public function create(string $name): Group + { + return new Group($this->client->post('groups', compact('name'))); + } + + public function update(int $id, string $name): Group + { + return new Group($this->client->patch('groups/' . $id, compact('name'))); + } + + public function validate($params): void + { + // TODO? + } + + public function list(ListParams $params = new ListParams): ListGroups + { + return new ListGroups($this->client->get('groups', $params->toArray())); + } + + public function get(int $id): Group + { + return new Group($this->client->get('groups/' . $id)); + } +} diff --git a/src/Response/Groups/Group.php b/src/Response/Groups/Group.php new file mode 100644 index 0000000..85ce1c3 --- /dev/null +++ b/src/Response/Groups/Group.php @@ -0,0 +1,39 @@ +created = $data->created; + $this->id = $data->id; + $this->membersCount = $data->members_count; + $this->name = $data->name; + } + + public function getId(): int + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function getCreated(): string + { + return $this->created; + } + + public function getMembersCount(): int + { + return $this->membersCount; + } +} diff --git a/src/Response/Groups/GroupDelete.php b/src/Response/Groups/GroupDelete.php new file mode 100644 index 0000000..e34614c --- /dev/null +++ b/src/Response/Groups/GroupDelete.php @@ -0,0 +1,18 @@ +success = $obj->success; + } + + public function getSuccess(): bool + { + return $this->success; + } +} diff --git a/src/Response/Groups/ListGroups.php b/src/Response/Groups/ListGroups.php new file mode 100644 index 0000000..3c4a3c0 --- /dev/null +++ b/src/Response/Groups/ListGroups.php @@ -0,0 +1,28 @@ +data = array_map(fn(object $entry) => new Group($entry), $obj->data); + $this->pagingMetadata = new PagingMetadata($obj->pagingMetadata); + } + + public function getData(): array + { + return $this->data; + } + + public function getPagingMetadata(): PagingMetadata + { + return $this->pagingMetadata; + } +} diff --git a/src/Response/PagingMetadata.php b/src/Response/PagingMetadata.php new file mode 100644 index 0000000..ed43c4c --- /dev/null +++ b/src/Response/PagingMetadata.php @@ -0,0 +1,39 @@ +count = $data->count; + $this->hasMore = $data->has_more; + $this->limit = $data->limit; + $this->offset = $data->offset; + } + + public function getCount(): int + { + return $this->count; + } + + public function isHasMore(): bool + { + return $this->hasMore; + } + + public function getLimit(): int + { + return $this->limit; + } + + public function getOffset(): int + { + return $this->offset; + } +} \ No newline at end of file diff --git a/tests/Client/GroupsTest.php b/tests/Client/GroupsTest.php new file mode 100644 index 0000000..6082547 --- /dev/null +++ b/tests/Client/GroupsTest.php @@ -0,0 +1,36 @@ +client->groups->create($name); + + $this->assertEquals($name, $created->getName()); + + $group = $this->client->groups->get($created->getId()); + + $this->assertEquals($created, $group); + + $listParams = new ListParams(); + $listParams->setLimit(77); + $listParams->setOffset(0); + $list = $this->client->groups->list(); + //$this->assertEquals($listParams->getLimit(), $list->getPagingMetadata()->getLimit()); + $this->assertEquals($listParams->getOffset(), $list->getPagingMetadata()->getOffset()); + $match = array_filter($list->getData(), fn($entry) => $entry->getId() === $created->getId()); + $this->assertCount(1, $match); + + $newName = 'PHP Test Group With a new Name'; + $updated = $this->client->groups->update($created->getId(), $newName); + $this->assertNotEquals($created->getName(), $updated->getName()); + + $deleted = $this->client->groups->delete($created->getId()); + $this->assertTrue($deleted->getSuccess()); + } +} From 8a739950be12b341952211bc62a7ea615cdc7809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 10:02:11 +0200 Subject: [PATCH 03/54] sync /contacts --- src/Constant/ContactsAction.php | 13 -- src/Library/OrderDirection.php | 9 ++ src/Params/Contacts/ListParams.php | 95 ++++++++++++++ src/Params/ContactsParams.php | 70 ----------- src/Params/WriteContactParams.php | 11 -- src/Resource/ContactsResource.php | 75 ++++------- src/Response/Contacts/Contact.php | 103 ++++++++++++--- src/Response/Contacts/Initials.php | 17 +++ src/Response/Contacts/ListContacts.php | 28 +++++ src/Response/Contacts/Properties.php | 168 +++++++++++++++++++++++++ src/Response/Contacts/Validation.php | 27 ++++ src/Validator/ContactsValidator.php | 58 --------- tests/Client/ContactsTest.php | 115 ++++++++--------- tests/Client/GroupsTest.php | 2 +- 14 files changed, 509 insertions(+), 282 deletions(-) delete mode 100644 src/Constant/ContactsAction.php create mode 100644 src/Library/OrderDirection.php create mode 100644 src/Params/Contacts/ListParams.php delete mode 100644 src/Params/ContactsParams.php delete mode 100644 src/Params/WriteContactParams.php create mode 100644 src/Response/Contacts/Initials.php create mode 100644 src/Response/Contacts/ListContacts.php create mode 100644 src/Response/Contacts/Properties.php create mode 100644 src/Response/Contacts/Validation.php delete mode 100755 src/Validator/ContactsValidator.php diff --git a/src/Constant/ContactsAction.php b/src/Constant/ContactsAction.php deleted file mode 100644 index 5059075..0000000 --- a/src/Constant/ContactsAction.php +++ /dev/null @@ -1,13 +0,0 @@ -groupId; + } + + public function setGroupId(?int $groupId): self + { + $this->groupId = $groupId; + return $this; + } + + public function getOrderBy(): ?string + { + return $this->orderBy; + } + + public function setOrderBy(?string $orderBy): self + { + $this->orderBy = $orderBy; + return $this; + } + + public function getOrderDirection(): ?OrderDirection + { + return $this->orderDirection; + } + + public function setOrderDirection(?OrderDirection $orderDirection): self + { + $this->orderDirection = $orderDirection; + return $this; + } + + public function getSearch(): ?string + { + return $this->search; + } + + public function setSearch(?string $search): self + { + $this->search = $search; + return $this; + } + + public function toArray(): array + { + $arr = get_object_vars($this); + $arr['group_id'] = $this->groupId; + $arr['order_by'] = $this->orderBy; + $arr['order_direction'] = $this->orderDirection; + + unset($arr['groupId'], $arr['orderBy'], $arr['orderDirection']); + + return $arr; + } + + public function getLimit(): int + { + return $this->limit; + } + + public function setLimit(int $limit): self + { + $this->limit = $limit; + return $this; + } + + public function getOffset(): int + { + return $this->offset; + } + + public function setOffset(int $offset): self + { + $this->offset = $offset; + return $this; + } +} diff --git a/src/Params/ContactsParams.php b/src/Params/ContactsParams.php deleted file mode 100644 index 7f192d0..0000000 --- a/src/Params/ContactsParams.php +++ /dev/null @@ -1,70 +0,0 @@ -action = $action; - } - - public function getAction(): string { - return $this->action; - } - - public function setAction(string $action): self { - $this->action = $action; - return $this; - } - - public function getId(): ?int { - return $this->id; - } - - public function setId(?int $id): self { - $this->id = $id; - return $this; - } - - public function getNick(): ?string { - return $this->nick; - } - - public function setNick(?string $nick): self { - $this->nick = $nick; - return $this; - } - - public function getMobile(): ?string { - return $this->mobile; - } - - public function setMobile(?string $mobile): self { - $this->mobile = $mobile; - return $this; - } - - public function getEmail(): ?string { - return $this->email; - } - - public function setEmail(?string $email): self { - $this->email = $email; - return $this; - } - - public function toArray(): array { - $arr = get_object_vars($this); - $arr = array_merge($arr, [ - 'empfaenger' => $arr['mobile'], - 'json' => true, - ]); - unset($arr['mobile']); - return $arr; - } -} diff --git a/src/Params/WriteContactParams.php b/src/Params/WriteContactParams.php deleted file mode 100644 index f96b44f..0000000 --- a/src/Params/WriteContactParams.php +++ /dev/null @@ -1,11 +0,0 @@ -setId($id); - $this->validate($params); - $res = $this->client->post('contacts', $params->toArray()); - - return new ContactDelete($res); +class ContactsResource extends Resource +{ + public function delete(int $id): void + { + $this->client->delete('contacts/' . $id); } - /** - * @param ContactsParams $params - * @throws InvalidRequiredArgumentException - */ - public function validate($params): void { - (new ContactsValidator($params))->validate(); + public function validate($params): void + { + // TODO? } - /** - * @throws InvalidRequiredArgumentException - */ - public function create(): ContactCreate { - $params = new WriteContactParams; - $this->validate($params); - $res = $this->client->get('contacts', $params->toArray()); - - return new ContactCreate($res); + public function create(Contact $contact): Contact + { + return Contact::fromApi($this->client->post('contacts', $contact->toPayload())); } - /** - * @throws InvalidRequiredArgumentException - */ - public function write(WriteContactParams $params): ContactEdit { - $this->validate($params); - $res = $this->client->get('contacts', $params->toArray()); - - return new ContactEdit($res); + public function update(Contact $contact): Contact + { + return Contact::fromApi($this->client->patch('contacts/' . $contact->getId(), $contact->toPayload())); } - /** - * @return Contact[] - * @throws InvalidRequiredArgumentException - */ - public function read(int $id = null): array { - $params = (new ContactsParams(ContactsAction::READ))->setId($id); - $this->validate($params); - $res = $this->client->get('contacts', $params->toArray()); + public function list(ListParams $params = new ListParams): ListContacts + { + return new ListContacts($this->client->get('contacts', $params->toArray())); + } - return array_map(static function ($value) { - return new Contact($value); - }, $res); + public function get(int $id): Contact + { + return Contact::fromApi($this->client->get('contacts/' . $id)); } } diff --git a/src/Response/Contacts/Contact.php b/src/Response/Contacts/Contact.php index 091b63e..8d3b5d1 100644 --- a/src/Response/Contacts/Contact.php +++ b/src/Response/Contacts/Contact.php @@ -2,26 +2,101 @@ namespace Seven\Api\Response\Contacts; -class Contact { - protected int $id; - protected string $name; - protected string $number; +class Contact +{ + protected string $avatar; + protected readonly string $created; + protected readonly int $id; + protected Initials $initials; + /** @var int[] $groups */ + protected array $groups = []; + protected Properties $properties; + protected Validation $validation; - public function __construct(object $data) { - $this->id = (int)$data->ID; - $this->name = $data->Name; - $this->number = $data->Number; + public static function fromApi(object $obj): Contact + { + $contact = new Contact; + $contact->avatar = $obj->avatar; + $contact->created = $obj->created; + $contact->groups = $obj->groups; + $contact->id = $obj->id; + $contact->initials = Initials::fromApi($obj->initials); + $contact->properties = Properties::fromApi($obj->properties); + $contact->validation = Validation::fromApi($obj->validation); + return $contact; } - public function getId(): int { - return $this->id; + public function toPayload(): array + { + return [ + ...$this->properties->toPayload(), + 'avatar' => $this->avatar, + 'groups[]' => $this->groups, + ]; + } + + public function getAvatar(): string + { + return $this->avatar; + } + + public function setAvatar(string $avatar): Contact + { + $this->avatar = $avatar; + return $this; + } + + public function getInitials(): Initials + { + return $this->initials; + } + + public function setInitials(Initials $initials): Contact + { + $this->initials = $initials; + return $this; + } + + public function getGroups(): array + { + return $this->groups; } - public function getName(): string { - return $this->name; + public function setGroups(array $groups): Contact + { + $this->groups = $groups; + return $this; + } + + public function getProperties(): Properties + { + return $this->properties; + } + + public function setProperties(Properties $properties): Contact + { + $this->properties = $properties; + return $this; + } + + public function getValidation(): Validation + { + return $this->validation; + } + + public function setValidation(Validation $validation): Contact + { + $this->validation = $validation; + return $this; + } + + public function getId(): int + { + return $this->id; } - public function getNumber(): string { - return $this->number; + public function getCreated(): string + { + return $this->created; } } diff --git a/src/Response/Contacts/Initials.php b/src/Response/Contacts/Initials.php new file mode 100644 index 0000000..0089acf --- /dev/null +++ b/src/Response/Contacts/Initials.php @@ -0,0 +1,17 @@ +color = $obj->color; + $initials->initials = $obj->initials; + return $initials; + } +} diff --git a/src/Response/Contacts/ListContacts.php b/src/Response/Contacts/ListContacts.php new file mode 100644 index 0000000..2439ddb --- /dev/null +++ b/src/Response/Contacts/ListContacts.php @@ -0,0 +1,28 @@ +data = array_map(fn(object $entry) => Contact::fromApi($entry), $obj->data); + $this->pagingMetadata = new PagingMetadata($obj->pagingMetadata); + } + + public function getData(): array + { + return $this->data; + } + + public function getPagingMetadata(): PagingMetadata + { + return $this->pagingMetadata; + } +} diff --git a/src/Response/Contacts/Properties.php b/src/Response/Contacts/Properties.php new file mode 100644 index 0000000..8938d0a --- /dev/null +++ b/src/Response/Contacts/Properties.php @@ -0,0 +1,168 @@ +address = $obj->address; + if ($obj->birthday) $properties->birthday = new DateTime($obj->birthday); + $properties->city = $obj->city; + $properties->email = $obj->email; + $properties->firstname = $obj->firstname; + $properties->fullname = $obj->fullname; + $properties->homeNumber = $obj->home_number; + $properties->lastname = $obj->lastname; + $properties->mobileNumber = $obj->mobile_number; + $properties->notes = $obj->notes; + $properties->postalCode = $obj->postal_code; + return $properties; + } + + public function toPayload(): array + { + return [ + 'address' => $this->getAddress(), + 'birthday' => $this->getBirthday()->format('Y-m-d'), + 'city' => $this->getCity(), + 'email' => $this->getEmail(), + 'firstname' => $this->getFirstname(), + 'home_number' => $this->getHomeNumber(), + 'lastname' => $this->getLastname(), + 'mobile_number' => $this->getMobileNumber(), + 'notes' => $this->getNotes(), + 'postal_code' => $this->getPostalCode(), + ]; + } + + public function getAddress(): ?string + { + return $this->address; + } + + public function setAddress(?string $address): Properties + { + $this->address = $address; + return $this; + } + + public function getBirthday(): ?DateTime + { + return $this->birthday; + } + + public function setBirthday(?DateTime $birthday): Properties + { + $this->birthday = $birthday; + return $this; + } + + public function getCity(): ?string + { + return $this->city; + } + + public function setCity(?string $city): Properties + { + $this->city = $city; + return $this; + } + + public function getEmail(): ?string + { + return $this->email; + } + + public function setEmail(?string $email): Properties + { + $this->email = $email; + return $this; + } + + public function getFirstname(): ?string + { + return $this->firstname; + } + + public function setFirstname(?string $firstname): Properties + { + $this->firstname = $firstname; + return $this; + } + + public function getHomeNumber(): ?string + { + return $this->homeNumber; + } + + public function setHomeNumber(?string $homeNumber): Properties + { + $this->homeNumber = $homeNumber; + return $this; + } + + public function getLastname(): ?string + { + return $this->lastname; + } + + public function setLastname(?string $lastname): Properties + { + $this->lastname = $lastname; + return $this; + } + + public function getMobileNumber(): ?string + { + return $this->mobileNumber; + } + + public function setMobileNumber(?string $mobileNumber): Properties + { + $this->mobileNumber = $mobileNumber; + return $this; + } + + public function getNotes(): ?string + { + return $this->notes; + } + + public function setNotes(?string $notes): Properties + { + $this->notes = $notes; + return $this; + } + + public function getPostalCode(): ?string + { + return $this->postalCode; + } + + public function setPostalCode(?string $postalCode): Properties + { + $this->postalCode = $postalCode; + return $this; + } + + public function getFullname(): ?string + { + return $this->fullname; + } +} diff --git a/src/Response/Contacts/Validation.php b/src/Response/Contacts/Validation.php new file mode 100644 index 0000000..36331ba --- /dev/null +++ b/src/Response/Contacts/Validation.php @@ -0,0 +1,27 @@ +state = $obj->state; + $validation->timestamp = $obj->timestamp; + return $validation; + } + + public function getState(): ?string + { + return $this->state; + } + + public function getTimestamp(): ?string + { + return $this->timestamp; + } +} diff --git a/src/Validator/ContactsValidator.php b/src/Validator/ContactsValidator.php deleted file mode 100755 index aa417a8..0000000 --- a/src/Validator/ContactsValidator.php +++ /dev/null @@ -1,58 +0,0 @@ -params = $params; - } - - /** - * @throws InvalidRequiredArgumentException - */ - public function validate(): void { - $this->action(); - } - - /** @throws InvalidRequiredArgumentException */ - public function action(): void { - $action = $this->params->getAction(); - - switch ($action) { - case ContactsAction::DELETE: - $this->delete(); - break; - case ContactsAction::READ: - $this->read(); - break; - case ContactsAction::WRITE: - $this->write(); - break; - - default: - throw new InvalidRequiredArgumentException('Unknown action: ' . $action); - } - } - - /** - * @throws InvalidRequiredArgumentException - */ - public function delete(): void { - $id = $this->params->getId(); - - if ($id === null) - throw new InvalidRequiredArgumentException('Missing parameter id'); - } - - public function read(): void { - } - - public function write(): void { - } -} diff --git a/tests/Client/ContactsTest.php b/tests/Client/ContactsTest.php index b437421..84ab5e0 100755 --- a/tests/Client/ContactsTest.php +++ b/tests/Client/ContactsTest.php @@ -2,69 +2,58 @@ namespace Seven\Tests\Client; -use Seven\Api\Params\WriteContactParams; +use DateTime; +use Seven\Api\Library\OrderDirection; +use Seven\Api\Params\Contacts\ListParams; use Seven\Api\Response\Contacts\Contact; -use Seven\Api\Response\Contacts\ContactCreate; -use Seven\Api\Response\Contacts\ContactDelete; - -class ContactsTest extends BaseTest { - public function testContactsRead(): void { - $res = $this->client->contacts->read(); - - $this->assertIsArray($res); - - if (count($res)) { - $this->assertRead($res); - $contact = reset($res); - $contact = $this->client->contacts->read($contact->getId()); - $this->assertRead($contact); - } - } - - private function assertRead(array $res): void { - $this->assertContact(reset($res)); - } - - private function assertContact(Contact $c): void { - $this->assertGreaterThanOrEqual(1, $c->getId()); - } - - public function testContactsCreateEditDelete(): void { - $c = $this->client->contacts->create(); - $contactId = $c->getId(); - - $this->assertCreate($c); - - $writeParams = (new WriteContactParams) - ->setEmail('Tommy_Testersen@web.de') - ->setId($contactId) - ->setMobile('+0123459877676') - ->setNick('Tommy Testersen'); - $writeResponse = $this->client->contacts->write($writeParams); - $this->assertEquals(152, $writeResponse->getReturn()); - - $this->assertRead($this->client->contacts->read($contactId)); - - $this->assertDeleteSuccess($this->client->contacts->delete($contactId)); - } - - private function assertCreate(ContactCreate $c): void { - $contactId = $c->getId(); - - $this->assertIsInt($contactId); - $this->assertGreaterThan(0, $contactId); - $this->assertEquals(152, $c->getCode()); - } - - private function assertDeleteSuccess(ContactDelete $contactDelete): void { - $this->assertEquals(152, $contactDelete->getCode()); - } - - public function testContactsCreateDelete(): void { - $res = $this->client->contacts->create(); - $this->assertCreate($res); - - $res = $this->client->contacts->delete($res->getId()); - $this->assertDeleteSuccess($res); +use Seven\Api\Response\Contacts\Properties; + +class ContactsTest extends BaseTest +{ + public function testAll(): void + { + $toCreate = (new Contact) + ->setAvatar('https://avatars.githubusercontent.com/u/37155205') + ->setGroups([]) + ->setProperties( + (new Properties) + ->setAddress('Willestr. 4-6') + ->setBirthday(new DateTime('01.01.2000')) + ->setCity('Kiel') + ->setEmail('support@seven.io') + ->setFirstname('Dan') + ->setHomeNumber('4943130149270') + ->setLastname('Developer') + ->setMobileNumber('4917999999999') + ->setNotes('CPaaS') + ->setPostalCode('24103') + ); + $created = $this->client->contacts->create($toCreate); + + $this->assertEquals($toCreate->getProperties(), $created->getProperties()); + + $contact = $this->client->contacts->get($created->getId()); + + $this->assertEquals($created->getProperties(), $contact->getProperties()); + + $listParams = (new ListParams) + ->setLimit(77) + ->setOffset(0) + ->setGroupId(null) + ->setSearch('') + ->setOrderBy('') + ->setOrderDirection(OrderDirection::Ascending); + $list = $this->client->contacts->list($listParams); + $this->assertEquals($listParams->getLimit(), $list->getPagingMetadata()->getLimit()); + $this->assertEquals($listParams->getOffset(), $list->getPagingMetadata()->getOffset()); + $match = array_filter($list->getData(), fn($entry) => $entry->getId() === $created->getId()); + $this->assertCount(1, $match); + + $toUpdate = clone $contact; + $toUpdate->getProperties()->setNotes('New Notes'); + $updated = $this->client->contacts->update($toUpdate); + $this->assertNotEquals($created->getProperties()->getNotes(), $updated->getProperties()->getNotes()); + + $this->client->contacts->delete($created->getId()); } } diff --git a/tests/Client/GroupsTest.php b/tests/Client/GroupsTest.php index 6082547..5d22d8e 100644 --- a/tests/Client/GroupsTest.php +++ b/tests/Client/GroupsTest.php @@ -20,7 +20,7 @@ public function testAll(): void $listParams = new ListParams(); $listParams->setLimit(77); $listParams->setOffset(0); - $list = $this->client->groups->list(); + $list = $this->client->groups->list($listParams); //$this->assertEquals($listParams->getLimit(), $list->getPagingMetadata()->getLimit()); $this->assertEquals($listParams->getOffset(), $list->getPagingMetadata()->getOffset()); $match = array_filter($list->getData(), fn($entry) => $entry->getId() === $created->getId()); From cd666d80a5a268bc48bd8ec1411d62f107e19eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 11:37:51 +0200 Subject: [PATCH 04/54] implement /numbers --- src/Client.php | 3 + src/Constant/PaymentInterval.php | 9 ++ src/Params/Numbers/ListAvailableParams.php | 70 +++++++++++ src/Params/Numbers/OrderParams.php | 42 +++++++ src/Params/Numbers/UpdateParams.php | 67 ++++++++++ src/Resource/NumbersResource.php | 53 ++++++++ src/Response/Numbers/ActiveNumbers.php | 21 ++++ src/Response/Numbers/AvailableNumbers.php | 21 ++++ src/Response/Numbers/NumberDeletion.php | 18 +++ src/Response/Numbers/NumberOrder.php | 25 ++++ src/Response/Numbers/PhoneNumber.php | 115 ++++++++++++++++++ src/Response/Numbers/PhoneNumberBilling.php | 39 ++++++ .../Numbers/PhoneNumberBillingFees.php | 63 ++++++++++ src/Response/Numbers/PhoneNumberFeatures.php | 50 ++++++++ .../Numbers/PhoneNumberForwardInboundSms.php | 37 ++++++ .../PhoneNumberForwardInboundSmsToMail.php | 38 ++++++ .../PhoneNumberForwardInboundSmsToSms.php | 38 ++++++ src/Response/Numbers/PhoneNumberOffer.php | 46 +++++++ src/Response/Numbers/PhoneNumberOfferFees.php | 39 ++++++ .../Numbers/PhoneNumberOfferFeesPeriod.php | 25 ++++ tests/Client/NumbersTest.php | 49 ++++++++ 21 files changed, 868 insertions(+) create mode 100644 src/Constant/PaymentInterval.php create mode 100644 src/Params/Numbers/ListAvailableParams.php create mode 100644 src/Params/Numbers/OrderParams.php create mode 100644 src/Params/Numbers/UpdateParams.php create mode 100644 src/Resource/NumbersResource.php create mode 100644 src/Response/Numbers/ActiveNumbers.php create mode 100644 src/Response/Numbers/AvailableNumbers.php create mode 100644 src/Response/Numbers/NumberDeletion.php create mode 100644 src/Response/Numbers/NumberOrder.php create mode 100644 src/Response/Numbers/PhoneNumber.php create mode 100644 src/Response/Numbers/PhoneNumberBilling.php create mode 100644 src/Response/Numbers/PhoneNumberBillingFees.php create mode 100644 src/Response/Numbers/PhoneNumberFeatures.php create mode 100644 src/Response/Numbers/PhoneNumberForwardInboundSms.php create mode 100644 src/Response/Numbers/PhoneNumberForwardInboundSmsToMail.php create mode 100644 src/Response/Numbers/PhoneNumberForwardInboundSmsToSms.php create mode 100644 src/Response/Numbers/PhoneNumberOffer.php create mode 100644 src/Response/Numbers/PhoneNumberOfferFees.php create mode 100644 src/Response/Numbers/PhoneNumberOfferFeesPeriod.php create mode 100644 tests/Client/NumbersTest.php diff --git a/src/Client.php b/src/Client.php index fe749ab..8f20d28 100755 --- a/src/Client.php +++ b/src/Client.php @@ -9,6 +9,7 @@ use Seven\Api\Resource\HooksResource; use Seven\Api\Resource\JournalResource; use Seven\Api\Resource\LookupResource; +use Seven\Api\Resource\NumbersResource; use Seven\Api\Resource\PricingResource; use Seven\Api\Resource\RcsResource; use Seven\Api\Resource\SmsResource; @@ -26,6 +27,7 @@ class Client extends BaseClient public HooksResource $hooks; public JournalResource $journal; public LookupResource $lookup; + public NumbersResource $numbers; public PricingResource $pricing; public RcsResource $rcs; public SmsResource $sms; @@ -45,6 +47,7 @@ public function __construct(string $apiKey, string $sentWith = 'php-api') $this->hooks = new HooksResource($this); $this->journal = new JournalResource($this); $this->lookup = new LookupResource($this); + $this->numbers = new NumbersResource($this); $this->pricing = new PricingResource($this); $this->rcs = new RcsResource($this); $this->sms = new SmsResource($this); diff --git a/src/Constant/PaymentInterval.php b/src/Constant/PaymentInterval.php new file mode 100644 index 0000000..cde4c89 --- /dev/null +++ b/src/Constant/PaymentInterval.php @@ -0,0 +1,9 @@ +country; + } + + public function setCountry(?string $country): ListAvailableParams + { + $this->country = $country; + return $this; + } + + public function isFeaturesSms(): bool + { + return $this->featuresSms; + } + + public function setFeaturesSms(bool $featuresSms): ListAvailableParams + { + $this->featuresSms = $featuresSms; + return $this; + } + + public function isFeaturesApplicationToPersonSms(): bool + { + return $this->featuresApplicationToPersonSms; + } + + public function setFeaturesApplicationToPersonSms(bool $featuresApplicationToPersonSms): ListAvailableParams + { + $this->featuresApplicationToPersonSms = $featuresApplicationToPersonSms; + return $this; + } + + public function isFeaturesVoice(): bool + { + return $this->featuresVoice; + } + + public function setFeaturesVoice(bool $featuresVoice): ListAvailableParams + { + $this->featuresVoice = $featuresVoice; + return $this; + } + + public function toArray(): array + { + $arr = get_object_vars($this); + + $arr['features_a2p_sms'] = $this->featuresApplicationToPersonSms; + $arr['features_sms'] = $this->featuresSms; + $arr['features_voice'] = $this->featuresVoice; + + unset($arr['featuresApplicationToPersonSms'], $arr['featuresSms'], $arr['featuresVoice']); + + return $arr; + } +} diff --git a/src/Params/Numbers/OrderParams.php b/src/Params/Numbers/OrderParams.php new file mode 100644 index 0000000..669b3ca --- /dev/null +++ b/src/Params/Numbers/OrderParams.php @@ -0,0 +1,42 @@ +paymentInterval->value; + + unset($arr['paymentInterval']); + + return $arr; + } + + public function getPaymentInterval(): ?PaymentInterval + { + return $this->paymentInterval; + } + + public function setPaymentInterval(?PaymentInterval $paymentInterval): self + { + $this->paymentInterval = $paymentInterval; + return $this; + } + + public function getNumber(): string + { + return $this->number; + } +} diff --git a/src/Params/Numbers/UpdateParams.php b/src/Params/Numbers/UpdateParams.php new file mode 100644 index 0000000..6ac835f --- /dev/null +++ b/src/Params/Numbers/UpdateParams.php @@ -0,0 +1,67 @@ +emailForward; + } + + public function setEmailForward(?array $emailForward): UpdateParams + { + $this->emailForward = $emailForward; + return $this; + } + + public function getFriendlyName(): ?string + { + return $this->friendlyName; + } + + public function setFriendlyName(?string $friendlyName): UpdateParams + { + $this->friendlyName = $friendlyName; + return $this; + } + + public function getSmsForward(): ?array + { + return $this->smsForward; + } + + public function setSmsForward(?array $smsForward): UpdateParams + { + $this->smsForward = $smsForward; + return $this; + } + + public function toArray(): array + { + $arr = get_object_vars($this); + + $arr['email_forward'] = $this->emailForward; + $arr['friendly_name'] = $this->friendlyName; + $arr['sms_forward'] = $this->smsForward; + + unset($arr['emailForward'], $arr['friendlyName'], $arr['smsForward'], $arr['number']); + + return $arr; + } + + public function getNumber(): string + { + return $this->number; + } +} diff --git a/src/Resource/NumbersResource.php b/src/Resource/NumbersResource.php new file mode 100644 index 0000000..4442ed7 --- /dev/null +++ b/src/Resource/NumbersResource.php @@ -0,0 +1,53 @@ +client->delete($path)); + } + + public function order(OrderParams $params): NumberOrder + { + return new NumberOrder($this->client->post('numbers/order', $params->toArray())); + } + + public function update(UpdateParams $params): PhoneNumber + { + return new PhoneNumber($this->client->patch('numbers/active/' . $params->getNumber(), $params->toArray())); + } + + public function validate($params): void + { + // TODO? + } + + public function listActive(): ActiveNumbers + { + return new ActiveNumbers($this->client->get('numbers/active')); + } + + public function get(string $number): PhoneNumber + { + return new PhoneNumber($this->client->get('numbers/active/' . $number)); + } + + public function listAvailable(ListAvailableParams $params = new ListAvailableParams): AvailableNumbers + { + return new AvailableNumbers($this->client->get('numbers/available', $params->toArray())); + } +} diff --git a/src/Response/Numbers/ActiveNumbers.php b/src/Response/Numbers/ActiveNumbers.php new file mode 100644 index 0000000..c77ae6f --- /dev/null +++ b/src/Response/Numbers/ActiveNumbers.php @@ -0,0 +1,21 @@ +activeNumbers = array_map(fn($obj) => new PhoneNumber($obj), $data->activeNumbers); + } + + public function getActiveNumbers(): array + { + return $this->activeNumbers; + } +} diff --git a/src/Response/Numbers/AvailableNumbers.php b/src/Response/Numbers/AvailableNumbers.php new file mode 100644 index 0000000..06358c7 --- /dev/null +++ b/src/Response/Numbers/AvailableNumbers.php @@ -0,0 +1,21 @@ +availableNumbers = array_map(fn($obj) => new PhoneNumberOffer($obj), $data->availableNumbers); + } + + public function getAvailableNumbers(): array + { + return $this->availableNumbers; + } +} diff --git a/src/Response/Numbers/NumberDeletion.php b/src/Response/Numbers/NumberDeletion.php new file mode 100644 index 0000000..b7e3274 --- /dev/null +++ b/src/Response/Numbers/NumberDeletion.php @@ -0,0 +1,18 @@ +success = $obj->success; + } + + public function isSuccess(): bool + { + return $this->success; + } +} diff --git a/src/Response/Numbers/NumberOrder.php b/src/Response/Numbers/NumberOrder.php new file mode 100644 index 0000000..97d4f17 --- /dev/null +++ b/src/Response/Numbers/NumberOrder.php @@ -0,0 +1,25 @@ +error = $obj->error; + $this->success = $obj->success; + } + + public function getError(): ?string + { + return $this->error; + } + + public function isSuccess(): bool + { + return $this->success; + } +} diff --git a/src/Response/Numbers/PhoneNumber.php b/src/Response/Numbers/PhoneNumber.php new file mode 100644 index 0000000..672f1e0 --- /dev/null +++ b/src/Response/Numbers/PhoneNumber.php @@ -0,0 +1,115 @@ +billing = new PhoneNumberBilling($data->billing); + $this->country = $data->country; + $this->created = $data->created; + $this->expires = $data->expires; + $this->features = new PhoneNumberFeatures($data->features); + $this->forwardInboundSms = new PhoneNumberForwardInboundSms($data->forward_sms_mo); + $this->friendlyName = $data->friendly_name; + $this->number = $data->number; + } + + public function getBilling(): PhoneNumberBilling + { + return $this->billing; + } + + public function setBilling(PhoneNumberBilling $billing): PhoneNumber + { + $this->billing = $billing; + return $this; + } + + public function getCountry(): string + { + return $this->country; + } + + public function setCountry(string $country): PhoneNumber + { + $this->country = $country; + return $this; + } + + public function getCreated(): string + { + return $this->created; + } + + public function setCreated(string $created): PhoneNumber + { + $this->created = $created; + return $this; + } + + public function getExpires(): ?string + { + return $this->expires; + } + + public function setExpires(?string $expires): PhoneNumber + { + $this->expires = $expires; + return $this; + } + + public function getFeatures(): PhoneNumberFeatures + { + return $this->features; + } + + public function setFeatures(PhoneNumberFeatures $features): PhoneNumber + { + $this->features = $features; + return $this; + } + + public function getForwardInboundSms(): PhoneNumberForwardInboundSms + { + return $this->forwardInboundSms; + } + + public function setForwardInboundSms(PhoneNumberForwardInboundSms $forwardInboundSms): PhoneNumber + { + $this->forwardInboundSms = $forwardInboundSms; + return $this; + } + + public function getFriendlyName(): string + { + return $this->friendlyName; + } + + public function setFriendlyName(string $friendlyName): PhoneNumber + { + $this->friendlyName = $friendlyName; + return $this; + } + + public function getNumber(): string + { + return $this->number; + } + + public function setNumber(string $number): PhoneNumber + { + $this->number = $number; + return $this; + } +} diff --git a/src/Response/Numbers/PhoneNumberBilling.php b/src/Response/Numbers/PhoneNumberBilling.php new file mode 100644 index 0000000..0f5b2e4 --- /dev/null +++ b/src/Response/Numbers/PhoneNumberBilling.php @@ -0,0 +1,39 @@ +fees = $data->fees; + $this->paymentInterval = $data->payment_interval; + } + + public function getFees(): PhoneNumberBillingFees + { + return $this->fees; + } + + public function setFees(PhoneNumberBillingFees $fees): PhoneNumberBilling + { + $this->fees = $fees; + return $this; + } + + public function getPaymentInterval(): PaymentInterval + { + return $this->paymentInterval; + } + + public function setPaymentInterval(PaymentInterval $paymentInterval): PhoneNumberBilling + { + $this->paymentInterval = $paymentInterval; + return $this; + } +} diff --git a/src/Response/Numbers/PhoneNumberBillingFees.php b/src/Response/Numbers/PhoneNumberBillingFees.php new file mode 100644 index 0000000..9d4f4fd --- /dev/null +++ b/src/Response/Numbers/PhoneNumberBillingFees.php @@ -0,0 +1,63 @@ +basicCharge = $data->basic_charge; + $this->setup = $data->setup; + $this->smsInbound = $data->sms_mo; + $this->voiceInbound = $data->voice_mo; + } + + public function getBasicCharge(): float + { + return $this->basicCharge; + } + + public function setBasicCharge(float $basicCharge): PhoneNumberBillingFees + { + $this->basicCharge = $basicCharge; + return $this; + } + + public function getSetup(): float + { + return $this->setup; + } + + public function setSetup(float $setup): PhoneNumberBillingFees + { + $this->setup = $setup; + return $this; + } + + public function getSmsInbound(): float + { + return $this->smsInbound; + } + + public function setSmsInbound(float $smsInbound): PhoneNumberBillingFees + { + $this->smsInbound = $smsInbound; + return $this; + } + + public function getVoiceInbound(): float + { + return $this->voiceInbound; + } + + public function setVoiceInbound(float $voiceInbound): PhoneNumberBillingFees + { + $this->voiceInbound = $voiceInbound; + return $this; + } +} diff --git a/src/Response/Numbers/PhoneNumberFeatures.php b/src/Response/Numbers/PhoneNumberFeatures.php new file mode 100644 index 0000000..43c0263 --- /dev/null +++ b/src/Response/Numbers/PhoneNumberFeatures.php @@ -0,0 +1,50 @@ +applicationToPersonSms = $data->a2p_sms; + $this->sms = $data->sms; + $this->voice = $data->voice; + } + + public function isApplicationToPersonSms(): bool + { + return $this->applicationToPersonSms; + } + + public function setApplicationToPersonSms(bool $applicationToPersonSms): PhoneNumberFeatures + { + $this->applicationToPersonSms = $applicationToPersonSms; + return $this; + } + + public function isSms(): bool + { + return $this->sms; + } + + public function setSms(bool $sms): PhoneNumberFeatures + { + $this->sms = $sms; + return $this; + } + + public function isVoice(): bool + { + return $this->voice; + } + + public function setVoice(bool $voice): PhoneNumberFeatures + { + $this->voice = $voice; + return $this; + } +} diff --git a/src/Response/Numbers/PhoneNumberForwardInboundSms.php b/src/Response/Numbers/PhoneNumberForwardInboundSms.php new file mode 100644 index 0000000..b84a401 --- /dev/null +++ b/src/Response/Numbers/PhoneNumberForwardInboundSms.php @@ -0,0 +1,37 @@ +email = $data->email; + $this->sms = $data->sms; + } + + public function getEmail(): PhoneNumberForwardInboundSmsToMail + { + return $this->email; + } + + public function setEmail(PhoneNumberForwardInboundSmsToMail $email): PhoneNumberForwardInboundSms + { + $this->email = $email; + return $this; + } + + public function getSms(): PhoneNumberForwardInboundSmsToSms + { + return $this->sms; + } + + public function setSms(PhoneNumberForwardInboundSmsToSms $sms): PhoneNumberForwardInboundSms + { + $this->sms = $sms; + return $this; + } +} diff --git a/src/Response/Numbers/PhoneNumberForwardInboundSmsToMail.php b/src/Response/Numbers/PhoneNumberForwardInboundSmsToMail.php new file mode 100644 index 0000000..327087c --- /dev/null +++ b/src/Response/Numbers/PhoneNumberForwardInboundSmsToMail.php @@ -0,0 +1,38 @@ +addresses = $data->address; + $this->enabled = $data->enabled; + } + + public function getAddresses(): array + { + return $this->addresses; + } + + public function setAddresses(array $addresses): PhoneNumberForwardInboundSmsToMail + { + $this->addresses = $addresses; + return $this; + } + + public function isEnabled(): bool + { + return $this->enabled; + } + + public function setEnabled(bool $enabled): PhoneNumberForwardInboundSmsToMail + { + $this->enabled = $enabled; + return $this; + } +} diff --git a/src/Response/Numbers/PhoneNumberForwardInboundSmsToSms.php b/src/Response/Numbers/PhoneNumberForwardInboundSmsToSms.php new file mode 100644 index 0000000..c1617ca --- /dev/null +++ b/src/Response/Numbers/PhoneNumberForwardInboundSmsToSms.php @@ -0,0 +1,38 @@ +enabled = $data->enabled; + $this->numbers = $data->number; + } + + public function isEnabled(): bool + { + return $this->enabled; + } + + public function setEnabled(bool $enabled): PhoneNumberForwardInboundSmsToSms + { + $this->enabled = $enabled; + return $this; + } + + public function getNumbers(): array + { + return $this->numbers; + } + + public function setNumbers(array $numbers): PhoneNumberForwardInboundSmsToSms + { + $this->numbers = $numbers; + return $this; + } +} diff --git a/src/Response/Numbers/PhoneNumberOffer.php b/src/Response/Numbers/PhoneNumberOffer.php new file mode 100644 index 0000000..3595b5d --- /dev/null +++ b/src/Response/Numbers/PhoneNumberOffer.php @@ -0,0 +1,46 @@ +country = $data->country; + $this->features = new PhoneNumberFeatures($data->features); + $this->fees = new PhoneNumberOfferFees($data->fees); + $this->number = $data->number; + $this->numberParsed = $data->number_parsed; + } + + public function getCountry(): string + { + return $this->country; + } + + public function getFeatures(): PhoneNumberFeatures + { + return $this->features; + } + + public function getFees(): PhoneNumberOfferFees + { + return $this->fees; + } + + public function getNumber(): string + { + return $this->number; + } + + public function getNumberParsed(): string + { + return $this->numberParsed; + } +} diff --git a/src/Response/Numbers/PhoneNumberOfferFees.php b/src/Response/Numbers/PhoneNumberOfferFees.php new file mode 100644 index 0000000..80445a5 --- /dev/null +++ b/src/Response/Numbers/PhoneNumberOfferFees.php @@ -0,0 +1,39 @@ +annually = new PhoneNumberOfferFeesPeriod($data->annually); + $this->monthly = new PhoneNumberOfferFeesPeriod($data->monthly); + $this->inboundSms = $data->sms_mo; + $this->inboundVoice = $data->voice_mo; + } + + public function getAnnually(): PhoneNumberOfferFeesPeriod + { + return $this->annually; + } + + public function getInboundSms(): float + { + return $this->inboundSms; + } + + public function getInboundVoice(): float + { + return $this->inboundVoice; + } + + public function getMonthly(): PhoneNumberOfferFeesPeriod + { + return $this->monthly; + } +} diff --git a/src/Response/Numbers/PhoneNumberOfferFeesPeriod.php b/src/Response/Numbers/PhoneNumberOfferFeesPeriod.php new file mode 100644 index 0000000..28d9eca --- /dev/null +++ b/src/Response/Numbers/PhoneNumberOfferFeesPeriod.php @@ -0,0 +1,25 @@ +basicCharge = $data->basic_charge; + $this->setup = $data->setup; + } + + public function getBasicCharge(): float + { + return $this->basicCharge; + } + + public function getSetup(): float + { + return $this->setup; + } +} diff --git a/tests/Client/NumbersTest.php b/tests/Client/NumbersTest.php new file mode 100644 index 0000000..2d71ddc --- /dev/null +++ b/tests/Client/NumbersTest.php @@ -0,0 +1,49 @@ +setCountry('DE') + ->setFeaturesApplicationToPersonSms(true); + $offers = $this->client->numbers->listAvailable($availableParams)->getAvailableNumbers(); + $this->assertNotEmpty($offers); + + foreach ($offers as $offer) { + $this->assertEquals($availableParams->getCountry(), $offer->getCountry()); + $this->assertTrue($offer->getFeatures()->isApplicationToPersonSms()); + } + + $firstOffer = $offers[0]; + $orderParams = (new OrderParams($firstOffer->getNumber()))->setPaymentInterval(PaymentInterval::MONTHLY); + $order = $this->client->numbers->order($orderParams); + $this->assertNull($order->getError()); + $this->assertTrue($order->isSuccess()); + + $updateParams = (new UpdateParams($firstOffer->getNumber())) + ->setEmailForward(['php_test@seven.dev']) + ->setFriendlyName('Friendly Name') + ->setSmsForward(['491716992343']); + $updated = $this->client->numbers->update($updateParams); + $this->assertEquals($updateParams->getFriendlyName(), $updated->getFriendlyName()); + $this->assertEquals($updateParams->getEmailForward(), $updated->getForwardInboundSms()->getEmail()->getAddresses()); + $this->assertEquals($updateParams->getSmsForward(), $updated->getForwardInboundSms()->getSms()->getNumbers()); + + $number = $this->client->numbers->get($firstOffer->getNumber()); + $this->assertEquals($orderParams->getPaymentInterval(), $number->getBilling()->getPaymentInterval()); + + $actives = $this->client->numbers->listActive(); + $this->assertNotEmpty($actives); + + $deleted = $this->client->numbers->delete($firstOffer->getNumber()); + $this->assertTrue($deleted->isSuccess()); + } +} From ddbf892efc0746918d248739ed6cdc2205423423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 11:55:03 +0200 Subject: [PATCH 05/54] use endpoints for journal --- src/Constant/JournalConstants.php | 7 ++-- src/Constant/JournalType.php | 14 -------- src/Resource/JournalResource.php | 52 +++++++++++------------------- src/Validator/JournalValidator.php | 30 ++++++++++------- tests/Client/BaseTest.php | 29 +++++++++++------ tests/Client/JournalTest.php | 49 +++++++++++++++------------- 6 files changed, 85 insertions(+), 96 deletions(-) delete mode 100644 src/Constant/JournalType.php diff --git a/src/Constant/JournalConstants.php b/src/Constant/JournalConstants.php index cf7bda9..3179415 100644 --- a/src/Constant/JournalConstants.php +++ b/src/Constant/JournalConstants.php @@ -2,11 +2,8 @@ namespace Seven\Api\Constant; -class JournalConstants { - public const DATE_PATTERN = "/[\d]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][\d]|3[0-1])/"; - - public const ENDPOINT = 'journal'; - +class JournalConstants +{ public const LIMIT_MIN = 1; public const LIMIT_MAX = 100; } diff --git a/src/Constant/JournalType.php b/src/Constant/JournalType.php deleted file mode 100644 index 5ed7785..0000000 --- a/src/Constant/JournalType.php +++ /dev/null @@ -1,14 +0,0 @@ -fetch(JournalType::INBOUND, $params); + public function inbound(JournalParams $params = new JournalParams): array + { + return $this->fetch('inbound', JournalInbound::class, $params); } /** * @return JournalBase[] * @throws InvalidOptionalArgumentException */ - protected function fetch(string $type, JournalParams $params = null): array { - if (!$params) $params = new JournalParams; - + protected function fetch(string $type, string $class, JournalParams $params): array + { $this->validate($params); - switch ($type) { - case JournalType::VOICE: - $class = JournalVoice::class; - break; - case JournalType::OUTBOUND: - $class = JournalOutbound::class; - break; - case JournalType::REPLIES: - $class = JournalReply::class; - break; - default: - $class = JournalInbound::class; - } - - $array = $this->client->get( - JournalConstants::ENDPOINT, - array_merge($params->toArray(), compact('type')) - ); + $array = $this->client->get('journal/' . $type, $params->toArray()); return array_map(static function ($value) use ($class) { return new $class($value); }, $array); @@ -58,7 +40,8 @@ protected function fetch(string $type, JournalParams $params = null): array { /** * @throws InvalidOptionalArgumentException */ - public function validate($params): void { + public function validate($params): void + { (new JournalValidator($params))->validate(); } @@ -66,23 +49,26 @@ public function validate($params): void { * @return JournalOutbound[] * @throws InvalidOptionalArgumentException */ - public function outbound(JournalParams $params = null): array { - return $this->fetch(JournalType::OUTBOUND, $params); + public function outbound(JournalParams $params = new JournalParams): array + { + return $this->fetch('outbound', JournalOutbound::class, $params); } /** * @return JournalReply[] * @throws InvalidOptionalArgumentException */ - public function replies(JournalParams $params = null): array { - return $this->fetch(JournalType::REPLIES, $params); + public function replies(JournalParams $params = new JournalParams): array + { + return $this->fetch('replies', JournalReply::class, $params); } /** * @return JournalVoice[] * @throws InvalidOptionalArgumentException */ - public function voice(JournalParams $params = null): array { - return $this->fetch(JournalType::VOICE, $params); + public function voice(JournalParams $params = new JournalParams): array + { + return $this->fetch('voice', JournalVoice::class, $params); } } diff --git a/src/Validator/JournalValidator.php b/src/Validator/JournalValidator.php index c4cb1e6..f1e350c 100755 --- a/src/Validator/JournalValidator.php +++ b/src/Validator/JournalValidator.php @@ -7,15 +7,15 @@ use Seven\Api\Exception\InvalidOptionalArgumentException; use Seven\Api\Params\JournalParams; -class JournalValidator { - protected JournalParams $params; - - public function __construct(JournalParams $params) { - $this->params = $params; +class JournalValidator +{ + public function __construct(protected JournalParams $params) + { } /** @throws InvalidOptionalArgumentException */ - public function validate(): void { + public function validate(): void + { $this->id(); $this->limit(); $this->dateFrom(); @@ -25,7 +25,8 @@ public function validate(): void { } /** @throws InvalidOptionalArgumentException */ - public function id(): void { + public function id(): void + { $id = $this->params->getId(); if ($id === null) return; @@ -36,7 +37,8 @@ public function id(): void { /** * @throws InvalidOptionalArgumentException */ - public function limit(): void { + public function limit(): void + { $limit = $this->params->getLimit(); if ($limit === null) return; @@ -50,7 +52,8 @@ public function limit(): void { } /** @throws InvalidOptionalArgumentException */ - public function dateFrom(): void { + public function dateFrom(): void + { $dateFrom = $this->params->getDateFrom(); if (!$dateFrom) return; @@ -59,7 +62,8 @@ public function dateFrom(): void { } /** @throws InvalidOptionalArgumentException */ - public function dateTo(): void { + public function dateTo(): void + { $dateTo = $this->params->getDateTo(); if (!$dateTo) return; @@ -68,7 +72,8 @@ public function dateTo(): void { } /** @throws InvalidOptionalArgumentException */ - public function to(): void { + public function to(): void + { $to = $this->params->getTo(); if (!$to) return; @@ -76,6 +81,7 @@ public function to(): void { throw new InvalidOptionalArgumentException('to is not a valid number.'); } - public function state(): void { + public function state(): void + { } } diff --git a/tests/Client/BaseTest.php b/tests/Client/BaseTest.php index 3102f3c..2d62948 100755 --- a/tests/Client/BaseTest.php +++ b/tests/Client/BaseTest.php @@ -7,49 +7,58 @@ use PHPUnit\Framework\TestCase; use Seven\Api\Client; -abstract class BaseTest extends TestCase { +abstract class BaseTest extends TestCase +{ protected Client $client; protected bool $isSandbox; - public function __construct() { + public function __construct() + { parent::__construct(); $this->init(getenv('SEVEN_API_KEY'), false); } - protected function init(string $apiKey, bool $isSandbox): void { + protected function init(string $apiKey, bool $isSandbox): void + { $this->client = new Client($apiKey, 'php-api-test'); $this->isSandbox = $isSandbox; } - public static function createRandomURL(string $uri = 'https://my.tld/'): string { + public static function createRandomURL(string $uri = 'https://my.tld/'): string + { return $uri . uniqid('', true); } - public static function assertIsValidDateTime(string $dateTime): void { + public static function assertIsValidDateTime(string $dateTime): void + { $bool = null; try { $bool = new DateTime($dateTime); - } catch (Exception $e) { + } catch (Exception) { } self::assertInstanceOf(DateTime::class, $bool); } - public function toSandbox(): void { + public function toSandbox(): void + { $this->init(getenv('SEVEN_API_KEY_SANDBOX'), true); } - public function assertIsNullOrString($value): void { + public function assertIsNullOrString($value): void + { $this->assertTrue(is_string($value) || is_null($value)); } - public function assertIsNullOrLengthyString(?string $value): void { + public function assertIsNullOrLengthyString(?string $value): void + { $this->assertTrue(is_null($value) || 0 < strlen($value)); } - public function assertIsLengthyString(string $value): void { + public function assertIsLengthyString(string $value): void + { $this->assertIsString($value); $this->assertTrue($value !== ''); } diff --git a/tests/Client/JournalTest.php b/tests/Client/JournalTest.php index f3c5d05..1dbcaed 100755 --- a/tests/Client/JournalTest.php +++ b/tests/Client/JournalTest.php @@ -6,30 +6,27 @@ use DateTime; use Seven\Api\Constant\SmsConstants; use Seven\Api\Params\JournalParams; -use Seven\Api\Response\Journal\JournalInbound; +use Seven\Api\Response\Journal\JournalBase; use Seven\Api\Response\Journal\JournalOutbound; -use Seven\Api\Response\Journal\JournalReply; use Seven\Api\Response\Journal\JournalVoice; -class JournalTest extends BaseTest { - public function testJournalInbound(): void { +class JournalTest extends BaseTest +{ + public function testJournalInbound(): void + { $arr = $this->client->journal->inbound(); - $this->request($arr, JournalInbound::class); + $this->request($arr); } - private function request( - array $journals, - string $class, - ?callable $functionHandler = null - ): void { + private function request(array $journals, ?callable $functionHandler = null): void + { $this->assertIsArray($journals); + /** @var JournalBase $j */ foreach ($journals as $j) { - $this->assertInstanceOf($class, $j); $this->assertIsString($j->getFrom()); $this->assertIsNumeric($j->getId()); - $this->assertTrue(property_exists($j, 'price')); - $this->assertIsLengthyString($j->getText()); + $this->assertGreaterThanOrEqual(0.0, $j->getPrice()); $this->assertIsValidDateTime($j->getTimestamp()); $this->assertIsLengthyString($j->getTo()); @@ -37,7 +34,8 @@ private function request( } } - public function testJournalOutbound(): void { + public function testJournalOutbound(): void + { $arr = $this->client->journal->outbound(); $callable = function (JournalOutbound $j) { $this->assertIsString($j->getConnection()); @@ -50,10 +48,11 @@ public function testJournalOutbound(): void { $this->assertEquals(SmsConstants::TYPE_DIRECT, $j->getType()); }; - $this->request($arr, JournalOutbound::class, $callable); + $this->request($arr, $callable); } - public function testJournalVoice(): void { + public function testJournalVoice(): void + { $arr = $this->client->journal->voice(); $callable = function (JournalVoice $j) { $this->assertIsNullOrLengthyString($j->getDuration()); @@ -62,26 +61,32 @@ public function testJournalVoice(): void { $this->assertIsBool($j->isXml()); }; - $this->request($arr, JournalVoice::class, $callable); + $this->request($arr, $callable); } - public function testJournalReplies(): void { + public function testJournalReplies(): void + { $arr = $this->client->journal->replies(); - - $this->request($arr, JournalReply::class); + $this->request($arr); } - public function testJournalParams(): void { + public function testJournalParams(): void + { $params = (new JournalParams) - ->setId(null) ->setDateFrom((new DateTime)->sub(DateInterval::createFromDateString('30 day'))) ->setDateTo(new DateTime) + ->setId(null) ->setLimit(null) ->setState('') ->setTo('') ->toArray(); $this->assertArrayHasKey('date_from', $params); + $this->assertArrayNotHasKey('dateFrom', $params); + $this->assertIsString($params['date_from']); + $this->assertArrayHasKey('date_to', $params); + $this->assertArrayNotHasKey('dateTo', $params); + $this->assertIsString($params['date_to']); } } From bf781f903cb06ed9cd99b286cbb1e1bcbc7878c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 11:57:20 +0200 Subject: [PATCH 06/54] add missing Hook properties --- src/Response/Hooks/Hook.php | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/Response/Hooks/Hook.php b/src/Response/Hooks/Hook.php index d29919f..1dcb865 100644 --- a/src/Response/Hooks/Hook.php +++ b/src/Response/Hooks/Hook.php @@ -2,38 +2,59 @@ namespace Seven\Api\Response\Hooks; -class Hook { +class Hook +{ protected string $created; + protected bool $enabled; + protected ?string $eventFilter; protected string $eventType; protected int $id; protected string $requestMethod; protected string $targetUrl; - public function __construct(object $data) { + public function __construct(object $data) + { $this->created = $data->created; + $this->enabled = $data->enabled; + $this->eventFilter = $data->event_filter; $this->eventType = $data->event_type; $this->id = (int)$data->id; $this->requestMethod = $data->request_method; $this->targetUrl = $data->target_url; } - public function getCreated(): string { + public function getCreated(): string + { return $this->created; } - public function getEventType(): string { + public function getEventType(): string + { return $this->eventType; } - public function getId(): int { + public function getId(): int + { return $this->id; } - public function getRequestMethod(): string { + public function getRequestMethod(): string + { return $this->requestMethod; } - public function getTargetUrl(): string { + public function getTargetUrl(): string + { return $this->targetUrl; } + + public function getEventFilter(): ?string + { + return $this->eventFilter; + } + + public function isEnabled(): bool + { + return $this->enabled; + } } From ab967fcece07d6e45238427abe3a76bcc084943b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 12:11:03 +0200 Subject: [PATCH 07/54] add Hooks.SubscribeParams --- src/Constant/HooksEventType.php | 20 ++++++++--------- src/Constant/HooksRequestMethod.php | 14 +++++------- src/Params/Hooks/SubscribeParams.php | 31 +++++++++++++++++++++++++++ src/Resource/HooksResource.php | 32 +++++++++++----------------- tests/Client/BaseTest.php | 2 +- tests/Client/HooksTest.php | 23 +++++++++++--------- 6 files changed, 71 insertions(+), 51 deletions(-) create mode 100644 src/Params/Hooks/SubscribeParams.php diff --git a/src/Constant/HooksEventType.php b/src/Constant/HooksEventType.php index c5c39f0..b25f01f 100644 --- a/src/Constant/HooksEventType.php +++ b/src/Constant/HooksEventType.php @@ -2,15 +2,13 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -class HooksEventType { - use Reflectable; - - public const ALL = 'all'; - public const SMS_INBOUND = 'sms_mo'; - public const SMS_STATUS = 'dlr'; - public const TRACKING = 'tracking'; - public const VOICE_CALL = 'voice_call'; - public const VOICE_STATUS = 'voice_status'; +enum HooksEventType: string +{ + case ALL = 'all'; + case RCS = 'rcs'; + case SMS_INBOUND = 'sms_mo'; + case SMS_STATUS = 'dlr'; + case TRACKING = 'tracking'; + case VOICE_CALL = 'voice_call'; + case VOICE_STATUS = 'voice_status'; } diff --git a/src/Constant/HooksRequestMethod.php b/src/Constant/HooksRequestMethod.php index 9d6c79f..ec16bf6 100644 --- a/src/Constant/HooksRequestMethod.php +++ b/src/Constant/HooksRequestMethod.php @@ -2,13 +2,9 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -class HooksRequestMethod { - use Reflectable; - - public const GET = 'GET'; - public const JSON = 'JSON'; - public const POST = 'POST'; - public const DEFAULT = self::POST; +enum HooksRequestMethod +{ + case GET; + case JSON; + case POST; } diff --git a/src/Params/Hooks/SubscribeParams.php b/src/Params/Hooks/SubscribeParams.php new file mode 100644 index 0000000..b71e0ae --- /dev/null +++ b/src/Params/Hooks/SubscribeParams.php @@ -0,0 +1,31 @@ +eventFilter; + $arr['event_type'] = $this->eventType; + $arr['request_method'] = $this->requestMethod; + $arr['target_url'] = $this->targetUrl; + + unset($arr['eventFilter'], $arr['eventType'], $arr['requestMethod'], $arr['targetUrl']); + + return $arr; + } +} diff --git a/src/Resource/HooksResource.php b/src/Resource/HooksResource.php index 31c536d..4ed8cca 100644 --- a/src/Resource/HooksResource.php +++ b/src/Resource/HooksResource.php @@ -3,19 +3,21 @@ namespace Seven\Api\Resource; use Seven\Api\Constant\HooksAction; -use Seven\Api\Constant\HooksRequestMethod; use Seven\Api\Exception\InvalidRequiredArgumentException; +use Seven\Api\Params\Hooks\SubscribeParams; use Seven\Api\Params\HooksParams; use Seven\Api\Response\Hooks\Hooks; use Seven\Api\Response\Hooks\HookSubscribe; use Seven\Api\Response\Hooks\HookUnsubscribe; use Seven\Api\Validator\HooksValidator; -class HooksResource extends Resource { +class HooksResource extends Resource +{ /** * @throws InvalidRequiredArgumentException */ - public function unsubscribe(int $id): HookUnsubscribe { + public function unsubscribe(int $id): HookUnsubscribe + { $params = (new HooksParams(HooksAction::UNSUBSCRIBE))->setId($id); $this->validate($params); $obj = $this->client->post('hooks', $params->toArray());; @@ -26,29 +28,19 @@ public function unsubscribe(int $id): HookUnsubscribe { * @param HooksParams $params * @throws InvalidRequiredArgumentException */ - public function validate($params): void { + public function validate($params): void + { (new HooksValidator($params))->validate(); } - /** - * @throws InvalidRequiredArgumentException - */ - public function subscribe( - string $targetUrl, - string $eventType, - string $requestMethod = HooksRequestMethod::DEFAULT - ): HookSubscribe { - $params = (new HooksParams(HooksAction::SUBSCRIBE)) - ->setEventType($eventType) - ->setRequestMethod($requestMethod) - ->setTargetUrl($targetUrl); - $this->validate($params); - $obj = $this->client->post('hooks', $params->toArray()); - return new HookSubscribe($obj); + public function subscribe(SubscribeParams $params): HookSubscribe + { + return new HookSubscribe($this->client->post('hooks', $params->toArray())); } /** @throws InvalidRequiredArgumentException */ - public function read(): Hooks { + public function read(): Hooks + { $params = new HooksParams(HooksAction::READ); $this->validate($params); $obj = $this->client->get('hooks', $params->toArray()); diff --git a/tests/Client/BaseTest.php b/tests/Client/BaseTest.php index 2d62948..eeda366 100755 --- a/tests/Client/BaseTest.php +++ b/tests/Client/BaseTest.php @@ -25,7 +25,7 @@ protected function init(string $apiKey, bool $isSandbox): void $this->isSandbox = $isSandbox; } - public static function createRandomURL(string $uri = 'https://my.tld/'): string + public static function createRandomURL(string $uri = 'https://php.tld/'): string { return $uri . uniqid('', true); } diff --git a/tests/Client/HooksTest.php b/tests/Client/HooksTest.php index c082d8c..9fd95bd 100755 --- a/tests/Client/HooksTest.php +++ b/tests/Client/HooksTest.php @@ -5,9 +5,12 @@ use Seven\Api\Constant\HooksEventType; use Seven\Api\Constant\HooksRequestMethod; use Seven\Api\Library\Util; +use Seven\Api\Params\Hooks\SubscribeParams; -class HooksTest extends BaseTest { - public function testGetHooks(): void { +class HooksTest extends BaseTest +{ + public function testGetHooks(): void + { $res = $this->client->hooks->read(); $this->assertIsBool($res->isSuccess()); @@ -23,17 +26,16 @@ public function testGetHooks(): void { $h = $res->getHooks()[0]; - $this->assertContains($h->getEventType(), HooksEventType::values()); + $this->assertContains($h->getEventType(), array_column(HooksEventType::cases(), 'value')); $this->assertGreaterThan(0, $h->getId()); - $this->assertContains($h->getRequestMethod(), HooksRequestMethod::values()); + $this->assertContains($h->getRequestMethod(), array_column(HooksRequestMethod::cases(), 'name')); $this->assertTrue(Util::isValidUrl($h->getTargetUrl())); } - public function testSubscribeHook(bool $delete = true): ?int { - $res = $this->client->hooks->subscribe( - self::createRandomURL('http://ho.ok/'), - HooksEventType::SMS_INBOUND - ); + public function testSubscribeHook(bool $delete = true): ?int + { + $params = new SubscribeParams(self::createRandomURL(), HooksEventType::SMS_INBOUND); + $res = $this->client->hooks->subscribe($params); $id = $res->getId(); $isSuccess = $res->isSuccess(); @@ -49,7 +51,8 @@ public function testSubscribeHook(bool $delete = true): ?int { return $id; } - public function testUnsubscribeHook(?int $id = null): void { + public function testUnsubscribeHook(?int $id = null): void + { if (!$id) { $res = $this->client->hooks->read(); From b722196d6900f2146cb1d1708b08825852830642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 12:23:45 +0200 Subject: [PATCH 08/54] clean up hooks related --- src/BaseClient.php | 6 +- src/Constant/HooksAction.php | 13 --- src/Params/Hooks/SubscribeParams.php | 36 +++++++- src/Params/HooksParams.php | 96 --------------------- src/Resource/HooksResource.php | 24 +----- src/Validator/HooksValidator.php | 124 --------------------------- 6 files changed, 41 insertions(+), 258 deletions(-) delete mode 100644 src/Constant/HooksAction.php delete mode 100644 src/Params/HooksParams.php delete mode 100644 src/Validator/HooksValidator.php diff --git a/src/BaseClient.php b/src/BaseClient.php index 87a386a..ebeb451 100644 --- a/src/BaseClient.php +++ b/src/BaseClient.php @@ -84,9 +84,11 @@ protected function request(string $path, HttpMethod $method, array $payload = [] curl_setopt($ch, CURLOPT_POST, true); } elseif (HttpMethod::PATCH === $method) { curl_setopt($ch, CURLOPT_POSTFIELDS, $params); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::PATCH->name); - } elseif (HttpMethod::DELETE === $method) curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::DELETE->name); + } elseif (HttpMethod::DELETE === $method) { + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::DELETE->name); + } curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); diff --git a/src/Constant/HooksAction.php b/src/Constant/HooksAction.php deleted file mode 100644 index 6443f4b..0000000 --- a/src/Constant/HooksAction.php +++ /dev/null @@ -1,13 +0,0 @@ -eventFilter; - $arr['event_type'] = $this->eventType; - $arr['request_method'] = $this->requestMethod; + $arr['event_type'] = $this->eventType->value; + $arr['request_method'] = $this->requestMethod->name; $arr['target_url'] = $this->targetUrl; unset($arr['eventFilter'], $arr['eventType'], $arr['requestMethod'], $arr['targetUrl']); return $arr; } + + public function getEventFilter(): ?string + { + return $this->eventFilter; + } + + public function setEventFilter(?string $eventFilter): self + { + $this->eventFilter = $eventFilter; + return $this; + } + + public function getTargetUrl(): string + { + return $this->targetUrl; + } + + public function getEventType(): HooksEventType + { + return $this->eventType; + } + + public function getRequestMethod(): HooksRequestMethod + { + return $this->requestMethod; + } + + public function setRequestMethod(HooksRequestMethod $requestMethod): self + { + $this->requestMethod = $requestMethod; + return $this; + } } diff --git a/src/Params/HooksParams.php b/src/Params/HooksParams.php deleted file mode 100644 index f1ca9df..0000000 --- a/src/Params/HooksParams.php +++ /dev/null @@ -1,96 +0,0 @@ -action = $action; - } - - public function getAction(): string { - return $this->action; - } - - public function setAction(string $action): self { - $this->action = $action; - return $this; - } - - public function getTargetUrl(): ?string { - return $this->targetUrl; - } - - public function setTargetUrl(?string $targetUrl): self { - $this->targetUrl = $targetUrl; - return $this; - } - - public function getEventType(): ?string { - return $this->eventType; - } - - public function setEventType(?string $eventType): self { - $this->eventType = $eventType; - return $this; - } - - public function getEventFilter(): ?string { - return $this->eventFilter; - } - - public function setEventFilter(?string $eventFilter): self { - $this->eventFilter = $eventFilter; - return $this; - } - - public function getRequestMethod(): ?string { - return $this->requestMethod; - } - - public function setRequestMethod(?string $requestMethod): self { - $this->requestMethod = $requestMethod; - return $this; - } - - public function getId(): ?int { - return $this->id; - } - - public function setId(?int $id): self { - $this->id = $id; - return $this; - } - - public function toArray(): array { - $arr = get_object_vars($this); - - if (isset($arr['eventFilter'])) { - $arr['event_filter'] = $arr['eventFilter']; - unset($arr['eventFilter']); - } - - if (isset($arr['eventType'])) { - $arr['event_type'] = $arr['eventType']; - unset($arr['eventType']); - } - - if (isset($arr['requestMethod'])) { - $arr['request_method'] = $arr['requestMethod']; - unset($arr['requestMethod']); - } - - if (isset($arr['targetUrl'])) { - $arr['target_url'] = $arr['targetUrl']; - unset($arr['targetUrl']); - } - - return $arr; - } -} diff --git a/src/Resource/HooksResource.php b/src/Resource/HooksResource.php index 4ed8cca..772848b 100644 --- a/src/Resource/HooksResource.php +++ b/src/Resource/HooksResource.php @@ -2,35 +2,21 @@ namespace Seven\Api\Resource; -use Seven\Api\Constant\HooksAction; -use Seven\Api\Exception\InvalidRequiredArgumentException; use Seven\Api\Params\Hooks\SubscribeParams; -use Seven\Api\Params\HooksParams; use Seven\Api\Response\Hooks\Hooks; use Seven\Api\Response\Hooks\HookSubscribe; use Seven\Api\Response\Hooks\HookUnsubscribe; -use Seven\Api\Validator\HooksValidator; class HooksResource extends Resource { - /** - * @throws InvalidRequiredArgumentException - */ public function unsubscribe(int $id): HookUnsubscribe { - $params = (new HooksParams(HooksAction::UNSUBSCRIBE))->setId($id); - $this->validate($params); - $obj = $this->client->post('hooks', $params->toArray());; - return new HookUnsubscribe($obj); + return new HookUnsubscribe($this->client->delete('hooks?id=' . $id)); } - /** - * @param HooksParams $params - * @throws InvalidRequiredArgumentException - */ public function validate($params): void { - (new HooksValidator($params))->validate(); + // TODO? } public function subscribe(SubscribeParams $params): HookSubscribe @@ -38,12 +24,8 @@ public function subscribe(SubscribeParams $params): HookSubscribe return new HookSubscribe($this->client->post('hooks', $params->toArray())); } - /** @throws InvalidRequiredArgumentException */ public function read(): Hooks { - $params = new HooksParams(HooksAction::READ); - $this->validate($params); - $obj = $this->client->get('hooks', $params->toArray()); - return new Hooks($obj); + return new Hooks($this->client->get('hooks')); } } diff --git a/src/Validator/HooksValidator.php b/src/Validator/HooksValidator.php deleted file mode 100644 index a3e225f..0000000 --- a/src/Validator/HooksValidator.php +++ /dev/null @@ -1,124 +0,0 @@ -params = $params; - } - - /** @throws InvalidRequiredArgumentException */ - public function validate(): void { - $this->action(); - - switch ($this->params->getAction()) { - case HooksAction::READ: - $this->read(); - break; - case HooksAction::SUBSCRIBE: - $this->subscribe(); - break; - case HooksAction::UNSUBSCRIBE: - $this->unsubscribe(); - break; - } - } - - /** @throws InvalidRequiredArgumentException */ - public function action(): void { - $action = $this->params->getAction(); - - if (!in_array($action, HooksAction::values())) - throw new InvalidRequiredArgumentException('Unknown action: ' . $action); - } - - protected function read(): void { - } - - /** - * @throws InvalidRequiredArgumentException - */ - protected function subscribe(): void { - $this->eventFilter(); - $this->eventType(); - $this->requestMethod(); - $this->targetUrl(); - } - - public function eventFilter(): void { - - } - - /** @throws InvalidRequiredArgumentException */ - public function eventType(): void { - if (!$this->expectsExtendedParameters()) return; - - $eventType = $this->params->getEventType(); - $values = HooksEventType::values(); - - if (!in_array($eventType, $values)) { - throw new InvalidRequiredArgumentException( - "Invalid event type '$eventType'! Allowed values are " - . implode(',', $values) . '.'); - } - } - - private function expectsExtendedParameters(): bool { - $action = $this->params->getAction(); - - if (HooksAction::READ === $action) return false; - if (HooksAction::UNSUBSCRIBE === $action) return false; - - return true; - } - - /** @throws InvalidRequiredArgumentException */ - public function requestMethod(): void { - if (!$this->expectsExtendedParameters()) return; - - $requestMethod = $this->params->getRequestMethod(); - $values = HooksRequestMethod::values(); - - if (!in_array($requestMethod, $values)) { - throw new InvalidRequiredArgumentException( - "Invalid request method '$requestMethod'! Allowed values are " - . implode(',', $values) . '.'); - } - } - - /** @throws InvalidRequiredArgumentException */ - public function targetUrl(): void { - if (!$this->expectsExtendedParameters()) return; - - $targetUrl = $this->params->getTargetUrl(); - - if (!Util::isValidUrl($targetUrl)) - throw new InvalidRequiredArgumentException('Invalid target_url: ' . $targetUrl); - } - - /** - * @throws InvalidRequiredArgumentException - */ - protected function unsubscribe(): void { - $this->id(); - } - - /** @throws InvalidRequiredArgumentException */ - public function id(): void { - if (HooksAction::UNSUBSCRIBE !== $this->params->getAction()) return; - - $id = $this->params->getId(); - - if (!is_numeric($id)) - throw new InvalidRequiredArgumentException('Invalid ID: ' . $id); - } -} From 82b4d2201c5a54b31592720a29f085d000c389d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 12:37:50 +0200 Subject: [PATCH 09/54] clean up lookups --- src/Constant/LookupType.php | 14 ------ src/Params/LookupParams.php | 50 ------------------- src/Resource/LookupResource.php | 79 ++++++++++--------------------- src/Validator/LookupValidator.php | 58 ----------------------- tests/Client/LookupTest.php | 29 +++++++++--- 5 files changed, 47 insertions(+), 183 deletions(-) delete mode 100644 src/Constant/LookupType.php delete mode 100644 src/Params/LookupParams.php delete mode 100755 src/Validator/LookupValidator.php diff --git a/src/Constant/LookupType.php b/src/Constant/LookupType.php deleted file mode 100644 index ed1a9cd..0000000 --- a/src/Constant/LookupType.php +++ /dev/null @@ -1,14 +0,0 @@ -type = $type; - $this->numbers = $numbers; - } - - public function getNumbers(): array { - return $this->numbers; - } - - public function setNumbers(array $numbers): self { - $this->numbers = $numbers; - return $this; - } - - public function getType(): string { - return $this->type; - } - - public function setType(string $type): self { - $this->type = $type; - return $this; - } - - public function toArray(): array { - $arr = get_object_vars($this); - - $arr['number'] = implode(',', $arr['numbers']); - unset($arr['numbers']); - - return $arr; - } - - public function getJson(): ?bool { - return $this->json; - } - - public function setJson(?bool $json): self { - $this->json = $json; - return $this; - } -} diff --git a/src/Resource/LookupResource.php b/src/Resource/LookupResource.php index c94d02a..4808fab 100644 --- a/src/Resource/LookupResource.php +++ b/src/Resource/LookupResource.php @@ -2,85 +2,56 @@ namespace Seven\Api\Resource; -use Seven\Api\Exception\InvalidOptionalArgumentException; -use Seven\Api\Exception\InvalidRequiredArgumentException; -use Seven\Api\Params\LookupParams; use Seven\Api\Response\Lookup\LookupCnam; use Seven\Api\Response\Lookup\LookupFormat; use Seven\Api\Response\Lookup\LookupHlr; use Seven\Api\Response\Lookup\LookupMnp; -use Seven\Api\Validator\LookupValidator; -class LookupResource extends Resource { +class LookupResource extends Resource +{ /** - * @throws InvalidOptionalArgumentException - * @throws InvalidRequiredArgumentException + * @return LookupFormat[] */ - public function format(string ...$numbers): LookupFormat { - $params = new LookupParams('format', ...$numbers); - $res = $this->fetch($params); - return new LookupFormat($res); + public function format(string ...$numbers): array + { + $res = $this->fetch('format', ...$numbers); + return array_map(static fn($obj) => new LookupFormat($obj), is_array($res) ? $res : [$res]); } - /** - * @return mixed - * @throws InvalidOptionalArgumentException - * @throws InvalidRequiredArgumentException - */ - protected function fetch(LookupParams $params) { - $this->validate($params); - - return $this->client->post('lookup', $params->toArray()); + protected function fetch(string $type, string ...$numbers): object|array + { + return $this->client->get('lookup/' . $type, ['number' => implode(',', $numbers)]); } - /** - * @param LookupParams $params - * @throws InvalidOptionalArgumentException - * @throws InvalidRequiredArgumentException - */ - public function validate($params): void { - (new LookupValidator($params))->validate(); + public function validate($params): void + { + // TODO? } /** * @return LookupCnam[] - * @throws InvalidOptionalArgumentException - * @throws InvalidRequiredArgumentException */ - public function cnam(string ...$numbers): array { - $params = new LookupParams('cnam', ...$numbers); - $res = $this->fetch($params); - - return array_map(static function ($obj) { - return new LookupCnam($obj); - }, is_array($res) ? $res : [$res]); + public function cnam(string ...$numbers): array + { + $res = $this->fetch('cnam', ...$numbers); + return array_map(static fn($obj) => new LookupCnam($obj), is_array($res) ? $res : [$res]); } /** * @return LookupHlr[] - * @throws InvalidOptionalArgumentException - * @throws InvalidRequiredArgumentException */ - public function hlr(string ...$numbers): array { - $params = new LookupParams('hlr', ...$numbers); - $res = $this->fetch($params); - - return array_map(static function ($obj) { - return new LookupHlr($obj); - }, is_array($res) ? $res : [$res]); + public function hlr(string ...$numbers): array + { + $res = $this->fetch('hlr', ...$numbers); + return array_map(static fn($obj) => new LookupHlr($obj), is_array($res) ? $res : [$res]); } /** * @return LookupMnp[] - * @throws InvalidOptionalArgumentException - * @throws InvalidRequiredArgumentException */ - public function mnp(string ...$numbers): array { - $params = (new LookupParams('mnp', ...$numbers))->setJson(true); - $res = $this->fetch($params); - - return array_map(static function ($obj) { - return new LookupMnp($obj); - }, is_array($res) ? $res : [$res]); + public function mnp(string ...$numbers): array + { + $res = $this->fetch('mnp', ...$numbers); + return array_map(static fn($obj) => new LookupMnp($obj), is_array($res) ? $res : [$res]); } } diff --git a/src/Validator/LookupValidator.php b/src/Validator/LookupValidator.php deleted file mode 100755 index e3d4fdc..0000000 --- a/src/Validator/LookupValidator.php +++ /dev/null @@ -1,58 +0,0 @@ -params = $params; - } - - /** - * @throws InvalidOptionalArgumentException - * @throws InvalidRequiredArgumentException - */ - public function validate(): void { - $this->json(); - $this->number(); - $this->type(); - } - - /** @throws InvalidOptionalArgumentException */ - public function json(): void { - if (null === $this->params->getJson()) return; - - $type = $this->params->getType(); - - if (LookupType::MobileNumberPortability !== $type) { - throw new InvalidOptionalArgumentException( - 'json may only be set if type is set to mnp.'); - } - } - - /** @throws InvalidRequiredArgumentException */ - public function number(): void { - $numbers = $this->params->getNumbers(); - - if (empty($numbers)) throw new InvalidRequiredArgumentException('number(s) are missing.'); - } - - /** @throws InvalidRequiredArgumentException */ - public function type(): void { - $type = $this->params->getType(); - $values = LookupType::values(); - - if (!in_array($type, $values, true)) { - $imploded = implode(',', $values); - - throw new InvalidRequiredArgumentException( - "type $type is invalid. Valid types are: $imploded."); - } - } -} diff --git a/tests/Client/LookupTest.php b/tests/Client/LookupTest.php index 40aaa72..15deb3a 100755 --- a/tests/Client/LookupTest.php +++ b/tests/Client/LookupTest.php @@ -5,14 +5,24 @@ use Seven\Api\Response\Lookup\Carrier; -class LookupTest extends BaseTest { - public function testFormat(): void { +class LookupTest extends BaseTest +{ + public function testFormat(): void + { $res = $this->client->lookup->format('491716992343'); - $this->assertTrue($res->isSuccess()); + $this->assertCount(1, $res); } - public function testMnpMulti(): void { + public function testFormatMulti(): void + { + $res = $this->client->lookup->format('491716992343', '49179999999'); + $this->assertCount(2, $res); + } + + public function testMnpMulti(): void + { $arr = $this->client->lookup->mnp('491716992343'); + $this->assertCount(1, $arr); foreach ($arr as $item) { $this->assertIsInt($item->getCode()); @@ -29,8 +39,10 @@ public function testMnpMulti(): void { } } - public function testHlr(): void { + public function testHlr(): void + { $arr = $this->client->lookup->hlr('491716992343'); + $this->assertCount(1, $arr); foreach ($arr as $item) { $this->assertNotEmpty($item->getCountryCode()); @@ -54,15 +66,18 @@ public function testHlr(): void { } } - private function assertCarrier(Carrier $c): void { + private function assertCarrier(Carrier $c): void + { $this->assertNotEmpty($c->getCountry()); $this->assertNotEmpty($c->getName()); $this->assertNotEmpty($c->getNetworkCode()); $this->assertNotEmpty($c->getNetworkType()); } - public function testCnam(): void { + public function testCnam(): void + { $arr = $this->client->lookup->cnam('491716992343'); + $this->assertCount(1, $arr); foreach ($arr as $item) { $this->assertNotEmpty($item->getCode()); From acfc164564f0cb3a40f1203fa77a9d5d8053049d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 12:41:51 +0200 Subject: [PATCH 10/54] add rcs lookup --- src/Resource/LookupResource.php | 10 ++++++++++ src/Response/Lookup/LookupMnp.php | 20 ++++++++++++------- src/Response/Lookup/LookupRcsCapabilities.php | 16 +++++++++++++++ tests/Client/LookupTest.php | 6 ++++++ 4 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 src/Response/Lookup/LookupRcsCapabilities.php diff --git a/src/Resource/LookupResource.php b/src/Resource/LookupResource.php index 4808fab..4d5fda4 100644 --- a/src/Resource/LookupResource.php +++ b/src/Resource/LookupResource.php @@ -6,6 +6,7 @@ use Seven\Api\Response\Lookup\LookupFormat; use Seven\Api\Response\Lookup\LookupHlr; use Seven\Api\Response\Lookup\LookupMnp; +use Seven\Api\Response\Lookup\LookupRcsCapabilities; class LookupResource extends Resource { @@ -54,4 +55,13 @@ public function mnp(string ...$numbers): array $res = $this->fetch('mnp', ...$numbers); return array_map(static fn($obj) => new LookupMnp($obj), is_array($res) ? $res : [$res]); } + + /** + * @return LookupRcsCapabilities[] + */ + public function rcsCapabilities(string ...$numbers): array + { + $res = $this->fetch('rcs', ...$numbers); + return array_map(static fn($obj) => new LookupRcsCapabilities($obj), is_array($res) ? $res : [$res]); + } } diff --git a/src/Response/Lookup/LookupMnp.php b/src/Response/Lookup/LookupMnp.php index 92ce22d..d5cb334 100644 --- a/src/Response/Lookup/LookupMnp.php +++ b/src/Response/Lookup/LookupMnp.php @@ -2,35 +2,41 @@ namespace Seven\Api\Response\Lookup; -class LookupMnp { +class LookupMnp +{ protected int $code; protected Mnp $mnp; /** * @var int|float $price */ - protected $price; + protected int|float $price; protected bool $success; - public function __construct(object $data) { + public function __construct(object $data) + { $this->code = $data->code; $this->mnp = new Mnp($data->mnp); $this->price = $data->price; $this->success = $data->success; } - public function getCode(): int { + public function getCode(): int + { return $this->code; } - public function getMnp(): Mnp { + public function getMnp(): Mnp + { return $this->mnp; } - public function getPrice() { + public function getPrice() + { return $this->price; } - public function isSuccess(): bool { + public function isSuccess(): bool + { return $this->success; } } diff --git a/src/Response/Lookup/LookupRcsCapabilities.php b/src/Response/Lookup/LookupRcsCapabilities.php new file mode 100644 index 0000000..3f061f2 --- /dev/null +++ b/src/Response/Lookup/LookupRcsCapabilities.php @@ -0,0 +1,16 @@ +rcsCapabilities = $data->rcs_capabilities; + } +} diff --git a/tests/Client/LookupTest.php b/tests/Client/LookupTest.php index 15deb3a..a742e2d 100755 --- a/tests/Client/LookupTest.php +++ b/tests/Client/LookupTest.php @@ -7,6 +7,12 @@ class LookupTest extends BaseTest { + public function testRcsCapabilities(): void + { + $res = $this->client->lookup->rcsCapabilities('491716992343'); + $this->assertCount(1, $res); + } + public function testFormat(): void { $res = $this->client->lookup->format('491716992343'); From 4be4dd187c14b43f3db028c0aa62cbabe28d67a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 12:44:47 +0200 Subject: [PATCH 11/54] remove voiceparams.xml --- src/Params/VoiceParams.php | 49 ++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/Params/VoiceParams.php b/src/Params/VoiceParams.php index 559cc11..5452f77 100644 --- a/src/Params/VoiceParams.php +++ b/src/Params/VoiceParams.php @@ -2,73 +2,76 @@ namespace Seven\Api\Params; -class VoiceParams implements ParamsInterface { +class VoiceParams implements ParamsInterface +{ protected ?string $from = null; protected ?string $language = null; protected ?int $ringtime = null; protected string $text; protected string $to; - protected ?bool $xml = null; - public function __construct(string $text, string $to) { + public function __construct(string $text, string $to) + { $this->text = $text; $this->to = $to; } - public function toArray(): array { + public function toArray(): array + { return get_object_vars($this); } - public function getFrom(): ?string { + public function getFrom(): ?string + { return $this->from; } - public function setFrom(?string $from): self { + public function setFrom(?string $from): self + { $this->from = $from; return $this; } - public function getRingtime(): ?int { + public function getRingtime(): ?int + { return $this->ringtime; } - public function setRingtime(?int $ringtime): self { + public function setRingtime(?int $ringtime): self + { $this->ringtime = $ringtime; return $this; } - public function getText(): string { + public function getText(): string + { return $this->text; } - public function setText(string $text): self { + public function setText(string $text): self + { $this->text = $text; return $this; } - public function getTo(): string { + public function getTo(): string + { return $this->to; } - public function setTo(string $to): self { + public function setTo(string $to): self + { $this->to = $to; return $this; } - public function getXml(): ?bool { - return $this->xml; - } - - public function setXml(?bool $xml): self { - $this->xml = $xml; - return $this; - } - - public function getLanguage(): ?string { + public function getLanguage(): ?string + { return $this->language; } - public function setLanguage(?string $language): self { + public function setLanguage(?string $language): self + { $this->language = $language; return $this; } From dd699f24f52e73d75f4702d743145870495ce0b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 12:46:08 +0200 Subject: [PATCH 12/54] remove voiceparams.language --- src/Params/VoiceParams.php | 18 +-- src/Validator/VoiceValidator.php | 229 ++----------------------------- 2 files changed, 15 insertions(+), 232 deletions(-) diff --git a/src/Params/VoiceParams.php b/src/Params/VoiceParams.php index 5452f77..8d6a851 100644 --- a/src/Params/VoiceParams.php +++ b/src/Params/VoiceParams.php @@ -5,15 +5,10 @@ class VoiceParams implements ParamsInterface { protected ?string $from = null; - protected ?string $language = null; protected ?int $ringtime = null; - protected string $text; - protected string $to; - public function __construct(string $text, string $to) + public function __construct(protected string $text, protected string $to) { - $this->text = $text; - $this->to = $to; } public function toArray(): array @@ -64,15 +59,4 @@ public function setTo(string $to): self $this->to = $to; return $this; } - - public function getLanguage(): ?string - { - return $this->language; - } - - public function setLanguage(?string $language): self - { - $this->language = $language; - return $this; - } } diff --git a/src/Validator/VoiceValidator.php b/src/Validator/VoiceValidator.php index 11ea9be..1b8ab33 100755 --- a/src/Validator/VoiceValidator.php +++ b/src/Validator/VoiceValidator.php @@ -6,215 +6,22 @@ use Seven\Api\Exception\InvalidRequiredArgumentException; use Seven\Api\Params\VoiceParams; -class VoiceValidator { - public static array $LANGUAGES = [ - 'af-ZA', - 'am-ET', - 'ar-AE', - 'ar-BH', - 'ar-DZ', - 'ar-EG', - 'ar-IQ', - 'ar-JO', - 'ar-KW', - 'ar-LB', - 'ar-LY', - 'ar-MA', - 'ar-OM', - 'ar-QA', - 'ar-SA', - 'ar-SY', - 'ar-TN', - 'ar-YE', - 'az-AZ', - 'bg-BG', - 'bn-BD', - 'bn-IN', - 'bs-BA', - 'ca-ES', - 'cs-CZ', - 'cy-GB', - 'da-DK', - 'de-AT', - 'de-CH', - 'de-DE', - 'el-GR', - 'en-AU', - 'en-CA', - 'en-GB', - 'en-HK', - 'en-IE', - 'en-IN', - 'en-KE', - 'en-NG', - 'en-NZ', - 'en-PH', - 'en-SG', - 'en-TZ', - 'en-US', - 'en-ZA', - 'es-AR', - 'es-BO', - 'es-CL', - 'es-CO', - 'es-CR', - 'es-CU', - 'es-DO', - 'es-EC', - 'es-ES', - 'es-GQ', - 'es-GT', - 'es-HN', - 'es-MX', - 'es-NI', - 'es-PA', - 'es-PE', - 'es-PR', - 'es-PY', - 'es-SV', - 'es-US', - 'es-UY', - 'es-VE', - 'et-EE', - 'eu-ES', - 'fa-IR', - 'fi-FI', - 'fil-PH', - 'fr-BE', - 'fr-CA', - 'fr-CH', - 'fr-FR', - 'ga-IE', - 'gl-ES', - 'gu-IN', - 'he-IL', - 'hi-IN', - 'hr-HR', - 'hu-HU', - 'hy-AM', - 'id-ID', - 'is-IS', - 'it-IT', - 'ja-JP', - 'jv-ID', - 'ka-GE', - 'kk-KZ', - 'km-KH', - 'kn-IN', - 'ko-KR', - 'lo-LA', - 'lt-LT', - 'lv-LV', - 'mk-MK', - 'ml-IN', - 'mn-MN', - 'mr-IN', - 'ms-MY', - 'mt-MT', - 'my-MM', - 'nb-NO', - 'ne-NP', - 'nl-BE', - 'nl-NL', - 'pl-PL', - 'ps-AF', - 'pt-BR', - 'pt-PT', - 'ro-RO', - 'ru-RU', - 'si-LK', - 'sk-SK', - 'sl-SI', - 'so-SO', - 'sq-AL', - 'sr-RS', - 'su-ID', - 'sv-SE', - 'sw-KE', - 'sw-TZ', - 'ta-IN', - 'ta-LK', - 'ta-MY', - 'ta-SG', - 'te-IN', - 'th-TH', - 'tr-TR', - 'uk-UA', - 'ur-IN', - 'ur-PK', - 'uz-UZ', - 'vi-VN', - 'wuu-CN', - 'yue-CN', - 'zh-CN', - 'zh-HK', - 'zh-TW', - 'zu-ZA', - 'ar-EG', - 'ar-SA', - 'bg-BG', - 'ca-ES', - 'cs-CZ', - 'da-DK', - 'de-AT', - 'de-CH', - 'de-DE', - 'el-GR', - 'en-AU', - 'en-CA', - 'en-GB', - 'en-IE', - 'en-IN', - 'en-US', - 'es-ES', - 'es-MX', - 'fi-FI', - 'fr-BE', - 'fr-CA', - 'fr-CH', - 'fr-FR', - 'he-IL', - 'hi-IN', - 'hr-HR', - 'hu-HU', - 'id-ID', - 'it-IT', - 'ja-JP', - 'ko-KR', - 'ms-MY', - 'nb-NO', - 'nl-BE', - 'nl-NL', - 'pl-PL', - 'pt-BR', - 'pt-PT', - 'ro-RO', - 'ru-RU', - 'sk-SK', - 'sl-SI', - 'sv-SE', - 'ta-IN', - 'te-IN', - 'th-TH', - 'tr-TR', - 'vi-VN', - 'zh-CN', - 'zh-HK', - 'zh-TW', - ]; +class VoiceValidator +{ protected VoiceParams $params; - public function __construct(VoiceParams $params) { + public function __construct(VoiceParams $params) + { $this->params = $params; } /** * @throws InvalidRequiredArgumentException|InvalidOptionalArgumentException */ - public function validate(): void { + public function validate(): void + { $this->from(); - $this->language(); $this->ringtime(); $this->text(); $this->to(); @@ -223,7 +30,8 @@ public function validate(): void { /** * @throws InvalidOptionalArgumentException */ - public function from(): void { + public function from(): void + { $from = $this->params->getFrom(); if ($from === null) return; @@ -240,22 +48,11 @@ public function from(): void { ); } - /** - * @throws InvalidRequiredArgumentException - */ - public function language(): void { - $language = $this->params->getLanguage(); - - if ($language === null) return; - - if (!in_array($language, self::$LANGUAGES)) - throw new InvalidRequiredArgumentException('Invalid language.'); - } - /** * @throws InvalidOptionalArgumentException */ - public function ringtime(): void { + public function ringtime(): void + { $ringtime = $this->params->getRingtime(); if ($ringtime === null) return; @@ -273,7 +70,8 @@ public function ringtime(): void { } /** @throws InvalidRequiredArgumentException */ - public function text(): void { + public function text(): void + { $text = $this->params->getText(); $max = 10000; @@ -286,7 +84,8 @@ public function text(): void { } /** @throws InvalidRequiredArgumentException */ - public function to(): void { + public function to(): void + { $to = $this->params->getTo(); if ('' === $to) throw new InvalidRequiredArgumentException( From 1bbcc7a9c6d0d53505a22a41393652f7714a0423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 12:51:38 +0200 Subject: [PATCH 13/54] adjust ringtime values --- src/Resource/VoiceResource.php | 16 ++++++++++++---- src/Validator/VoiceValidator.php | 2 +- tests/Client/VoiceTest.php | 19 ++++++++++++------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/Resource/VoiceResource.php b/src/Resource/VoiceResource.php index fbb0d48..3efdf21 100644 --- a/src/Resource/VoiceResource.php +++ b/src/Resource/VoiceResource.php @@ -2,19 +2,25 @@ namespace Seven\Api\Resource; +use Seven\Api\Exception\InvalidOptionalArgumentException; use Seven\Api\Exception\InvalidRequiredArgumentException; use Seven\Api\Params\VoiceParams; use Seven\Api\Response\Voice\Voice; use Seven\Api\Validator\VoiceValidator; -class VoiceResource extends Resource { +class VoiceResource extends Resource +{ /** + * @param VoiceParams $params + * @return Voice + * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ - public function post(VoiceParams $params): Voice { + public function call(VoiceParams $params): Voice + { $this->validate($params); - $res = $this->client->post('voice', array_merge($params->toArray(), ['json' => true])); + $res = $this->client->post('voice', $params->toArray()); return new Voice($res); } @@ -22,8 +28,10 @@ public function post(VoiceParams $params): Voice { /** * @param VoiceParams $params * @throws InvalidRequiredArgumentException + * @throws InvalidOptionalArgumentException */ - public function validate($params): void { + public function validate($params): void + { (new VoiceValidator($params))->validate(); } } diff --git a/src/Validator/VoiceValidator.php b/src/Validator/VoiceValidator.php index 1b8ab33..93e9d1a 100755 --- a/src/Validator/VoiceValidator.php +++ b/src/Validator/VoiceValidator.php @@ -57,7 +57,7 @@ public function ringtime(): void if ($ringtime === null) return; - $min = 1; + $min = 5; $max = 60; if ($ringtime < $min) throw new InvalidOptionalArgumentException( diff --git a/tests/Client/VoiceTest.php b/tests/Client/VoiceTest.php index 11061c4..4627e2f 100755 --- a/tests/Client/VoiceTest.php +++ b/tests/Client/VoiceTest.php @@ -5,14 +5,17 @@ use Seven\Api\Params\VoiceParams; use Seven\Api\Response\Voice\Voice; -class VoiceTest extends BaseTest { - public function testVoice(): void { - $res = $this->client->voice->post($this->params); +class VoiceTest extends BaseTest +{ + public function testVoice(): void + { + $res = $this->client->voice->call($this->params); $this->assertVoice($res); } - private function assertVoice(Voice $v, bool $sandbox = false): void { + private function assertVoice(Voice $v, bool $sandbox = false): void + { $this->assertEquals(100, $v->getSuccess()); $this->assertCount(1, $v->getMessages()); @@ -25,15 +28,17 @@ private function assertVoice(Voice $v, bool $sandbox = false): void { else $this->assertGreaterThanOrEqual(0, $v->getTotalPrice()); } - public function testVoiceSandbox(): void { + public function testVoiceSandbox(): void + { $this->toSandbox(); $params = (clone $this->params); - $res = $this->client->voice->post($params); + $res = $this->client->voice->call($params); $this->assertVoice($res, true); } - protected function setUp(): void { + protected function setUp(): void + { $this->params = new VoiceParams('The current time is' . time(), '491716992343'); } } From 7cd8f0f3a79ad482d6cad35fa7406b7f12d979b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 12:54:17 +0200 Subject: [PATCH 14/54] remove pricingparams.format --- src/Constant/PricingConstants.php | 4 ++-- src/Params/PricingParams.php | 22 ++++++++-------------- src/Resource/PricingResource.php | 12 ++++++++---- src/Validator/PricingValidator.php | 25 ++++++++----------------- tests/Client/PricingTest.php | 13 ++++++++----- 5 files changed, 34 insertions(+), 42 deletions(-) diff --git a/src/Constant/PricingConstants.php b/src/Constant/PricingConstants.php index ad99012..672b8a1 100644 --- a/src/Constant/PricingConstants.php +++ b/src/Constant/PricingConstants.php @@ -2,7 +2,7 @@ namespace Seven\Api\Constant; -class PricingConstants { +class PricingConstants +{ public const COUNTRY_MAX_LENGTH = 3; - public const FORMATS = ['csv', 'json']; } diff --git a/src/Params/PricingParams.php b/src/Params/PricingParams.php index 56b874f..2b6998d 100644 --- a/src/Params/PricingParams.php +++ b/src/Params/PricingParams.php @@ -2,29 +2,23 @@ namespace Seven\Api\Params; -class PricingParams implements ParamsInterface { +class PricingParams implements ParamsInterface +{ protected ?string $country = null; - protected ?string $format = null; - public function toArray(): array { + public function toArray(): array + { return get_object_vars($this); } - public function getCountry(): ?string { + public function getCountry(): ?string + { return $this->country; } - public function setCountry(?string $country): self { + public function setCountry(?string $country): self + { $this->country = $country; return $this; } - - public function getFormat(): ?string { - return $this->format; - } - - public function setFormat(?string $format): self { - $this->format = $format; - return $this; - } } diff --git a/src/Resource/PricingResource.php b/src/Resource/PricingResource.php index 79a4432..deb61af 100644 --- a/src/Resource/PricingResource.php +++ b/src/Resource/PricingResource.php @@ -7,11 +7,13 @@ use Seven\Api\Response\Pricing\Pricing; use Seven\Api\Validator\PricingValidator; -class PricingResource extends Resource { +class PricingResource extends Resource +{ /** * @throws InvalidOptionalArgumentException */ - public function json(string $country = null): Pricing { + public function get(string $country = null): Pricing + { $params = (new PricingParams)->setCountry($country); $res = $this->fetch($params); return new Pricing($res); @@ -21,7 +23,8 @@ public function json(string $country = null): Pricing { * @return string|object * @throws InvalidOptionalArgumentException */ - protected function fetch(PricingParams $params = null) { + protected function fetch(PricingParams $params = null) + { if (!$params) $params = new PricingParams; $this->validate($params); @@ -33,7 +36,8 @@ protected function fetch(PricingParams $params = null) { * @param PricingParams $params * @throws InvalidOptionalArgumentException */ - public function validate($params): void { + public function validate($params): void + { (new PricingValidator($params))->validate(); } } diff --git a/src/Validator/PricingValidator.php b/src/Validator/PricingValidator.php index 7e37be6..5daf487 100755 --- a/src/Validator/PricingValidator.php +++ b/src/Validator/PricingValidator.php @@ -6,21 +6,21 @@ use Seven\Api\Exception\InvalidOptionalArgumentException; use Seven\Api\Params\PricingParams; -class PricingValidator { - protected PricingParams $params; - - public function __construct(PricingParams $params) { - $this->params = $params; +class PricingValidator +{ + public function __construct(protected PricingParams $params) + { } /** @throws InvalidOptionalArgumentException */ - public function validate(): void { + public function validate(): void + { $this->country(); - $this->format(); } /** @throws InvalidOptionalArgumentException */ - public function country(): void { + public function country(): void + { $country = $this->params->getCountry(); if (!$country) return; @@ -31,13 +31,4 @@ public function country(): void { . PricingConstants::COUNTRY_MAX_LENGTH); } } - - /** @throws InvalidOptionalArgumentException */ - public function format(): void { - $format = $this->params->getFormat(); - if (!$format) return; - - if (!in_array($format, PricingConstants::FORMATS)) - throw new InvalidOptionalArgumentException("format seems to be invalid: $format."); - } } diff --git a/tests/Client/PricingTest.php b/tests/Client/PricingTest.php index e924140..b76f630 100755 --- a/tests/Client/PricingTest.php +++ b/tests/Client/PricingTest.php @@ -2,17 +2,20 @@ namespace Seven\Tests\Client; -class PricingTest extends BaseTest { - public function testGermany(): void { - $res = $this->client->pricing->json('de'); +class PricingTest extends BaseTest +{ + public function testGermany(): void + { + $res = $this->client->pricing->get('de'); self::assertEquals(1, $res->getCountCountries()); self::assertGreaterThan(0, $res->getCountNetworks()); self::assertCount(1, $res->getCountries()); } - public function testJson(): void { - $res = $this->client->pricing->json(); + public function testJson(): void + { + $res = $this->client->pricing->get(); self::assertGreaterThan(0, $res->getCountCountries()); self::assertGreaterThan(0, $res->getCountNetworks()); From 132ebcf80a624bb35dec9b72a12d7707c9af2b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 13:03:16 +0200 Subject: [PATCH 15/54] clean up analytics --- src/Constant/AnalyticsGroupBy.php | 14 -------- src/Constant/AnalyticsSubaccounts.php | 11 +++--- src/Params/AnalyticsParams.php | 41 ++++++++++++----------- src/Resource/AnalyticsResource.php | 48 +++++++++++---------------- src/Validator/AnalyticsValidator.php | 23 ++++++++----- tests/Client/AnalyticsTest.php | 29 ++++++++-------- 6 files changed, 75 insertions(+), 91 deletions(-) delete mode 100644 src/Constant/AnalyticsGroupBy.php diff --git a/src/Constant/AnalyticsGroupBy.php b/src/Constant/AnalyticsGroupBy.php deleted file mode 100644 index c642de9..0000000 --- a/src/Constant/AnalyticsGroupBy.php +++ /dev/null @@ -1,14 +0,0 @@ -start; } - public function setStart(?DateTime $start): self { + public function setStart(?DateTime $start): self + { $this->start = $start; return $this; } - public function getEnd(): ?DateTime { + public function getEnd(): ?DateTime + { return $this->end; } - public function setEnd(?DateTime $end): self { + public function setEnd(?DateTime $end): self + { $this->end = $end; return $this; } - public function getLabel(): ?string { + public function getLabel(): ?string + { return $this->label; } - public function setLabel(?string $label): self { + public function setLabel(?string $label): self + { $this->label = $label; return $this; } - public function getSubaccounts(): ?string { + public function getSubaccounts(): string|int|null + { return $this->subaccounts; } - public function setSubaccounts(?string $subaccounts): self { + public function setSubaccounts(string|int|null $subaccounts): self + { $this->subaccounts = $subaccounts; return $this; } diff --git a/src/Resource/AnalyticsResource.php b/src/Resource/AnalyticsResource.php index bb660ea..3783a3f 100644 --- a/src/Resource/AnalyticsResource.php +++ b/src/Resource/AnalyticsResource.php @@ -2,7 +2,6 @@ namespace Seven\Api\Resource; -use Seven\Api\Constant\AnalyticsGroupBy; use Seven\Api\Exception\InvalidOptionalArgumentException; use Seven\Api\Params\AnalyticsParams; use Seven\Api\Response\Analytics\AbstractAnalytic; @@ -12,50 +11,38 @@ use Seven\Api\Response\Analytics\AnalyticBySubaccount; use Seven\Api\Validator\AnalyticsValidator; -class AnalyticsResource extends Resource { +class AnalyticsResource extends Resource +{ /** * @return AnalyticByCountry[] * @throws InvalidOptionalArgumentException */ - public function byCountry(AnalyticsParams $params = null): array { - return $this->fetch($params ?? new AnalyticsParams, AnalyticsGroupBy::COUNTRY); + public function byCountry(AnalyticsParams $params = new AnalyticsParams): array + { + return $this->fetch($params, 'country', AnalyticByCountry::class); } /** * @return AbstractAnalytic[] * @throws InvalidOptionalArgumentException */ - protected function fetch(AnalyticsParams $params, string $groupBy): array { + protected function fetch(AnalyticsParams $params, string $groupBy, string $class): array + { $this->validate($params); - switch ($groupBy) { - case AnalyticsGroupBy::COUNTRY: - $class = AnalyticByCountry::class; - break; - case AnalyticsGroupBy::LABEL: - $class = AnalyticByLabel::class; - break; - case AnalyticsGroupBy::SUBACCOUNT: - $class = AnalyticBySubaccount::class; - break; - default: - $class = AnalyticByDate::class; - } - $arr = $this->client->get( 'analytics', array_merge($params->toArray(), ['group_by' => $groupBy]) ); - return array_map(static function ($value) use ($class) { - return new $class($value); - }, $arr); + return array_map(static fn($value) => new $class($value), $arr); } /** * @param AnalyticsParams $params * @throws InvalidOptionalArgumentException */ - public function validate($params): void { + public function validate($params): void + { (new AnalyticsValidator($params))->validate(); } @@ -63,23 +50,26 @@ public function validate($params): void { * @return AnalyticByDate[] * @throws InvalidOptionalArgumentException */ - public function byDate(AnalyticsParams $params = null): array { - return $this->fetch($params ?? new AnalyticsParams, AnalyticsGroupBy::DATE); + public function byDate(AnalyticsParams $params = new AnalyticsParams): array + { + return $this->fetch($params, 'date', AnalyticByDate::class); } /** * @return AnalyticByLabel[] * @throws InvalidOptionalArgumentException */ - public function byLabel(AnalyticsParams $params = null): array { - return $this->fetch($params ?? new AnalyticsParams, AnalyticsGroupBy::LABEL); + public function byLabel(AnalyticsParams $params = new AnalyticsParams): array + { + return $this->fetch($params, 'label', AnalyticByLabel::class); } /** * @return AnalyticBySubaccount[] * @throws InvalidOptionalArgumentException */ - public function bySubaccount(AnalyticsParams $params = null): array { - return $this->fetch($params ?? new AnalyticsParams, AnalyticsGroupBy::SUBACCOUNT); + public function bySubaccount(AnalyticsParams $params = new AnalyticsParams): array + { + return $this->fetch($params, 'subaccount', AnalyticBySubaccount::class); } } diff --git a/src/Validator/AnalyticsValidator.php b/src/Validator/AnalyticsValidator.php index 44d3ba3..338e37c 100755 --- a/src/Validator/AnalyticsValidator.php +++ b/src/Validator/AnalyticsValidator.php @@ -7,15 +7,18 @@ use Seven\Api\Exception\InvalidOptionalArgumentException; use Seven\Api\Params\AnalyticsParams; -class AnalyticsValidator { +class AnalyticsValidator +{ protected AnalyticsParams $params; - public function __construct(AnalyticsParams $params) { + public function __construct(AnalyticsParams $params) + { $this->params = $params; } /** @throws InvalidOptionalArgumentException */ - public function validate(): void { + public function validate(): void + { $this->end(); $this->label(); $this->start(); @@ -23,7 +26,8 @@ public function validate(): void { } /** @throws InvalidOptionalArgumentException */ - public function end(): void { + public function end(): void + { $end = $this->params->getEnd(); if (!$end) return; @@ -35,11 +39,13 @@ public function end(): void { throw new InvalidOptionalArgumentException('start date can not be past end date.'); } - public function label(): void { + public function label(): void + { } /** @throws InvalidOptionalArgumentException */ - public function start(): void { + public function start(): void + { $start = $this->params->getStart(); if (!$start) return; @@ -48,12 +54,13 @@ public function start(): void { } /** @throws InvalidOptionalArgumentException */ - public function subaccounts(): void { + public function subaccounts(): void + { $subaccounts = $this->params->getSubaccounts(); if (!$subaccounts) return; $invalid = false; - $values = AnalyticsSubaccounts::values(); + $values = array_column(AnalyticsSubaccounts::cases(), 'value');; if (!in_array($subaccounts, $values)) { if (is_numeric($subaccounts)) { diff --git a/tests/Client/AnalyticsTest.php b/tests/Client/AnalyticsTest.php index 67a7599..74e0e6f 100755 --- a/tests/Client/AnalyticsTest.php +++ b/tests/Client/AnalyticsTest.php @@ -3,13 +3,14 @@ namespace Seven\Tests\Client; use Seven\Api\Response\Analytics\AbstractAnalytic; -use Seven\Api\Response\Analytics\AnalyticByCountry; use Seven\Api\Response\Analytics\AnalyticByDate; use Seven\Api\Response\Analytics\AnalyticByLabel; use Seven\Api\Response\Analytics\AnalyticBySubaccount; -class AnalyticsTest extends BaseTest { - public function testAnalyticsGroupByDate(): void { +class AnalyticsTest extends BaseTest +{ + public function testAnalyticsGroupByDate(): void + { $res = $this->client->analytics->byDate(); $this->assertCount(31, $res); @@ -24,13 +25,15 @@ public function testAnalyticsGroupByDate(): void { /** * @return AbstractAnalytic[] */ - private function assertResponse(array $res): array { + private function assertResponse(array $res): array + { $this->assertIsArray($res); return $res; } - private function assertEach(AbstractAnalytic $a): bool { + private function assertEach(AbstractAnalytic $a): bool + { $this->assertGreaterThanOrEqual(0, $a->getHLR()); $this->assertGreaterThanOrEqual(0, $a->getInbound()); $this->assertGreaterThanOrEqual(0, $a->getMNP()); @@ -53,23 +56,21 @@ private function assertEach(AbstractAnalytic $a): bool { return $isEmpty; } - public function testAnalyticsGroupByLabel(): void { + public function testAnalyticsGroupByLabel(): void + { foreach ($this->assertResponse($this->client->analytics->byLabel()) as $a) { /** @var AnalyticByLabel $a */ $this->assertIsString($a->getLabel()); } } - public function testAnalyticsGroupByCountry(): void { - foreach ($this->assertResponse($this->client->analytics->byCountry()) as $a) { - /** @var AnalyticByCountry $a */ - $country = $a->getCountry(); - $this->assertIsString($country); - $this->assertNotEmpty($country); - } + public function testAnalyticsGroupByCountry(): void + { + $this->assertResponse($this->client->analytics->byCountry()); } - public function testAnalyticsGroupBySubaccount(): void { + public function testAnalyticsGroupBySubaccount(): void + { foreach ($this->assertResponse($this->client->analytics->bySubaccount()) as $a) { /** @var AnalyticBySubaccount $a */ $account = $a->getAccount(); From e5646e640176c74a2a08cc048d00402caaf8e39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 13:08:48 +0200 Subject: [PATCH 16/54] fix rcs validator --- .../CreateSubaccountParams.php | 8 +-- .../{ => Subaccounts}/SubaccountsParams.php | 49 +++++++++++++------ src/Resource/RcsResource.php | 1 + src/Resource/SubaccountsResource.php | 28 +++++++---- src/Validator/RcsValidator.php | 36 -------------- src/Validator/SubaccountsValidator.php | 29 +++++++---- tests/Client/SubaccountsTest.php | 26 ++++++---- 7 files changed, 93 insertions(+), 84 deletions(-) rename src/Params/{ => Subaccounts}/CreateSubaccountParams.php (54%) rename src/Params/{ => Subaccounts}/SubaccountsParams.php (52%) diff --git a/src/Params/CreateSubaccountParams.php b/src/Params/Subaccounts/CreateSubaccountParams.php similarity index 54% rename from src/Params/CreateSubaccountParams.php rename to src/Params/Subaccounts/CreateSubaccountParams.php index 84c4874..8a0433a 100644 --- a/src/Params/CreateSubaccountParams.php +++ b/src/Params/Subaccounts/CreateSubaccountParams.php @@ -1,11 +1,13 @@ name = $name; $this->email = $email; parent::__construct(SubaccountsAction::CREATE); diff --git a/src/Params/SubaccountsParams.php b/src/Params/Subaccounts/SubaccountsParams.php similarity index 52% rename from src/Params/SubaccountsParams.php rename to src/Params/Subaccounts/SubaccountsParams.php index 7ae65ad..2bd756e 100644 --- a/src/Params/SubaccountsParams.php +++ b/src/Params/Subaccounts/SubaccountsParams.php @@ -1,8 +1,11 @@ action = $action; } - public function toArray(): array { + public function toArray(): array + { return get_object_vars($this); } - public function getAction(): string { + public function getAction(): string + { return $this->action; } - public function setAction(string $action): self { + public function setAction(string $action): self + { $this->action = $action; return $this; } - public function getName(): ?string { + public function getName(): ?string + { return $this->action; } - public function setName(?string $name): self { + public function setName(?string $name): self + { $this->name = $name; return $this; } - public function getEmail(): ?string { + public function getEmail(): ?string + { return $this->email; } - public function setEmail(?string $email): self { + public function setEmail(?string $email): self + { $this->email = $email; return $this; } - public function getId(): ?int { + public function getId(): ?int + { return $this->id; } - public function setId(?int $id): self { + public function setId(?int $id): self + { $this->id = $id; return $this; } - public function getAmount(): ?float { + public function getAmount(): ?float + { return $this->amount; } - public function setAmount(?float $amount): self { + public function setAmount(?float $amount): self + { $this->amount = $amount; return $this; } - public function getThreshold(): ?float { + public function getThreshold(): ?float + { return $this->threshold; } - public function setThreshold(?float $threshold): self { + public function setThreshold(?float $threshold): self + { $this->threshold = $threshold; return $this; } diff --git a/src/Resource/RcsResource.php b/src/Resource/RcsResource.php index 834249d..2d0c74a 100644 --- a/src/Resource/RcsResource.php +++ b/src/Resource/RcsResource.php @@ -35,6 +35,7 @@ public function dispatch(RcsParams $params): Rcs } /** + * @param RcsParams $params * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ diff --git a/src/Resource/SubaccountsResource.php b/src/Resource/SubaccountsResource.php index 15a25bb..be7cab9 100644 --- a/src/Resource/SubaccountsResource.php +++ b/src/Resource/SubaccountsResource.php @@ -5,8 +5,8 @@ use Seven\Api\Constant\SubaccountsAction; use Seven\Api\Exception\InvalidOptionalArgumentException; use Seven\Api\Exception\InvalidRequiredArgumentException; -use Seven\Api\Params\CreateSubaccountParams; -use Seven\Api\Params\SubaccountsParams; +use Seven\Api\Params\Subaccounts\CreateSubaccountParams; +use Seven\Api\Params\Subaccounts\SubaccountsParams; use Seven\Api\Response\Subaccounts\Subaccount; use Seven\Api\Response\Subaccounts\SubaccountCreate; use Seven\Api\Response\Subaccounts\SubaccountDelete; @@ -14,12 +14,14 @@ use Seven\Api\Response\Subaccounts\SubaccountUpdate; use Seven\Api\Validator\SubaccountsValidator; -class SubaccountsResource extends Resource { +class SubaccountsResource extends Resource +{ /** * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ - public function delete(int $id): SubaccountDelete { + public function delete(int $id): SubaccountDelete + { $params = (new SubaccountsParams(SubaccountsAction::DELETE))->setId($id); $res = $this->fetch($params, 'POST'); @@ -31,7 +33,8 @@ public function delete(int $id): SubaccountDelete { * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ - protected function fetch(SubaccountsParams $params, string $method) { + protected function fetch(SubaccountsParams $params, string $method) + { $this->validate($params); return $this->client->$method('subaccounts', $params->toArray()); @@ -41,7 +44,8 @@ protected function fetch(SubaccountsParams $params, string $method) { * @param SubaccountsParams $params * @throws InvalidRequiredArgumentException */ - public function validate($params): void { + public function validate($params): void + { (new SubaccountsValidator($params))->validate(); } @@ -50,7 +54,8 @@ public function validate($params): void { * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ - public function read(): array { + public function read(): array + { $params = new SubaccountsParams(SubaccountsAction::READ); $arr = $this->fetch($params, 'GET'); @@ -63,7 +68,8 @@ public function read(): array { * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ - public function create(CreateSubaccountParams $params): SubaccountCreate { + public function create(CreateSubaccountParams $params): SubaccountCreate + { $res = $this->fetch($params, 'POST'); return new SubaccountCreate($res); @@ -73,7 +79,8 @@ public function create(CreateSubaccountParams $params): SubaccountCreate { * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ - public function transferCredits(int $id, float $amount): SubaccountTransferCredits { + public function transferCredits(int $id, float $amount): SubaccountTransferCredits + { $params = (new SubaccountsParams(SubaccountsAction::TRANSFER_CREDITS)) ->setAmount($amount) ->setId($id); @@ -86,7 +93,8 @@ public function transferCredits(int $id, float $amount): SubaccountTransferCredi * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ - public function update(int $id, float $amount, float $threshold): SubaccountUpdate { + public function update(int $id, float $amount, float $threshold): SubaccountUpdate + { $params = (new SubaccountsParams(SubaccountsAction::UPDATE)) ->setAmount($amount) ->setId($id) diff --git a/src/Validator/RcsValidator.php b/src/Validator/RcsValidator.php index 3830fb2..f105c61 100644 --- a/src/Validator/RcsValidator.php +++ b/src/Validator/RcsValidator.php @@ -62,37 +62,8 @@ public function foreign_id(): void } } - /** @throws InvalidOptionalArgumentException */ public function from(): void { - $from = $this->params->getFrom(); - - if (null === $from || '' === $from) { - return; - } - - $length = strlen($from); - - $alphaNumericMax = SmsConstants::FROM_ALPHANUMERIC_MAX; - $numericMax = SmsConstants::FROM_NUMERIC_MAX; - - $isNumeric = is_numeric($from); - - if ($length > $numericMax) { - throw new InvalidOptionalArgumentException( - "Argument 'from' may not exceed $numericMax chars."); - } - - if ($length > $alphaNumericMax && !$isNumeric) { - throw new InvalidOptionalArgumentException( - "Argument 'from' must be numeric. if > $alphaNumericMax chars."); - } - - if (!ctype_alnum( - str_ireplace(SmsConstants::FROM_ALLOWED_CHARS, '', $from))) { - throw new InvalidOptionalArgumentException( - "Argument 'from' must be alphanumeric."); - } } /** @throws InvalidOptionalArgumentException */ @@ -128,13 +99,6 @@ public function text(): void throw new InvalidRequiredArgumentException( 'You cannot send an empty message.'); } - - $maxTextLength = SmsConstants::TEXT_MAX_LENGTH; - - if ($maxTextLength < $length) { - throw new InvalidRequiredArgumentException( - "The text can not be longer than $maxTextLength characters."); - } } /** @throws InvalidRequiredArgumentException */ diff --git a/src/Validator/SubaccountsValidator.php b/src/Validator/SubaccountsValidator.php index 5228b02..482fbbc 100644 --- a/src/Validator/SubaccountsValidator.php +++ b/src/Validator/SubaccountsValidator.php @@ -4,19 +4,22 @@ use Seven\Api\Constant\SubaccountsAction; use Seven\Api\Exception\InvalidRequiredArgumentException; -use Seven\Api\Params\SubaccountsParams; +use Seven\Api\Params\Subaccounts\SubaccountsParams; -class SubaccountsValidator { +class SubaccountsValidator +{ protected SubaccountsParams $params; - public function __construct(SubaccountsParams $params) { + public function __construct(SubaccountsParams $params) + { $this->params = $params; } /** * @throws InvalidRequiredArgumentException */ - public function validate(): void { + public function validate(): void + { $this->action(); switch ($this->params->getAction()) { @@ -39,13 +42,15 @@ public function validate(): void { } /** @throws InvalidRequiredArgumentException */ - public function action(): void { + public function action(): void + { if (!in_array($this->params->getAction(), SubaccountsAction::values())) throw new InvalidRequiredArgumentException('Parameter "number" is missing.'); } /** @throws InvalidRequiredArgumentException */ - public function create(): void { + public function create(): void + { if (!$this->params->getName()) throw new InvalidRequiredArgumentException('Parameter "name" is missing.'); @@ -54,16 +59,19 @@ public function create(): void { } /** @throws InvalidRequiredArgumentException */ - public function delete(): void { + public function delete(): void + { if (!$this->params->getId()) throw new InvalidRequiredArgumentException('Parameter "id" is missing or invalid.'); } - public function read(): void { + public function read(): void + { } /** @throws InvalidRequiredArgumentException */ - public function transferCredits(): void { + public function transferCredits(): void + { if (!$this->params->getId()) throw new InvalidRequiredArgumentException('Parameter "id" is invalid.'); @@ -72,7 +80,8 @@ public function transferCredits(): void { } /** @throws InvalidRequiredArgumentException */ - public function update(): void { + public function update(): void + { if (!$this->params->getId()) throw new InvalidRequiredArgumentException('Parameter "id" is invalid.'); diff --git a/tests/Client/SubaccountsTest.php b/tests/Client/SubaccountsTest.php index cf8c28c..36882f8 100644 --- a/tests/Client/SubaccountsTest.php +++ b/tests/Client/SubaccountsTest.php @@ -3,18 +3,21 @@ namespace Seven\Tests\Client; use Seven\Api\Exception\InvalidRequiredArgumentException; -use Seven\Api\Params\CreateSubaccountParams; +use Seven\Api\Params\Subaccounts\CreateSubaccountParams; use Seven\Api\Response\Subaccounts\Subaccount; -class SubaccountsTest extends BaseTest { - public function testCreateFail(): void { +class SubaccountsTest extends BaseTest +{ + public function testCreateFail(): void + { $this->expectException(InvalidRequiredArgumentException::class); $params = new CreateSubaccountParams('', ''); $this->client->subaccounts->create($params); } - public function testCreate(): Subaccount { + public function testCreate(): Subaccount + { $params = new CreateSubaccountParams( 'Tommy Tester', sprintf('tommy.tester.%d@seven.dev', time()) @@ -29,7 +32,8 @@ public function testCreate(): Subaccount { return $res->getSubaccount(); } - private function assertSubaccount(Subaccount $subaccount): void { + private function assertSubaccount(Subaccount $subaccount): void + { $this->assertGreaterThan(0, $subaccount->getId()); $this->assertGreaterThanOrEqual(0, $subaccount->getTotalUsage()); @@ -47,7 +51,8 @@ private function assertSubaccount(Subaccount $subaccount): void { /** * @depends testCreate */ - public function testTransferCredits(Subaccount $subaccount): Subaccount { + public function testTransferCredits(Subaccount $subaccount): Subaccount + { $id = $subaccount->getId(); $amount = 12.34; $res = $this->client->subaccounts->transferCredits($id, $amount); @@ -64,7 +69,8 @@ public function testTransferCredits(Subaccount $subaccount): Subaccount { /** * @depends testTransferCredits */ - public function testUpdate(Subaccount $subaccount): Subaccount { + public function testUpdate(Subaccount $subaccount): Subaccount + { $id = $subaccount->getId(); $amount = 12.34; $threshold = 123.456; @@ -82,7 +88,8 @@ public function testUpdate(Subaccount $subaccount): Subaccount { /** * @depends testUpdate */ - public function testDelete(Subaccount $subaccount): void { + public function testDelete(Subaccount $subaccount): void + { $res = $this->client->subaccounts->delete($subaccount->getId()); if ($res->isSuccess()) { @@ -92,7 +99,8 @@ public function testDelete(Subaccount $subaccount): void { } } - public function testRead(): void { + public function testRead(): void + { $res = $this->client->subaccounts->read(); $this->assertIsArray($res); From 076823faf8548c0a82b7b3711e090fc496fc6316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 13:18:49 +0200 Subject: [PATCH 17/54] use header to retrieve json --- src/Params/StatusParams.php | 20 ++++++++++++++------ src/Resource/SmsResource.php | 14 +++++++++----- src/Resource/StatusResource.php | 15 ++++++++------- tests/Client/SmsTest.php | 28 +++++++++++++++------------- tests/Client/StatusTest.php | 15 ++++++++++----- 5 files changed, 56 insertions(+), 36 deletions(-) diff --git a/src/Params/StatusParams.php b/src/Params/StatusParams.php index 3493f64..f32463f 100644 --- a/src/Params/StatusParams.php +++ b/src/Params/StatusParams.php @@ -2,25 +2,33 @@ namespace Seven\Api\Params; -class StatusParams implements ParamsInterface { +class StatusParams implements ParamsInterface +{ + /** @var int[] $messageIds */ protected array $messageIds; - public function __construct(int ...$messageIds) { + public function __construct(int ...$messageIds) + { $this->messageIds = $messageIds; } - public function getMessageIds(): array { + public function getMessageIds(): array + { return $this->messageIds; } - public function setMessageIds(array $messageIds): self { - $this->messageIds = $messageIds; + public function addMessageIds(int ...$messageIds): self + { + array_push($this->messageIds, ...$messageIds); return $this; } - public function toArray(): array { + public function toArray(): array + { $arr = get_object_vars($this); + $arr['msg_id'] = implode(',', $arr['messageIds']); + unset($arr['messageIds']); return $arr; diff --git a/src/Resource/SmsResource.php b/src/Resource/SmsResource.php index bace736..63e9c6e 100644 --- a/src/Resource/SmsResource.php +++ b/src/Resource/SmsResource.php @@ -9,8 +9,10 @@ use Seven\Api\Response\Sms\SmsDelete; use Seven\Api\Validator\SmsValidator; -class SmsResource extends Resource { - public function delete(int ...$ids): SmsDelete { +class SmsResource extends Resource +{ + public function delete(int ...$ids): SmsDelete + { $res = $this->client->delete('sms', compact('ids')); return new SmsDelete($res); } @@ -19,10 +21,11 @@ public function delete(int ...$ids): SmsDelete { * @throws InvalidRequiredArgumentException * @throws InvalidOptionalArgumentException */ - public function dispatch(SmsParams $params): Sms { + public function dispatch(SmsParams $params): Sms + { $this->validate($params); - $res = $this->client->post('sms', array_merge($params->toArray(), ['json' => true])); + $res = $this->client->post('sms', $params->toArray()); return new Sms($res); } @@ -32,7 +35,8 @@ public function dispatch(SmsParams $params): Sms { * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ - public function validate($params): void { + public function validate($params): void + { (new SmsValidator($params))->validate(); } } diff --git a/src/Resource/StatusResource.php b/src/Resource/StatusResource.php index 43d410f..35726c9 100644 --- a/src/Resource/StatusResource.php +++ b/src/Resource/StatusResource.php @@ -8,30 +8,31 @@ use Seven\Api\Response\Status; use Seven\Api\Validator\StatusValidator; -class StatusResource extends Resource { +class StatusResource extends Resource +{ /** * @return Status[] * @throws InvalidRequiredArgumentException * @throws UnexpectedApiResponseException */ - public function get(int ...$msgIds): array { + public function get(int ...$msgIds): array + { $params = new StatusParams(...$msgIds); $this->validate($params); - $res = $this->client->get('status', array_merge($params->toArray(), ['json' => true])); + $res = $this->client->get('status', $params->toArray()); if (!is_array($res)) throw new UnexpectedApiResponseException($res); - return array_map(static function ($obj) { - return new Status($obj); - }, $res); + return array_map(static fn($obj) => new Status($obj), $res); } /** * @param StatusParams $params * @throws InvalidRequiredArgumentException */ - public function validate($params): void { + public function validate($params): void + { (new StatusValidator($params))->validate(); } } diff --git a/tests/Client/SmsTest.php b/tests/Client/SmsTest.php index 051feca..9fff366 100755 --- a/tests/Client/SmsTest.php +++ b/tests/Client/SmsTest.php @@ -2,23 +2,28 @@ namespace Seven\Tests\Client; -use DateInterval; use DateTime; use Seven\Api\Params\SmsParams; -class SmsTest extends BaseTest { - public function testSms(): void { - $params = clone $this->params; +class SmsTest extends BaseTest +{ + public function testSms(): void + { + $params = (new SmsParams('HI2U! The UNIX time is ' . time() . '.', '491716992343')); $params->setText('Müller'); + $params->setDelay(new DateTime('2050-12-31')); $res = $this->client->sms->dispatch($params); $msg = $res->getMessages()[0]; $this->assertEquals($params->getText(), $msg->getText()); $this->assertEquals(str_replace('+', '', $params->getTo()[0]), $msg->getRecipient()); + + $this->client->sms->delete($msg->getId()); } - public function testSmsFiles(): void { - $p = clone $this->params; + public function testSmsFiles(): void + { + $p = (new SmsParams('HI2U! The UNIX time is ' . time() . '.', '491716992343')); $text = ''; $start = 1; $end = 3; @@ -41,10 +46,11 @@ public function testSmsFiles(): void { $this->assertEquals($fileCount, $links); } - public function testDelete(): void { - $params = (clone $this->params) + public function testDelete(): void + { + $params = (new SmsParams('HI2U! The UNIX time is ' . time() . '.', '491716992343')) ->addTo('4917987654321') - ->setDelay((new DateTime)->add(DateInterval::createFromDateString('1 day'))); + ->setDelay(new DateTime('2050-12-31')); $sms = $this->client->sms->dispatch($params); $this->assertNotEmpty($sms->getMessages()); $msg = $sms->getMessages()[0]; @@ -53,8 +59,4 @@ public function testDelete(): void { if ($res->isSuccess()) $this->assertSameSize($sms->getMessages(), $res->getDeleted()); else $this->assertNull($res->getDeleted()); } - - protected function setUp(): void { - $this->params = new SmsParams('HI2U! The UNIX time is ' . time() . '.', '491716992343'); - } } diff --git a/tests/Client/StatusTest.php b/tests/Client/StatusTest.php index 775a2fd..f670877 100755 --- a/tests/Client/StatusTest.php +++ b/tests/Client/StatusTest.php @@ -6,15 +6,19 @@ use Seven\Api\Exception\InvalidRequiredArgumentException; use Seven\Api\Params\JournalParams; -class StatusTest extends BaseTest { - public function testError(): void { +class StatusTest extends BaseTest +{ + public function testError(): void + { $this->expectException(InvalidRequiredArgumentException::class); $this->client->status->get(0); } - public function testSuccess(): void { + public function testSuccess(): void + { $msgId = $this->getMessageId(); - $arr = $this->client->status->get($msgId); + $arr = $this->client->status->get($msgId, $msgId); + $this->assertCount(2, $arr); foreach ($arr as $obj) { $status = $obj->getStatus(); @@ -27,7 +31,8 @@ public function testSuccess(): void { } } - private function getMessageId(): int { + private function getMessageId(): int + { $journalParams = (new JournalParams)->setLimit(1); $outbounds = $this->client->journal->outbound($journalParams); $outbound = $outbounds[0]; From 6eb6d52cdf90d7a940c6dc02e49bb5dbd2d4f37e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 13:44:30 +0200 Subject: [PATCH 18/54] implement request signing --- src/BaseClient.php | 51 +++++++++++++++++---------------------- src/Client.php | 4 +-- tests/Client/BaseTest.php | 2 +- 3 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/BaseClient.php b/src/BaseClient.php index ebeb451..b9b1a8e 100644 --- a/src/BaseClient.php +++ b/src/BaseClient.php @@ -10,46 +10,29 @@ abstract class BaseClient { public const BASE_URI = 'https://gateway.seven.io/api'; - /** - * @var array|string[] - */ + /** @var string[] $headers */ protected array $headers; /** * @throws Exception */ public function __construct( - protected string $apiKey, - protected string $sentWith = 'php-api' + protected string $apiKey, + protected string $sentWith = 'php-api', + protected ?string $signingSecret = null, ) { if ('' === $apiKey) throw new InvalidArgumentException( 'Invalid required constructor argument apiKey: ' . $apiKey); - if ('' === $sentWith || !is_string($sentWith)) throw new InvalidArgumentException( + if ('' === $sentWith) throw new InvalidArgumentException( 'Invalid required constructor argument sentWith: ' . $sentWith); $this->headers = [ 'Accept: application/json', 'SentWith: ' . $this->sentWith, - 'X-Api-Key:' . $this->apiKey, + 'X-Api-Key: ' . $this->apiKey, ]; - //$this->setContentTypeJson(); - } - - public function setContentTypeJson(): void - { - $this->setContentType('application/json'); - } - - public function setContentType(string $contentType): void - { - $this->headers['Content-Type'] = $contentType; - } - - public function setContentTypeUrlEncoded(): void - { - $this->setContentType('application/x-www-form-urlencoded'); } public function getApiKey(): string @@ -69,7 +52,6 @@ public function delete(string $path, array $options = [], array $headers = []): protected function request(string $path, HttpMethod $method, array $payload = [], array $headers = []): mixed { - $headers = array_unique([...$this->headers, ...$headers]); $url = self::BASE_URI . '/' . $path; $params = http_build_query($payload); if (HttpMethod::GET === $method) $url .= str_ends_with($url, '?') ? '' : '?' . $params; @@ -77,10 +59,7 @@ protected function request(string $path, HttpMethod $method, array $payload = [] $ch = curl_init($url); if (HttpMethod::POST === $method) { - $value = $headers['Content-Type'] ?? '' === 'application/json' - ? json_encode($payload, JSON_UNESCAPED_UNICODE) - : $params; - curl_setopt($ch, CURLOPT_POSTFIELDS, $value); + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); curl_setopt($ch, CURLOPT_POST, true); } elseif (HttpMethod::PATCH === $method) { curl_setopt($ch, CURLOPT_POSTFIELDS, $params); @@ -90,8 +69,22 @@ protected function request(string $path, HttpMethod $method, array $payload = [] curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::DELETE->name); } + if ($this->signingSecret) { + $nonce = bin2hex(random_bytes(16)); + $timestamp = time(); + $toSign = $timestamp . PHP_EOL . + $nonce . PHP_EOL . + $method->name . PHP_EOL . + $url . PHP_EOL . + md5($params); + $hash = hash_hmac('sha256', $toSign, $this->signingSecret); + $this->headers[] = 'X-Nonce: ' . $nonce; + $this->headers[] = 'X-Signature: ' . $hash; + $this->headers[] = 'X-Timestamp: ' . $timestamp; + } + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_HTTPHEADER, array_unique([...$this->headers, ...$headers])); $res = curl_exec($ch); diff --git a/src/Client.php b/src/Client.php index 8f20d28..4f86e40 100755 --- a/src/Client.php +++ b/src/Client.php @@ -36,9 +36,9 @@ class Client extends BaseClient public ValidateForVoiceResource $validateForVoice; public VoiceResource $voice; - public function __construct(string $apiKey, string $sentWith = 'php-api') + public function __construct(string $apiKey, string $sentWith = 'php-api', string $signingSecret = null) { - parent::__construct($apiKey, $sentWith); + parent::__construct($apiKey, $sentWith, $signingSecret); $this->analytics = new AnalyticsResource($this); $this->balance = new BalanceResource($this); diff --git a/tests/Client/BaseTest.php b/tests/Client/BaseTest.php index eeda366..a047e1b 100755 --- a/tests/Client/BaseTest.php +++ b/tests/Client/BaseTest.php @@ -21,7 +21,7 @@ public function __construct() protected function init(string $apiKey, bool $isSandbox): void { - $this->client = new Client($apiKey, 'php-api-test'); + $this->client = new Client($apiKey, 'php-api-test', getenv('SEVEN_SIGNING_SECRET')); $this->isSandbox = $isSandbox; } From 38ed530312a0db6d7f1672135d7f29cf6d92e297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 13:46:54 +0200 Subject: [PATCH 19/54] use strict types for resources --- src/Resource/AnalyticsResource.php | 2 +- src/Resource/BalanceResource.php | 11 +++++++---- src/Resource/ContactsResource.php | 2 +- src/Resource/GroupsResource.php | 2 +- src/Resource/HooksResource.php | 2 +- src/Resource/JournalResource.php | 2 +- src/Resource/LookupResource.php | 2 +- src/Resource/NumbersResource.php | 2 +- src/Resource/PricingResource.php | 2 +- src/Resource/RcsResource.php | 2 +- src/Resource/Resource.php | 11 +++++------ src/Resource/SmsResource.php | 2 +- src/Resource/StatusResource.php | 2 +- src/Resource/SubaccountsResource.php | 2 +- src/Resource/ValidateForVoiceResource.php | 11 +++++++---- src/Resource/VoiceResource.php | 2 +- 16 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/Resource/AnalyticsResource.php b/src/Resource/AnalyticsResource.php index 3783a3f..73053c2 100644 --- a/src/Resource/AnalyticsResource.php +++ b/src/Resource/AnalyticsResource.php @@ -1,4 +1,4 @@ -client->get('balance'); return new Balance($res); } diff --git a/src/Resource/ContactsResource.php b/src/Resource/ContactsResource.php index 3a5fc0f..e7b13a4 100644 --- a/src/Resource/ContactsResource.php +++ b/src/Resource/ContactsResource.php @@ -1,4 +1,4 @@ -client = $client; +abstract class Resource +{ + public function __construct(protected BaseClient $client) + { } abstract public function validate($params): void; diff --git a/src/Resource/SmsResource.php b/src/Resource/SmsResource.php index 63e9c6e..d12eafc 100644 --- a/src/Resource/SmsResource.php +++ b/src/Resource/SmsResource.php @@ -1,4 +1,4 @@ -validate($params); $res = $this->client->post('validate_for_voice', $params->toArray()); @@ -26,7 +28,8 @@ public function post(ValidateForVoiceParams $params): ValidateForVoice { * @throws InvalidOptionalArgumentException * @throws InvalidRequiredArgumentException */ - public function validate($params): void { + public function validate($params): void + { (new ValidateForVoiceValidator($params))->validate(); } } diff --git a/src/Resource/VoiceResource.php b/src/Resource/VoiceResource.php index 3efdf21..1328517 100644 --- a/src/Resource/VoiceResource.php +++ b/src/Resource/VoiceResource.php @@ -1,4 +1,4 @@ - Date: Wed, 24 Apr 2024 13:54:25 +0200 Subject: [PATCH 20/54] use enums --- src/Constant/NetworkType.php | 31 +++++++++----------- src/Constant/PortingStatus.php | 17 +++++------ src/Constant/ReachableStatus.php | 19 ++++++------- src/Constant/RoamingStatus.php | 13 ++++----- src/Constant/StatusCode.php | 39 ++++++++++++-------------- src/Constant/StatusMessage.php | 25 ++++++++--------- src/Constant/SubaccountsAction.php | 7 ++--- src/Library/Reflectable.php | 13 --------- src/Library/Util.php | 6 ++-- src/Validator/SubaccountsValidator.php | 2 +- tests/Client/StatusTest.php | 2 +- 11 files changed, 71 insertions(+), 103 deletions(-) delete mode 100644 src/Library/Reflectable.php diff --git a/src/Constant/NetworkType.php b/src/Constant/NetworkType.php index 7e9f390..3d7b407 100644 --- a/src/Constant/NetworkType.php +++ b/src/Constant/NetworkType.php @@ -2,21 +2,18 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -class NetworkType { - use Reflectable; - - public const FixedLine = 'fixed_line'; - public const FixedLineOrMobile = 'fixed_line_or_mobile'; - public const Mobile = 'mobile'; - public const Pager = 'pager'; - public const PersonalNumber = 'personal_number'; - public const PremiumRate = 'premium_rate'; - public const SharedCost = 'shared_cost'; - public const TollFree = 'toll_free'; - public const Uan = 'uan'; - public const Unknown = 'unknown'; - public const Voicemail = 'voicemail'; - public const Voip = 'voip'; +enum NetworkType: string +{ + case FixedLine = 'fixed_line'; + case FixedLineOrMobile = 'fixed_line_or_mobile'; + case Mobile = 'mobile'; + case Pager = 'pager'; + case PersonalNumber = 'personal_number'; + case PremiumRate = 'premium_rate'; + case SharedCost = 'shared_cost'; + case TollFree = 'toll_free'; + case Uan = 'uan'; + case Unknown = 'unknown'; + case Voicemail = 'voicemail'; + case Voip = 'voip'; } diff --git a/src/Constant/PortingStatus.php b/src/Constant/PortingStatus.php index 45c541b..a67bace 100644 --- a/src/Constant/PortingStatus.php +++ b/src/Constant/PortingStatus.php @@ -2,14 +2,11 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -class PortingStatus { - use Reflectable; - - public const AssumedNotPorted = 'assumed_not_ported'; - public const AssumedPorted = 'assumed_ported'; - public const NotPorted = 'not_ported'; - public const Ported = 'ported'; - public const Unknown = 'unknown'; +enum PortingStatus: string +{ + case AssumedNotPorted = 'assumed_not_ported'; + case AssumedPorted = 'assumed_ported'; + case NotPorted = 'not_ported'; + case Ported = 'ported'; + case Unknown = 'unknown'; } diff --git a/src/Constant/ReachableStatus.php b/src/Constant/ReachableStatus.php index 94e9536..f22a70d 100644 --- a/src/Constant/ReachableStatus.php +++ b/src/Constant/ReachableStatus.php @@ -2,15 +2,12 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -class ReachableStatus { - use Reflectable; - - public const Absent = 'absent'; - public const BadNumber = 'bad_number'; - public const Blacklisted = 'blacklisted'; - public const Reachable = 'reachable'; - public const Undeliverable = 'undeliverable'; - public const Unknown = 'unknown'; +enum ReachableStatus: string +{ + case Absent = 'absent'; + case BadNumber = 'bad_number'; + case Blacklisted = 'blacklisted'; + case Reachable = 'reachable'; + case Undeliverable = 'undeliverable'; + case Unknown = 'unknown'; } diff --git a/src/Constant/RoamingStatus.php b/src/Constant/RoamingStatus.php index 16ca418..fbde5ce 100644 --- a/src/Constant/RoamingStatus.php +++ b/src/Constant/RoamingStatus.php @@ -2,12 +2,9 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -class RoamingStatus { - use Reflectable; - - public const NotRoaming = 'not_roaming'; - public const Roaming = 'roaming'; - public const Unknown = 'unknown'; +enum RoamingStatus: string +{ + case NotRoaming = 'not_roaming'; + case Roaming = 'roaming'; + case Unknown = 'unknown'; } diff --git a/src/Constant/StatusCode.php b/src/Constant/StatusCode.php index ca362dd..2bc03f6 100644 --- a/src/Constant/StatusCode.php +++ b/src/Constant/StatusCode.php @@ -2,25 +2,22 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -class StatusCode { - use Reflectable; - - public const SmsCarrierTemporarilyUnavailable = 11; - public const Sent = 100; - public const SentPartially = 101; - public const FromIsInvalid = 201; - public const ToIsInvalid = 202; - public const ToIsMissing = 301; - public const TextIsMissing = 305; - public const TextIsTooLong = 401; - public const ReloadLockPrevention = 402; - public const DailyNumberLimitReached = 403; - public const NotEnoughCredits = 500; - public const CarrierDeliveryFailed = 600; - public const UnknownError = 700; - public const AuthError = 900; - public const HttpApiIsDisabled = 902; - public const InvalidServerIp = 903; +enum StatusCode: int +{ + case SmsCarrierTemporarilyUnavailable = 11; + case Sent = 100; + case SentPartially = 101; + case FromIsInvalid = 201; + case ToIsInvalid = 202; + case ToIsMissing = 301; + case TextIsMissing = 305; + case TextIsTooLong = 401; + case ReloadLockPrevention = 402; + case DailyNumberLimitReached = 403; + case NotEnoughCredits = 500; + case CarrierDeliveryFailed = 600; + case UnknownError = 700; + case AuthError = 900; + case HttpApiIsDisabled = 902; + case InvalidServerIp = 903; } diff --git a/src/Constant/StatusMessage.php b/src/Constant/StatusMessage.php index a182755..18df926 100644 --- a/src/Constant/StatusMessage.php +++ b/src/Constant/StatusMessage.php @@ -2,18 +2,15 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -class StatusMessage { - use Reflectable; - - public const Accepted = 'ACCEPTED'; - public const Buffered = 'BUFFERED'; - public const Delivered = 'DELIVERED'; - public const Expired = 'EXPIRED'; - public const Failed = 'FAILED'; - public const NotDelivered = 'NOTDELIVERED'; - public const Rejected = 'REJECTED'; - public const Transmitted = 'TRANSMITTED'; - public const Unknown = 'UNKNOWN'; +enum StatusMessage: string +{ + case Accepted = 'ACCEPTED'; + case Buffered = 'BUFFERED'; + case Delivered = 'DELIVERED'; + case Expired = 'EXPIRED'; + case Failed = 'FAILED'; + case NotDelivered = 'NOTDELIVERED'; + case Rejected = 'REJECTED'; + case Transmitted = 'TRANSMITTED'; + case Unknown = 'UNKNOWN'; } diff --git a/src/Constant/SubaccountsAction.php b/src/Constant/SubaccountsAction.php index 58a0c5c..9cc69ea 100644 --- a/src/Constant/SubaccountsAction.php +++ b/src/Constant/SubaccountsAction.php @@ -2,11 +2,8 @@ namespace Seven\Api\Constant; -use Seven\Api\Library\Reflectable; - -final class SubaccountsAction { - use Reflectable; - +enum SubaccountsAction: string +{ public const CREATE = 'create'; public const DELETE = 'delete'; public const READ = 'read'; diff --git a/src/Library/Reflectable.php b/src/Library/Reflectable.php deleted file mode 100644 index 6b70690..0000000 --- a/src/Library/Reflectable.php +++ /dev/null @@ -1,13 +0,0 @@ -getConstants(); - return array_values($constants); - } -} diff --git a/src/Library/Util.php b/src/Library/Util.php index d92d786..f1d95f1 100755 --- a/src/Library/Util.php +++ b/src/Library/Util.php @@ -2,8 +2,10 @@ namespace Seven\Api\Library; -class Util { - public static function isValidUrl(string $url): bool { +abstract class Util +{ + public static function isValidUrl(string $url): bool + { return false !== filter_var($url, FILTER_VALIDATE_URL); } } diff --git a/src/Validator/SubaccountsValidator.php b/src/Validator/SubaccountsValidator.php index 482fbbc..d091321 100644 --- a/src/Validator/SubaccountsValidator.php +++ b/src/Validator/SubaccountsValidator.php @@ -44,7 +44,7 @@ public function validate(): void /** @throws InvalidRequiredArgumentException */ public function action(): void { - if (!in_array($this->params->getAction(), SubaccountsAction::values())) + if (!in_array($this->params->getAction(), array_column(SubaccountsAction::cases(), 'value'))) throw new InvalidRequiredArgumentException('Parameter "number" is missing.'); } diff --git a/tests/Client/StatusTest.php b/tests/Client/StatusTest.php index f670877..61117c0 100755 --- a/tests/Client/StatusTest.php +++ b/tests/Client/StatusTest.php @@ -25,7 +25,7 @@ public function testSuccess(): void $statusTime = $obj->getStatusTime(); if ($status) { - $this->assertContains($status, StatusMessage::values()); + $this->assertContains($status, array_column(StatusMessage::cases(), 'value')); $this->assertNotNull($statusTime); } else $this->assertNull($statusTime); } From 8fe4671b0ec3087fb86ba84d95b77cd4fa6cd08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Wed, 24 Apr 2024 14:12:01 +0200 Subject: [PATCH 21/54] merge clients --- README.md | 16 +- src/BaseClient.php | 117 -------------- src/Client.php | 162 +++++++++++++------- src/Resource/Resource.php | 4 +- tests/{Client => }/AnalyticsTest.php | 10 +- tests/BalanceTest.php | 13 ++ tests/{Client => }/BaseTest.php | 7 +- tests/Client/BalanceTest.php | 11 -- tests/Client/ClientTest.php | 20 --- tests/ClientTest.php | 23 +++ tests/{Client => }/ContactsTest.php | 12 +- tests/{Client => }/GroupsTest.php | 12 +- tests/{Client => }/HooksTest.php | 12 +- tests/{Client => }/JournalTest.php | 10 +- tests/{Client => }/LookupTest.php | 14 +- tests/{Client => }/NumbersTest.php | 14 +- tests/{Client => }/PricingTest.php | 6 +- tests/{Client => }/RcsTest.php | 10 +- tests/Resources.php | 58 +++++++ tests/{Client => }/SmsTest.php | 12 +- tests/{Client => }/StatusTest.php | 8 +- tests/{Client => }/SubaccountsTest.php | 14 +- tests/{Client => }/ValidateForVoiceTest.php | 15 +- tests/{Client => }/VoiceTest.php | 6 +- 24 files changed, 302 insertions(+), 284 deletions(-) delete mode 100644 src/BaseClient.php mode change 100755 => 100644 src/Client.php rename tests/{Client => }/AnalyticsTest.php (86%) mode change 100755 => 100644 create mode 100644 tests/BalanceTest.php rename tests/{Client => }/BaseTest.php (87%) mode change 100755 => 100644 delete mode 100755 tests/Client/BalanceTest.php delete mode 100755 tests/Client/ClientTest.php create mode 100644 tests/ClientTest.php rename tests/{Client => }/ContactsTest.php (84%) mode change 100755 => 100644 rename tests/{Client => }/GroupsTest.php (71%) rename tests/{Client => }/HooksTest.php (84%) mode change 100755 => 100644 rename tests/{Client => }/JournalTest.php (92%) mode change 100755 => 100644 rename tests/{Client => }/LookupTest.php (87%) mode change 100755 => 100644 rename tests/{Client => }/NumbersTest.php (78%) rename tests/{Client => }/PricingTest.php (81%) mode change 100755 => 100644 rename tests/{Client => }/RcsTest.php (81%) create mode 100644 tests/Resources.php rename tests/{Client => }/SmsTest.php (84%) mode change 100755 => 100644 rename tests/{Client => }/StatusTest.php (83%) mode change 100755 => 100644 rename tests/{Client => }/SubaccountsTest.php (86%) rename tests/{Client => }/ValidateForVoiceTest.php (71%) mode change 100755 => 100644 rename tests/{Client => }/VoiceTest.php (88%) mode change 100755 => 100644 diff --git a/README.md b/README.md index 1246bc8..28960d7 100755 --- a/README.md +++ b/README.md @@ -19,9 +19,13 @@ if you don't use Composer. ```php use Seven\Api\Client; use Seven\Api\Params\SmsParams; +use Seven\Api\Resource\SmsResource; + $client = new Client('MY_VERY_SECRET_API_KEY!'); -$params = new SmsParams('HI2U', '+4901234567890'); -$client->sms($params); +$smsResource = new SmsResource($client); +$smsParams = new SmsParams('HI2U', '+4901234567890'); +$res = $smsResource->dispatch($smsParams); +var_dump($res); ``` See [docs](/docs) for more details. @@ -31,7 +35,13 @@ See [docs](/docs) for more details. Some basic tests are implemented. You can run them like this: ```shell script -SEVEN_API_KEY= SEVEN_API_KEY_SANDBOX= php vendor/bin/phpunit tests/Client +SEVEN_API_KEY= php vendor/bin/phpunit tests +``` + +or + +```shell script +SEVEN_API_KEY_SANDBOX= php vendor/bin/phpunit tests ``` Make sure to fill in the values. diff --git a/src/BaseClient.php b/src/BaseClient.php deleted file mode 100644 index b9b1a8e..0000000 --- a/src/BaseClient.php +++ /dev/null @@ -1,117 +0,0 @@ -headers = [ - 'Accept: application/json', - 'SentWith: ' . $this->sentWith, - 'X-Api-Key: ' . $this->apiKey, - ]; - } - - public function getApiKey(): string - { - return $this->apiKey; - } - - public function getSentWith(): string - { - return $this->sentWith; - } - - public function delete(string $path, array $options = [], array $headers = []): mixed - { - return $this->request($path, HttpMethod::DELETE, $options, $headers); - } - - protected function request(string $path, HttpMethod $method, array $payload = [], array $headers = []): mixed - { - $url = self::BASE_URI . '/' . $path; - $params = http_build_query($payload); - if (HttpMethod::GET === $method) $url .= str_ends_with($url, '?') ? '' : '?' . $params; - - $ch = curl_init($url); - - if (HttpMethod::POST === $method) { - curl_setopt($ch, CURLOPT_POSTFIELDS, $params); - curl_setopt($ch, CURLOPT_POST, true); - } elseif (HttpMethod::PATCH === $method) { - curl_setopt($ch, CURLOPT_POSTFIELDS, $params); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::PATCH->name); - } elseif (HttpMethod::DELETE === $method) { - curl_setopt($ch, CURLOPT_POSTFIELDS, $params); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::DELETE->name); - } - - if ($this->signingSecret) { - $nonce = bin2hex(random_bytes(16)); - $timestamp = time(); - $toSign = $timestamp . PHP_EOL . - $nonce . PHP_EOL . - $method->name . PHP_EOL . - $url . PHP_EOL . - md5($params); - $hash = hash_hmac('sha256', $toSign, $this->signingSecret); - $this->headers[] = 'X-Nonce: ' . $nonce; - $this->headers[] = 'X-Signature: ' . $hash; - $this->headers[] = 'X-Timestamp: ' . $timestamp; - } - - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_HTTPHEADER, array_unique([...$this->headers, ...$headers])); - - $res = curl_exec($ch); - - if (false === $res) throw new UnexpectedValueException(curl_error($ch)); - - curl_close($ch); - - try { - $res = json_decode($res, false, 512, JSON_THROW_ON_ERROR); - } catch (Exception) { - } - - return $res; - } - - public function patch(string $path, array $payload = [], array $headers = []): mixed - { - return $this->request($path, HttpMethod::PATCH, $payload, $headers); - } - - public function post(string $path, array $payload = [], array $headers = []): mixed - { - return $this->request($path, HttpMethod::POST, $payload, $headers); - } - - public function get(string $path, array $params = [], array $headers = []): mixed - { - return $this->request($path, HttpMethod::GET, $params, $headers); - } -} diff --git a/src/Client.php b/src/Client.php old mode 100755 new mode 100644 index 4f86e40..ce27f35 --- a/src/Client.php +++ b/src/Client.php @@ -2,58 +2,116 @@ namespace Seven\Api; -use Seven\Api\Resource\AnalyticsResource; -use Seven\Api\Resource\BalanceResource; -use Seven\Api\Resource\ContactsResource; -use Seven\Api\Resource\GroupsResource; -use Seven\Api\Resource\HooksResource; -use Seven\Api\Resource\JournalResource; -use Seven\Api\Resource\LookupResource; -use Seven\Api\Resource\NumbersResource; -use Seven\Api\Resource\PricingResource; -use Seven\Api\Resource\RcsResource; -use Seven\Api\Resource\SmsResource; -use Seven\Api\Resource\StatusResource; -use Seven\Api\Resource\SubaccountsResource; -use Seven\Api\Resource\ValidateForVoiceResource; -use Seven\Api\Resource\VoiceResource; - -class Client extends BaseClient +use Exception; +use InvalidArgumentException; +use Seven\Api\Constant\HttpMethod; +use UnexpectedValueException; + +class Client { - public AnalyticsResource $analytics; - public BalanceResource $balance; - public ContactsResource $contacts; - public GroupsResource $groups; - public HooksResource $hooks; - public JournalResource $journal; - public LookupResource $lookup; - public NumbersResource $numbers; - public PricingResource $pricing; - public RcsResource $rcs; - public SmsResource $sms; - public StatusResource $status; - public SubaccountsResource $subaccounts; - public ValidateForVoiceResource $validateForVoice; - public VoiceResource $voice; - - public function __construct(string $apiKey, string $sentWith = 'php-api', string $signingSecret = null) - { - parent::__construct($apiKey, $sentWith, $signingSecret); - - $this->analytics = new AnalyticsResource($this); - $this->balance = new BalanceResource($this); - $this->contacts = new ContactsResource($this); - $this->groups = new GroupsResource($this); - $this->hooks = new HooksResource($this); - $this->journal = new JournalResource($this); - $this->lookup = new LookupResource($this); - $this->numbers = new NumbersResource($this); - $this->pricing = new PricingResource($this); - $this->rcs = new RcsResource($this); - $this->sms = new SmsResource($this); - $this->status = new StatusResource($this); - $this->subaccounts = new SubaccountsResource($this); - $this->validateForVoice = new ValidateForVoiceResource($this); - $this->voice = new VoiceResource($this); + public const BASE_URI = 'https://gateway.seven.io/api'; + /** @var string[] $headers */ + protected array $headers; + + /** + * @throws Exception + */ + public function __construct( + protected string $apiKey, + protected string $sentWith = 'php-api', + protected ?string $signingSecret = null, + ) + { + if ('' === $apiKey) throw new InvalidArgumentException( + 'Invalid required constructor argument apiKey: ' . $apiKey); + + if ('' === $sentWith) throw new InvalidArgumentException( + 'Invalid required constructor argument sentWith: ' . $sentWith); + + $this->headers = [ + 'Accept: application/json', + 'SentWith: ' . $this->sentWith, + 'X-Api-Key: ' . $this->apiKey, + ]; + } + + public function getApiKey(): string + { + return $this->apiKey; + } + + public function getSentWith(): string + { + return $this->sentWith; + } + + public function delete(string $path, array $options = [], array $headers = []): mixed + { + return $this->request($path, HttpMethod::DELETE, $options, $headers); + } + + protected function request(string $path, HttpMethod $method, array $payload = [], array $headers = []): mixed + { + $url = self::BASE_URI . '/' . $path; + $params = http_build_query($payload); + if (HttpMethod::GET === $method) $url .= str_ends_with($url, '?') ? '' : '?' . $params; + + $ch = curl_init($url); + + if (HttpMethod::POST === $method) { + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + curl_setopt($ch, CURLOPT_POST, true); + } elseif (HttpMethod::PATCH === $method) { + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::PATCH->name); + } elseif (HttpMethod::DELETE === $method) { + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, HttpMethod::DELETE->name); + } + + if ($this->signingSecret) { + $nonce = bin2hex(random_bytes(16)); + $timestamp = time(); + $toSign = $timestamp . PHP_EOL . + $nonce . PHP_EOL . + $method->name . PHP_EOL . + $url . PHP_EOL . + md5($params); + $hash = hash_hmac('sha256', $toSign, $this->signingSecret); + $this->headers[] = 'X-Nonce: ' . $nonce; + $this->headers[] = 'X-Signature: ' . $hash; + $this->headers[] = 'X-Timestamp: ' . $timestamp; + } + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HTTPHEADER, array_unique([...$this->headers, ...$headers])); + + $res = curl_exec($ch); + + if (false === $res) throw new UnexpectedValueException(curl_error($ch)); + + curl_close($ch); + + try { + $res = json_decode($res, false, 512, JSON_THROW_ON_ERROR); + } catch (Exception) { + } + + return $res; + } + + public function patch(string $path, array $payload = [], array $headers = []): mixed + { + return $this->request($path, HttpMethod::PATCH, $payload, $headers); + } + + public function post(string $path, array $payload = [], array $headers = []): mixed + { + return $this->request($path, HttpMethod::POST, $payload, $headers); + } + + public function get(string $path, array $params = [], array $headers = []): mixed + { + return $this->request($path, HttpMethod::GET, $params, $headers); } } diff --git a/src/Resource/Resource.php b/src/Resource/Resource.php index 9d2a43e..3ef961b 100644 --- a/src/Resource/Resource.php +++ b/src/Resource/Resource.php @@ -2,11 +2,11 @@ namespace Seven\Api\Resource; -use Seven\Api\BaseClient; +use Seven\Api\Client; abstract class Resource { - public function __construct(protected BaseClient $client) + public function __construct(protected Client $client) { } diff --git a/tests/Client/AnalyticsTest.php b/tests/AnalyticsTest.php old mode 100755 new mode 100644 similarity index 86% rename from tests/Client/AnalyticsTest.php rename to tests/AnalyticsTest.php index 74e0e6f..aa0d4db --- a/tests/Client/AnalyticsTest.php +++ b/tests/AnalyticsTest.php @@ -1,6 +1,6 @@ client->analytics->byDate(); + $res = $this->resources->analytics->byDate(); $this->assertCount(31, $res); @@ -58,7 +58,7 @@ private function assertEach(AbstractAnalytic $a): bool public function testAnalyticsGroupByLabel(): void { - foreach ($this->assertResponse($this->client->analytics->byLabel()) as $a) { + foreach ($this->assertResponse($this->resources->analytics->byLabel()) as $a) { /** @var AnalyticByLabel $a */ $this->assertIsString($a->getLabel()); } @@ -66,12 +66,12 @@ public function testAnalyticsGroupByLabel(): void public function testAnalyticsGroupByCountry(): void { - $this->assertResponse($this->client->analytics->byCountry()); + $this->assertResponse($this->resources->analytics->byCountry()); } public function testAnalyticsGroupBySubaccount(): void { - foreach ($this->assertResponse($this->client->analytics->bySubaccount()) as $a) { + foreach ($this->assertResponse($this->resources->analytics->bySubaccount()) as $a) { /** @var AnalyticBySubaccount $a */ $account = $a->getAccount(); $this->assertEach($a); diff --git a/tests/BalanceTest.php b/tests/BalanceTest.php new file mode 100644 index 0000000..e61f865 --- /dev/null +++ b/tests/BalanceTest.php @@ -0,0 +1,13 @@ +resources->balance->get(); + + $this->assertNotEmpty($res->getCurrency()); + } +} diff --git a/tests/Client/BaseTest.php b/tests/BaseTest.php old mode 100755 new mode 100644 similarity index 87% rename from tests/Client/BaseTest.php rename to tests/BaseTest.php index a047e1b..eb8f44e --- a/tests/Client/BaseTest.php +++ b/tests/BaseTest.php @@ -1,6 +1,6 @@ client = new Client($apiKey, 'php-api-test', getenv('SEVEN_SIGNING_SECRET')); + $client = new Client($apiKey, 'php-api-test', getenv('SEVEN_SIGNING_SECRET')); + $this->resources = new Resources($client); $this->isSandbox = $isSandbox; } diff --git a/tests/Client/BalanceTest.php b/tests/Client/BalanceTest.php deleted file mode 100755 index bbcd203..0000000 --- a/tests/Client/BalanceTest.php +++ /dev/null @@ -1,11 +0,0 @@ -client->balance->get(); - - $this->assertNotEmpty($res->getCurrency()); - } -} diff --git a/tests/Client/ClientTest.php b/tests/Client/ClientTest.php deleted file mode 100755 index 6cf63f1..0000000 --- a/tests/Client/ClientTest.php +++ /dev/null @@ -1,20 +0,0 @@ -client->getApiKey())); - - self::assertGreaterThan(0, strlen($this->client->getSentWith())); - } - - public function testClientWithBadCredentials(): void { - $this->expectException(InvalidArgumentException::class); - - new Client('', ''); - } -} diff --git a/tests/ClientTest.php b/tests/ClientTest.php new file mode 100644 index 0000000..c9d3e13 --- /dev/null +++ b/tests/ClientTest.php @@ -0,0 +1,23 @@ +resources->client->getApiKey())); + + self::assertGreaterThan(0, strlen($this->resources->client->getSentWith())); + } + + public function testClientWithBadCredentials(): void + { + $this->expectException(InvalidArgumentException::class); + + new Client('', ''); + } +} diff --git a/tests/Client/ContactsTest.php b/tests/ContactsTest.php old mode 100755 new mode 100644 similarity index 84% rename from tests/Client/ContactsTest.php rename to tests/ContactsTest.php index 84ab5e0..07e3dac --- a/tests/Client/ContactsTest.php +++ b/tests/ContactsTest.php @@ -1,6 +1,6 @@ setNotes('CPaaS') ->setPostalCode('24103') ); - $created = $this->client->contacts->create($toCreate); + $created = $this->resources->contacts->create($toCreate); $this->assertEquals($toCreate->getProperties(), $created->getProperties()); - $contact = $this->client->contacts->get($created->getId()); + $contact = $this->resources->contacts->get($created->getId()); $this->assertEquals($created->getProperties(), $contact->getProperties()); @@ -43,7 +43,7 @@ public function testAll(): void ->setSearch('') ->setOrderBy('') ->setOrderDirection(OrderDirection::Ascending); - $list = $this->client->contacts->list($listParams); + $list = $this->resources->contacts->list($listParams); $this->assertEquals($listParams->getLimit(), $list->getPagingMetadata()->getLimit()); $this->assertEquals($listParams->getOffset(), $list->getPagingMetadata()->getOffset()); $match = array_filter($list->getData(), fn($entry) => $entry->getId() === $created->getId()); @@ -51,9 +51,9 @@ public function testAll(): void $toUpdate = clone $contact; $toUpdate->getProperties()->setNotes('New Notes'); - $updated = $this->client->contacts->update($toUpdate); + $updated = $this->resources->contacts->update($toUpdate); $this->assertNotEquals($created->getProperties()->getNotes(), $updated->getProperties()->getNotes()); - $this->client->contacts->delete($created->getId()); + $this->resources->contacts->delete($created->getId()); } } diff --git a/tests/Client/GroupsTest.php b/tests/GroupsTest.php similarity index 71% rename from tests/Client/GroupsTest.php rename to tests/GroupsTest.php index 5d22d8e..3d51352 100644 --- a/tests/Client/GroupsTest.php +++ b/tests/GroupsTest.php @@ -1,6 +1,6 @@ client->groups->create($name); + $created = $this->resources->groups->create($name); $this->assertEquals($name, $created->getName()); - $group = $this->client->groups->get($created->getId()); + $group = $this->resources->groups->get($created->getId()); $this->assertEquals($created, $group); $listParams = new ListParams(); $listParams->setLimit(77); $listParams->setOffset(0); - $list = $this->client->groups->list($listParams); + $list = $this->resources->groups->list($listParams); //$this->assertEquals($listParams->getLimit(), $list->getPagingMetadata()->getLimit()); $this->assertEquals($listParams->getOffset(), $list->getPagingMetadata()->getOffset()); $match = array_filter($list->getData(), fn($entry) => $entry->getId() === $created->getId()); $this->assertCount(1, $match); $newName = 'PHP Test Group With a new Name'; - $updated = $this->client->groups->update($created->getId(), $newName); + $updated = $this->resources->groups->update($created->getId(), $newName); $this->assertNotEquals($created->getName(), $updated->getName()); - $deleted = $this->client->groups->delete($created->getId()); + $deleted = $this->resources->groups->delete($created->getId()); $this->assertTrue($deleted->getSuccess()); } } diff --git a/tests/Client/HooksTest.php b/tests/HooksTest.php old mode 100755 new mode 100644 similarity index 84% rename from tests/Client/HooksTest.php rename to tests/HooksTest.php index 9fd95bd..b3e8e8a --- a/tests/Client/HooksTest.php +++ b/tests/HooksTest.php @@ -1,6 +1,6 @@ client->hooks->read(); + $res = $this->resources->hooks->read(); $this->assertIsBool($res->isSuccess()); $this->assertIsArray($res->getHooks()); @@ -19,7 +19,7 @@ public function testGetHooks(): void if (!count($res->getHooks())) { $this->testSubscribeHook(false); - $res = $this->client->hooks->read(); + $res = $this->resources->hooks->read(); } $this->assertArrayHasKey(0, $res->getHooks()); @@ -35,7 +35,7 @@ public function testGetHooks(): void public function testSubscribeHook(bool $delete = true): ?int { $params = new SubscribeParams(self::createRandomURL(), HooksEventType::SMS_INBOUND); - $res = $this->client->hooks->subscribe($params); + $res = $this->resources->hooks->subscribe($params); $id = $res->getId(); $isSuccess = $res->isSuccess(); @@ -54,7 +54,7 @@ public function testSubscribeHook(bool $delete = true): ?int public function testUnsubscribeHook(?int $id = null): void { if (!$id) { - $res = $this->client->hooks->read(); + $res = $this->resources->hooks->read(); $hooks = $res->getHooks(); $id = count($hooks) @@ -62,7 +62,7 @@ public function testUnsubscribeHook(?int $id = null): void : $this->testSubscribeHook(false); } - $res = $this->client->hooks->unsubscribe($id); + $res = $this->resources->hooks->unsubscribe($id); $this->assertTrue($res->isSuccess()); } } diff --git a/tests/Client/JournalTest.php b/tests/JournalTest.php old mode 100755 new mode 100644 similarity index 92% rename from tests/Client/JournalTest.php rename to tests/JournalTest.php index 1dbcaed..58eb116 --- a/tests/Client/JournalTest.php +++ b/tests/JournalTest.php @@ -1,6 +1,6 @@ client->journal->inbound(); + $arr = $this->resources->journal->inbound(); $this->request($arr); } @@ -36,7 +36,7 @@ private function request(array $journals, ?callable $functionHandler = null): vo public function testJournalOutbound(): void { - $arr = $this->client->journal->outbound(); + $arr = $this->resources->journal->outbound(); $callable = function (JournalOutbound $j) { $this->assertIsString($j->getConnection()); $this->assertIsNullOrLengthyString($j->getDlr()); @@ -53,7 +53,7 @@ public function testJournalOutbound(): void public function testJournalVoice(): void { - $arr = $this->client->journal->voice(); + $arr = $this->resources->journal->voice(); $callable = function (JournalVoice $j) { $this->assertIsNullOrLengthyString($j->getDuration()); $this->assertIsNullOrString($j->getError()); @@ -66,7 +66,7 @@ public function testJournalVoice(): void public function testJournalReplies(): void { - $arr = $this->client->journal->replies(); + $arr = $this->resources->journal->replies(); $this->request($arr); } diff --git a/tests/Client/LookupTest.php b/tests/LookupTest.php old mode 100755 new mode 100644 similarity index 87% rename from tests/Client/LookupTest.php rename to tests/LookupTest.php index a742e2d..b8c3959 --- a/tests/Client/LookupTest.php +++ b/tests/LookupTest.php @@ -1,7 +1,7 @@ client->lookup->rcsCapabilities('491716992343'); + $res = $this->resources->lookup->rcsCapabilities('491716992343'); $this->assertCount(1, $res); } public function testFormat(): void { - $res = $this->client->lookup->format('491716992343'); + $res = $this->resources->lookup->format('491716992343'); $this->assertCount(1, $res); } public function testFormatMulti(): void { - $res = $this->client->lookup->format('491716992343', '49179999999'); + $res = $this->resources->lookup->format('491716992343', '49179999999'); $this->assertCount(2, $res); } public function testMnpMulti(): void { - $arr = $this->client->lookup->mnp('491716992343'); + $arr = $this->resources->lookup->mnp('491716992343'); $this->assertCount(1, $arr); foreach ($arr as $item) { @@ -47,7 +47,7 @@ public function testMnpMulti(): void public function testHlr(): void { - $arr = $this->client->lookup->hlr('491716992343'); + $arr = $this->resources->lookup->hlr('491716992343'); $this->assertCount(1, $arr); foreach ($arr as $item) { @@ -82,7 +82,7 @@ private function assertCarrier(Carrier $c): void public function testCnam(): void { - $arr = $this->client->lookup->cnam('491716992343'); + $arr = $this->resources->lookup->cnam('491716992343'); $this->assertCount(1, $arr); foreach ($arr as $item) { diff --git a/tests/Client/NumbersTest.php b/tests/NumbersTest.php similarity index 78% rename from tests/Client/NumbersTest.php rename to tests/NumbersTest.php index 2d71ddc..79e5140 100644 --- a/tests/Client/NumbersTest.php +++ b/tests/NumbersTest.php @@ -1,6 +1,6 @@ setCountry('DE') ->setFeaturesApplicationToPersonSms(true); - $offers = $this->client->numbers->listAvailable($availableParams)->getAvailableNumbers(); + $offers = $this->resources->numbers->listAvailable($availableParams)->getAvailableNumbers(); $this->assertNotEmpty($offers); foreach ($offers as $offer) { @@ -24,7 +24,7 @@ public function testAll(): void $firstOffer = $offers[0]; $orderParams = (new OrderParams($firstOffer->getNumber()))->setPaymentInterval(PaymentInterval::MONTHLY); - $order = $this->client->numbers->order($orderParams); + $order = $this->resources->numbers->order($orderParams); $this->assertNull($order->getError()); $this->assertTrue($order->isSuccess()); @@ -32,18 +32,18 @@ public function testAll(): void ->setEmailForward(['php_test@seven.dev']) ->setFriendlyName('Friendly Name') ->setSmsForward(['491716992343']); - $updated = $this->client->numbers->update($updateParams); + $updated = $this->resources->numbers->update($updateParams); $this->assertEquals($updateParams->getFriendlyName(), $updated->getFriendlyName()); $this->assertEquals($updateParams->getEmailForward(), $updated->getForwardInboundSms()->getEmail()->getAddresses()); $this->assertEquals($updateParams->getSmsForward(), $updated->getForwardInboundSms()->getSms()->getNumbers()); - $number = $this->client->numbers->get($firstOffer->getNumber()); + $number = $this->resources->numbers->get($firstOffer->getNumber()); $this->assertEquals($orderParams->getPaymentInterval(), $number->getBilling()->getPaymentInterval()); - $actives = $this->client->numbers->listActive(); + $actives = $this->resources->numbers->listActive(); $this->assertNotEmpty($actives); - $deleted = $this->client->numbers->delete($firstOffer->getNumber()); + $deleted = $this->resources->numbers->delete($firstOffer->getNumber()); $this->assertTrue($deleted->isSuccess()); } } diff --git a/tests/Client/PricingTest.php b/tests/PricingTest.php old mode 100755 new mode 100644 similarity index 81% rename from tests/Client/PricingTest.php rename to tests/PricingTest.php index b76f630..38c3d6b --- a/tests/Client/PricingTest.php +++ b/tests/PricingTest.php @@ -1,12 +1,12 @@ client->pricing->get('de'); + $res = $this->resources->pricing->get('de'); self::assertEquals(1, $res->getCountCountries()); self::assertGreaterThan(0, $res->getCountNetworks()); @@ -15,7 +15,7 @@ public function testGermany(): void public function testJson(): void { - $res = $this->client->pricing->get(); + $res = $this->resources->pricing->get(); self::assertGreaterThan(0, $res->getCountCountries()); self::assertGreaterThan(0, $res->getCountNetworks()); diff --git a/tests/Client/RcsTest.php b/tests/RcsTest.php similarity index 81% rename from tests/Client/RcsTest.php rename to tests/RcsTest.php index 4a5b453..f28ab71 100644 --- a/tests/Client/RcsTest.php +++ b/tests/RcsTest.php @@ -1,6 +1,6 @@ client->rcs->dispatch($params); + $res = $this->resources->rcs->dispatch($params); $this->assertCount(1, $res->getMessages()); $msg = $res->getMessages()[0]; @@ -25,18 +25,18 @@ public function testDelete(): void { $params = (new RcsParams('HI', '491716992343')) ->setDelay((new DateTime)->add(DateInterval::createFromDateString('1 day'))); - $rcs = $this->client->rcs->dispatch($params); + $rcs = $this->resources->rcs->dispatch($params); $this->assertNotEmpty($rcs->getMessages()); $msg = $rcs->getMessages()[0]; - $res = $this->client->rcs->delete($msg->getId()); + $res = $this->resources->rcs->delete($msg->getId()); $this->assertTrue($res->isSuccess()); } public function testEvent(): void { $params = new RcsEventParams('4915237035388', RcsEvent::IS_TYPING); - $res = $this->client->rcs->event($params); + $res = $this->resources->rcs->event($params); $this->assertTrue($res->isSuccess()); } diff --git a/tests/Resources.php b/tests/Resources.php new file mode 100644 index 0000000..4822f9a --- /dev/null +++ b/tests/Resources.php @@ -0,0 +1,58 @@ +analytics = new AnalyticsResource($client); + $this->balance = new BalanceResource($client); + $this->contacts = new ContactsResource($client); + $this->groups = new GroupsResource($client); + $this->hooks = new HooksResource($client); + $this->journal = new JournalResource($client); + $this->lookup = new LookupResource($client); + $this->numbers = new NumbersResource($client); + $this->pricing = new PricingResource($client); + $this->rcs = new RcsResource($client); + $this->sms = new SmsResource($client); + $this->status = new StatusResource($client); + $this->subaccounts = new SubaccountsResource($client); + $this->validateForVoice = new ValidateForVoiceResource($client); + $this->voice = new VoiceResource($client); + } +} diff --git a/tests/Client/SmsTest.php b/tests/SmsTest.php old mode 100755 new mode 100644 similarity index 84% rename from tests/Client/SmsTest.php rename to tests/SmsTest.php index 9fff366..2237cb6 --- a/tests/Client/SmsTest.php +++ b/tests/SmsTest.php @@ -1,6 +1,6 @@ setText('Müller'); $params->setDelay(new DateTime('2050-12-31')); - $res = $this->client->sms->dispatch($params); + $res = $this->resources->sms->dispatch($params); $msg = $res->getMessages()[0]; $this->assertEquals($params->getText(), $msg->getText()); $this->assertEquals(str_replace('+', '', $params->getTo()[0]), $msg->getRecipient()); - $this->client->sms->delete($msg->getId()); + $this->resources->sms->delete($msg->getId()); } public function testSmsFiles(): void @@ -39,7 +39,7 @@ public function testSmsFiles(): void $p->addFile($file); } - $json = $this->client->sms->dispatch($p->setText($text)); + $json = $this->resources->sms->dispatch($p->setText($text)); $msg = trim($json->getMessages()[0]->getText()); $links = (int)preg_match_all('#(https://svn.me/)#', $msg); @@ -51,11 +51,11 @@ public function testDelete(): void $params = (new SmsParams('HI2U! The UNIX time is ' . time() . '.', '491716992343')) ->addTo('4917987654321') ->setDelay(new DateTime('2050-12-31')); - $sms = $this->client->sms->dispatch($params); + $sms = $this->resources->sms->dispatch($params); $this->assertNotEmpty($sms->getMessages()); $msg = $sms->getMessages()[0]; - $res = $this->client->sms->delete($msg->getId()); + $res = $this->resources->sms->delete($msg->getId()); if ($res->isSuccess()) $this->assertSameSize($sms->getMessages(), $res->getDeleted()); else $this->assertNull($res->getDeleted()); } diff --git a/tests/Client/StatusTest.php b/tests/StatusTest.php old mode 100755 new mode 100644 similarity index 83% rename from tests/Client/StatusTest.php rename to tests/StatusTest.php index 61117c0..83b2d91 --- a/tests/Client/StatusTest.php +++ b/tests/StatusTest.php @@ -1,6 +1,6 @@ expectException(InvalidRequiredArgumentException::class); - $this->client->status->get(0); + $this->resources->status->get(0); } public function testSuccess(): void { $msgId = $this->getMessageId(); - $arr = $this->client->status->get($msgId, $msgId); + $arr = $this->resources->status->get($msgId, $msgId); $this->assertCount(2, $arr); foreach ($arr as $obj) { @@ -34,7 +34,7 @@ public function testSuccess(): void private function getMessageId(): int { $journalParams = (new JournalParams)->setLimit(1); - $outbounds = $this->client->journal->outbound($journalParams); + $outbounds = $this->resources->journal->outbound($journalParams); $outbound = $outbounds[0]; $msgId = $outbound->getId(); return (int)$msgId; diff --git a/tests/Client/SubaccountsTest.php b/tests/SubaccountsTest.php similarity index 86% rename from tests/Client/SubaccountsTest.php rename to tests/SubaccountsTest.php index 36882f8..adde2ee 100644 --- a/tests/Client/SubaccountsTest.php +++ b/tests/SubaccountsTest.php @@ -1,6 +1,6 @@ expectException(InvalidRequiredArgumentException::class); $params = new CreateSubaccountParams('', ''); - $this->client->subaccounts->create($params); + $this->resources->subaccounts->create($params); } public function testCreate(): Subaccount @@ -22,7 +22,7 @@ public function testCreate(): Subaccount 'Tommy Tester', sprintf('tommy.tester.%d@seven.dev', time()) ); - $res = $this->client->subaccounts->create($params); + $res = $this->resources->subaccounts->create($params); $this->assertTrue($res->isSuccess()); $this->assertNull($res->getError()); @@ -55,7 +55,7 @@ public function testTransferCredits(Subaccount $subaccount): Subaccount { $id = $subaccount->getId(); $amount = 12.34; - $res = $this->client->subaccounts->transferCredits($id, $amount); + $res = $this->resources->subaccounts->transferCredits($id, $amount); if ($res->isSuccess()) { $this->assertNull($res->getError()); @@ -74,7 +74,7 @@ public function testUpdate(Subaccount $subaccount): Subaccount $id = $subaccount->getId(); $amount = 12.34; $threshold = 123.456; - $res = $this->client->subaccounts->update($id, $amount, $threshold); + $res = $this->resources->subaccounts->update($id, $amount, $threshold); if ($res->isSuccess()) { $this->assertNull($res->getError()); @@ -90,7 +90,7 @@ public function testUpdate(Subaccount $subaccount): Subaccount */ public function testDelete(Subaccount $subaccount): void { - $res = $this->client->subaccounts->delete($subaccount->getId()); + $res = $this->resources->subaccounts->delete($subaccount->getId()); if ($res->isSuccess()) { $this->assertNull($res->getError()); @@ -101,7 +101,7 @@ public function testDelete(Subaccount $subaccount): void public function testRead(): void { - $res = $this->client->subaccounts->read(); + $res = $this->resources->subaccounts->read(); $this->assertIsArray($res); array_walk($res, [$this, 'assertSubaccount']); diff --git a/tests/Client/ValidateForVoiceTest.php b/tests/ValidateForVoiceTest.php old mode 100755 new mode 100644 similarity index 71% rename from tests/Client/ValidateForVoiceTest.php rename to tests/ValidateForVoiceTest.php index 68bd3f6..bb95b0a --- a/tests/Client/ValidateForVoiceTest.php +++ b/tests/ValidateForVoiceTest.php @@ -1,22 +1,25 @@ setCallback('https://seven.dev/callback/validate_for_voice'); - $res = $this->client->validateForVoice->post($params); + $res = $this->resources->validateForVoice->post($params); $this->assertTrue($res->isSuccess()); } - public function testValidateForVoiceFaulty(): void { + public function testValidateForVoiceFaulty(): void + { $faultySenderNumber = '0'; $params = new ValidateForVoiceParams($faultySenderNumber); - $voice = $this->client->validateForVoice->post($params); + $voice = $this->resources->validateForVoice->post($params); $this->assertTrue($voice->getError() === null || $voice->getError() !== ''); $this->assertTrue($voice->getFormattedOutput() == null || $voice->getFormattedOutput() !== ''); diff --git a/tests/Client/VoiceTest.php b/tests/VoiceTest.php old mode 100755 new mode 100644 similarity index 88% rename from tests/Client/VoiceTest.php rename to tests/VoiceTest.php index 4627e2f..54ef518 --- a/tests/Client/VoiceTest.php +++ b/tests/VoiceTest.php @@ -1,6 +1,6 @@ client->voice->call($this->params); + $res = $this->resources->voice->call($this->params); $this->assertVoice($res); } @@ -32,7 +32,7 @@ public function testVoiceSandbox(): void { $this->toSandbox(); $params = (clone $this->params); - $res = $this->client->voice->call($params); + $res = $this->resources->voice->call($params); $this->assertVoice($res, true); } From ed17977d16299d727f9cc4082979b742eb98a441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Matthies?= Date: Fri, 24 May 2024 08:42:09 +0200 Subject: [PATCH 22/54] fix request signing --- .idea/php.xml | 30 +- docs/classes/Seven-Api-BaseClient.html | 759 --- docs/classes/Seven-Api-Client.html | 1074 ++-- .../Seven-Api-Constant-AnalyticsGroupBy.html | 431 -- ...ven-Api-Constant-AnalyticsSubaccounts.html | 317 +- .../Seven-Api-Constant-ContactsAction.html | 395 -- .../Seven-Api-Constant-HooksAction.html | 395 -- .../Seven-Api-Constant-HooksEventType.html | 484 +- ...Seven-Api-Constant-HooksRequestMethod.html | 383 +- .../Seven-Api-Constant-HttpMethod.html | 362 +- .../Seven-Api-Constant-JournalConstants.html | 286 +- .../Seven-Api-Constant-JournalType.html | 431 -- .../Seven-Api-Constant-LookupType.html | 431 -- .../Seven-Api-Constant-NetworkType.html | 689 +- .../Seven-Api-Constant-PortingStatus.html | 430 +- .../Seven-Api-Constant-PricingConstants.html | 235 +- .../Seven-Api-Constant-ReachableStatus.html | 467 +- .../Seven-Api-Constant-RoamingStatus.html | 356 +- .../Seven-Api-Constant-SmsConstants.html | 311 +- .../Seven-Api-Constant-StatusCode.html | 865 ++- .../Seven-Api-Constant-StatusMessage.html | 578 +- .../Seven-Api-Constant-SubaccountsAction.html | 397 +- ...tion-InvalidOptionalArgumentException.html | 234 +- ...tion-InvalidRequiredArgumentException.html | 234 +- ...eption-UnexpectedApiResponseException.html | 234 +- ...-Api-Exception-UnknownOptionException.html | 234 +- .../Seven-Api-Library-Reflectable.html | 266 - docs/classes/Seven-Api-Library-Util.html | 219 +- .../Seven-Api-Params-AnalyticsParams.html | 455 +- .../Seven-Api-Params-ContactsParams.html | 1010 --- ...ven-Api-Params-CreateSubaccountParams.html | 1138 ---- .../classes/Seven-Api-Params-HooksParams.html | 1142 ---- .../Seven-Api-Params-JournalParams.html | 507 +- .../Seven-Api-Params-LookupParams.html | 754 --- .../Seven-Api-Params-ParamsInterface.html | 207 +- .../Seven-Api-Params-PricingParams.html | 413 +- docs/classes/Seven-Api-Params-SmsParams.html | 1046 +-- .../Seven-Api-Params-StatusParams.html | 360 +- .../Seven-Api-Params-SubaccountsParams.html | 1142 ---- ...ven-Api-Params-ValidateForVoiceParams.html | 346 +- .../classes/Seven-Api-Params-VoiceParams.html | 705 +- .../Seven-Api-Params-WriteContactParams.html | 987 --- .../Seven-Api-Resource-AnalyticsResource.html | 407 +- .../Seven-Api-Resource-BalanceResource.html | 283 +- .../Seven-Api-Resource-ContactsResource.html | 502 +- .../Seven-Api-Resource-HooksResource.html | 394 +- .../Seven-Api-Resource-JournalResource.html | 412 +- .../Seven-Api-Resource-LookupResource.html | 556 +- .../Seven-Api-Resource-PricingResource.html | 320 +- docs/classes/Seven-Api-Resource-Resource.html | 267 +- .../Seven-Api-Resource-SmsResource.html | 308 +- .../Seven-Api-Resource-StatusResource.html | 285 +- ...even-Api-Resource-SubaccountsResource.html | 419 +- ...Api-Resource-ValidateForVoiceResource.html | 287 +- .../Seven-Api-Resource-VoiceResource.html | 315 +- ...i-Response-Analytics-AbstractAnalytic.html | 379 +- ...-Response-Analytics-AnalyticByCountry.html | 402 +- ...Api-Response-Analytics-AnalyticByDate.html | 402 +- ...pi-Response-Analytics-AnalyticByLabel.html | 402 +- ...sponse-Analytics-AnalyticBySubaccount.html | 402 +- docs/classes/Seven-Api-Response-Balance.html | 277 +- .../Seven-Api-Response-Contacts-Contact.html | 1014 ++- ...n-Api-Response-Contacts-ContactCreate.html | 277 +- ...n-Api-Response-Contacts-ContactDelete.html | 252 +- ...ven-Api-Response-Contacts-ContactEdit.html | 252 +- .../Seven-Api-Response-Hooks-Hook.html | 522 +- ...even-Api-Response-Hooks-HookSubscribe.html | 277 +- ...en-Api-Response-Hooks-HookUnsubscribe.html | 252 +- .../Seven-Api-Response-Hooks-Hooks.html | 275 +- ...even-Api-Response-Journal-JournalBase.html | 379 +- ...n-Api-Response-Journal-JournalInbound.html | 377 +- ...-Api-Response-Journal-JournalOutbound.html | 577 +- ...ven-Api-Response-Journal-JournalReply.html | 377 +- ...ven-Api-Response-Journal-JournalVoice.html | 477 +- .../Seven-Api-Response-Lookup-Carrier.html | 327 +- .../Seven-Api-Response-Lookup-LookupCnam.html | 327 +- ...even-Api-Response-Lookup-LookupFormat.html | 452 +- .../Seven-Api-Response-Lookup-LookupHlr.html | 677 +- .../Seven-Api-Response-Lookup-LookupMnp.html | 335 +- .../Seven-Api-Response-Lookup-Mnp.html | 402 +- .../Seven-Api-Response-Pricing-Country.html | 325 +- .../Seven-Api-Response-Pricing-Network.html | 373 +- .../Seven-Api-Response-Pricing-Pricing.html | 300 +- docs/classes/Seven-Api-Response-Sms-Sms.html | 375 +- .../Seven-Api-Response-Sms-SmsDelete.html | 275 +- .../Seven-Api-Response-Sms-SmsMessage.html | 536 +- docs/classes/Seven-Api-Response-Status.html | 302 +- ...n-Api-Response-Subaccounts-Subaccount.html | 402 +- ...ponse-Subaccounts-SubaccountAutoTopup.html | 277 +- ...esponse-Subaccounts-SubaccountContact.html | 277 +- ...Response-Subaccounts-SubaccountCreate.html | 302 +- ...Response-Subaccounts-SubaccountDelete.html | 356 +- ...Subaccounts-SubaccountTransferCredits.html | 277 +- ...Response-Subaccounts-SubaccountUpdate.html | 277 +- .../Seven-Api-Response-ValidateForVoice.html | 402 +- .../Seven-Api-Response-Voice-Voice.html | 350 +- ...Seven-Api-Response-Voice-VoiceMessage.html | 427 +- ...even-Api-Validator-AnalyticsValidator.html | 318 +- ...Seven-Api-Validator-ContactsValidator.html | 575 -- .../Seven-Api-Validator-HooksValidator.html | 880 --- .../Seven-Api-Validator-JournalValidator.html | 348 +- .../Seven-Api-Validator-LookupValidator.html | 556 -- .../Seven-Api-Validator-PricingValidator.html | 323 +- .../Seven-Api-Validator-SmsValidator.html | 415 +- .../Seven-Api-Validator-StatusValidator.html | 264 +- ...en-Api-Validator-SubaccountsValidator.html | 358 +- ...i-Validator-ValidateForVoiceValidator.html | 278 +- .../Seven-Api-Validator-VoiceValidator.html | 412 +- docs/css/base.css | 190 +- docs/css/normalize.css | 2 +- docs/css/template.css | 139 +- docs/files/src-baseclient.html | 151 - docs/files/src-client.html | 154 +- docs/files/src-constant-analyticsgroupby.html | 151 - .../src-constant-analyticssubaccounts.html | 154 +- docs/files/src-constant-contactsaction.html | 151 - docs/files/src-constant-hooksaction.html | 151 - docs/files/src-constant-hookseventtype.html | 154 +- .../src-constant-hooksrequestmethod.html | 154 +- docs/files/src-constant-httpmethod.html | 154 +- docs/files/src-constant-journalconstants.html | 154 +- docs/files/src-constant-journaltype.html | 151 - docs/files/src-constant-lookuptype.html | 151 - docs/files/src-constant-networktype.html | 154 +- docs/files/src-constant-portingstatus.html | 154 +- docs/files/src-constant-pricingconstants.html | 154 +- docs/files/src-constant-reachablestatus.html | 154 +- docs/files/src-constant-roamingstatus.html | 154 +- docs/files/src-constant-smsconstants.html | 154 +- docs/files/src-constant-statuscode.html | 154 +- docs/files/src-constant-statusmessage.html | 154 +- .../files/src-constant-subaccountsaction.html | 154 +- ...tion-invalidoptionalargumentexception.html | 154 +- ...tion-invalidrequiredargumentexception.html | 154 +- ...eption-unexpectedapiresponseexception.html | 154 +- .../src-exception-unknownoptionexception.html | 154 +- docs/files/src-library-reflectable.html | 151 - docs/files/src-library-util.html | 154 +- docs/files/src-params-analyticsparams.html | 154 +- docs/files/src-params-contactsparams.html | 151 - .../src-params-createsubaccountparams.html | 151 - docs/files/src-params-hooksparams.html | 151 - docs/files/src-params-journalparams.html | 154 +- docs/files/src-params-lookupparams.html | 151 - docs/files/src-params-paramsinterface.html | 154 +- docs/files/src-params-pricingparams.html | 154 +- docs/files/src-params-smsparams.html | 154 +- docs/files/src-params-statusparams.html | 154 +- docs/files/src-params-subaccountsparams.html | 151 - .../src-params-validateforvoiceparams.html | 154 +- docs/files/src-params-voiceparams.html | 154 +- docs/files/src-params-writecontactparams.html | 151 - .../files/src-resource-analyticsresource.html | 154 +- docs/files/src-resource-balanceresource.html | 154 +- docs/files/src-resource-contactsresource.html | 154 +- docs/files/src-resource-hooksresource.html | 154 +- docs/files/src-resource-journalresource.html | 154 +- docs/files/src-resource-lookupresource.html | 154 +- docs/files/src-resource-pricingresource.html | 154 +- docs/files/src-resource-resource.html | 154 +- docs/files/src-resource-smsresource.html | 154 +- docs/files/src-resource-statusresource.html | 154 +- .../src-resource-subaccountsresource.html | 154 +- ...src-resource-validateforvoiceresource.html | 154 +- docs/files/src-resource-voiceresource.html | 154 +- ...c-response-analytics-abstractanalytic.html | 154 +- ...-response-analytics-analyticbycountry.html | 154 +- ...src-response-analytics-analyticbydate.html | 154 +- ...rc-response-analytics-analyticbylabel.html | 154 +- ...sponse-analytics-analyticbysubaccount.html | 154 +- docs/files/src-response-balance.html | 154 +- docs/files/src-response-contacts-contact.html | 154 +- .../src-response-contacts-contactcreate.html | 154 +- .../src-response-contacts-contactdelete.html | 154 +- .../src-response-contacts-contactedit.html | 154 +- docs/files/src-response-hooks-hook.html | 154 +- docs/files/src-response-hooks-hooks.html | 154 +- .../src-response-hooks-hooksubscribe.html | 154 +- .../src-response-hooks-hookunsubscribe.html | 154 +- .../src-response-journal-journalbase.html | 154 +- .../src-response-journal-journalinbound.html | 154 +- .../src-response-journal-journaloutbound.html | 154 +- .../src-response-journal-journalreply.html | 154 +- .../src-response-journal-journalvoice.html | 154 +- docs/files/src-response-lookup-carrier.html | 154 +- .../files/src-response-lookup-lookupcnam.html | 154 +- .../src-response-lookup-lookupformat.html | 154 +- docs/files/src-response-lookup-lookuphlr.html | 154 +- docs/files/src-response-lookup-lookupmnp.html | 154 +- docs/files/src-response-lookup-mnp.html | 154 +- docs/files/src-response-pricing-country.html | 154 +- docs/files/src-response-pricing-network.html | 154 +- docs/files/src-response-pricing-pricing.html | 154 +- docs/files/src-response-sms-sms.html | 154 +- docs/files/src-response-sms-smsdelete.html | 154 +- docs/files/src-response-sms-smsmessage.html | 154 +- docs/files/src-response-status.html | 154 +- .../src-response-subaccounts-subaccount.html | 154 +- ...ponse-subaccounts-subaccountautotopup.html | 154 +- ...esponse-subaccounts-subaccountcontact.html | 154 +- ...response-subaccounts-subaccountcreate.html | 154 +- ...response-subaccounts-subaccountdelete.html | 154 +- ...subaccounts-subaccounttransfercredits.html | 154 +- ...response-subaccounts-subaccountupdate.html | 154 +- docs/files/src-response-validateforvoice.html | 154 +- docs/files/src-response-voice-voice.html | 154 +- .../src-response-voice-voicemessage.html | 154 +- .../src-validator-analyticsvalidator.html | 154 +- .../src-validator-contactsvalidator.html | 151 - docs/files/src-validator-hooksvalidator.html | 151 - .../files/src-validator-journalvalidator.html | 154 +- docs/files/src-validator-lookupvalidator.html | 151 - .../files/src-validator-pricingvalidator.html | 154 +- docs/files/src-validator-smsvalidator.html | 154 +- docs/files/src-validator-statusvalidator.html | 154 +- .../src-validator-subaccountsvalidator.html | 154 +- ...c-validator-validateforvoicevalidator.html | 154 +- docs/files/src-validator-voicevalidator.html | 154 +- docs/graphs/classes.html | 10 +- docs/index.html | 46 +- docs/indices/files.html | 351 +- docs/js/searchIndex.js | 5651 +++++++++++------ docs/namespaces/default.html | 143 +- docs/namespaces/seven-api-constant.html | 197 +- docs/namespaces/seven-api-exception.html | 159 +- docs/namespaces/seven-api-library.html | 163 +- docs/namespaces/seven-api-params.html | 196 +- docs/namespaces/seven-api-resource.html | 177 +- .../seven-api-response-analytics.html | 161 +- .../seven-api-response-contacts.html | 159 +- docs/namespaces/seven-api-response-hooks.html | 159 +- .../seven-api-response-journal.html | 161 +- .../namespaces/seven-api-response-lookup.html | 163 +- .../seven-api-response-pricing.html | 157 +- docs/namespaces/seven-api-response-sms.html | 157 +- .../seven-api-response-subaccounts.html | 165 +- docs/namespaces/seven-api-response-voice.html | 155 +- docs/namespaces/seven-api-response.html | 168 +- docs/namespaces/seven-api-validator.html | 181 +- docs/namespaces/seven-api.html | 163 +- docs/namespaces/seven.html | 143 +- docs/packages/Application.html | 389 +- docs/packages/default.html | 143 +- docs/reports/deprecated.html | 33 +- docs/reports/errors.html | 80 +- docs/reports/markers.html | 143 +- src/Client.php | 86 +- src/Constant/SubaccountsAction.php | 12 - src/Exception/InvalidApiKeyException.php | 18 + .../InvalidOptionalArgumentException.php | 10 +- .../InvalidRequiredArgumentException.php | 10 +- .../UnexpectedApiResponseException.php | 10 +- src/Exception/UnknownOptionException.php | 10 +- src/Params/Subaccounts/AutoChargeParams.php | 23 + src/Params/Subaccounts/CreateParams.php | 34 + .../Subaccounts/CreateSubaccountParams.php | 15 - src/Params/Subaccounts/SubaccountsParams.php | 91 - .../Subaccounts/TransferCreditsParams.php | 22 + src/Resource/SubaccountsResource.php | 89 +- ...{SubaccountAutoTopup.php => AutoTopUp.php} | 12 +- src/Response/Subaccounts/Subaccount.php | 31 +- ...ntUpdate.php => SubaccountAutoCharged.php} | 12 +- .../Subaccounts/SubaccountContact.php | 12 +- src/Response/Subaccounts/SubaccountCreate.php | 15 +- src/Response/Subaccounts/SubaccountDelete.php | 16 +- .../Subaccounts/SubaccountTransferCredits.php | 12 +- src/Validator/SubaccountsValidator.php | 94 - tests/SubaccountsTest.php | 20 +- 268 files changed, 41098 insertions(+), 33436 deletions(-) delete mode 100644 docs/classes/Seven-Api-BaseClient.html delete mode 100644 docs/classes/Seven-Api-Constant-AnalyticsGroupBy.html delete mode 100644 docs/classes/Seven-Api-Constant-ContactsAction.html delete mode 100644 docs/classes/Seven-Api-Constant-HooksAction.html delete mode 100644 docs/classes/Seven-Api-Constant-JournalType.html delete mode 100644 docs/classes/Seven-Api-Constant-LookupType.html delete mode 100644 docs/classes/Seven-Api-Library-Reflectable.html delete mode 100644 docs/classes/Seven-Api-Params-ContactsParams.html delete mode 100644 docs/classes/Seven-Api-Params-CreateSubaccountParams.html delete mode 100644 docs/classes/Seven-Api-Params-HooksParams.html delete mode 100644 docs/classes/Seven-Api-Params-LookupParams.html delete mode 100644 docs/classes/Seven-Api-Params-SubaccountsParams.html delete mode 100644 docs/classes/Seven-Api-Params-WriteContactParams.html delete mode 100644 docs/classes/Seven-Api-Validator-ContactsValidator.html delete mode 100644 docs/classes/Seven-Api-Validator-HooksValidator.html delete mode 100644 docs/classes/Seven-Api-Validator-LookupValidator.html delete mode 100644 docs/files/src-baseclient.html delete mode 100644 docs/files/src-constant-analyticsgroupby.html delete mode 100644 docs/files/src-constant-contactsaction.html delete mode 100644 docs/files/src-constant-hooksaction.html delete mode 100644 docs/files/src-constant-journaltype.html delete mode 100644 docs/files/src-constant-lookuptype.html delete mode 100644 docs/files/src-library-reflectable.html delete mode 100644 docs/files/src-params-contactsparams.html delete mode 100644 docs/files/src-params-createsubaccountparams.html delete mode 100644 docs/files/src-params-hooksparams.html delete mode 100644 docs/files/src-params-lookupparams.html delete mode 100644 docs/files/src-params-subaccountsparams.html delete mode 100644 docs/files/src-params-writecontactparams.html delete mode 100644 docs/files/src-validator-contactsvalidator.html delete mode 100644 docs/files/src-validator-hooksvalidator.html delete mode 100644 docs/files/src-validator-lookupvalidator.html delete mode 100644 src/Constant/SubaccountsAction.php create mode 100644 src/Exception/InvalidApiKeyException.php create mode 100644 src/Params/Subaccounts/AutoChargeParams.php create mode 100644 src/Params/Subaccounts/CreateParams.php delete mode 100644 src/Params/Subaccounts/CreateSubaccountParams.php delete mode 100644 src/Params/Subaccounts/SubaccountsParams.php create mode 100644 src/Params/Subaccounts/TransferCreditsParams.php rename src/Response/Subaccounts/{SubaccountAutoTopup.php => AutoTopUp.php} (63%) rename src/Response/Subaccounts/{SubaccountUpdate.php => SubaccountAutoCharged.php} (61%) delete mode 100644 src/Validator/SubaccountsValidator.php diff --git a/.idea/php.xml b/.idea/php.xml index 0bb2182..a09383f 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -45,34 +45,36 @@ - - + + - - - /home/aim/.asdf/installs/php/8.2.17RC2/conf.d/php.ini - + + + /etc/php/8.3/cli/conf.d/10-mysqlnd.ini, /etc/php/8.3/cli/conf.d/10-opcache.ini, /etc/php/8.3/cli/conf.d/10-pdo.ini, /etc/php/8.3/cli/conf.d/15-xml.ini, /etc/php/8.3/cli/conf.d/20-amqp.ini, /etc/php/8.3/cli/conf.d/20-bcmath.ini, /etc/php/8.3/cli/conf.d/20-calendar.ini, /etc/php/8.3/cli/conf.d/20-ctype.ini, /etc/php/8.3/cli/conf.d/20-curl.ini, /etc/php/8.3/cli/conf.d/20-dom.ini, /etc/php/8.3/cli/conf.d/20-exif.ini, /etc/php/8.3/cli/conf.d/20-ffi.ini, /etc/php/8.3/cli/conf.d/20-fileinfo.ini, /etc/php/8.3/cli/conf.d/20-ftp.ini, /etc/php/8.3/cli/conf.d/20-gd.ini, /etc/php/8.3/cli/conf.d/20-gettext.ini, /etc/php/8.3/cli/conf.d/20-gmp.ini, /etc/php/8.3/cli/conf.d/20-iconv.ini, /etc/php/8.3/cli/conf.d/20-igbinary.ini, /etc/php/8.3/cli/conf.d/20-mbstring.ini, /etc/php/8.3/cli/conf.d/20-mysqli.ini, /etc/php/8.3/cli/conf.d/20-pdo_mysql.ini, /etc/php/8.3/cli/conf.d/20-pdo_pgsql.ini, /etc/php/8.3/cli/conf.d/20-pgsql.ini, /etc/php/8.3/cli/conf.d/20-phar.ini, /etc/php/8.3/cli/conf.d/20-posix.ini, /etc/php/8.3/cli/conf.d/20-readline.ini, /etc/php/8.3/cli/conf.d/20-redis.ini, /etc/php/8.3/cli/conf.d/20-shmop.ini, /etc/php/8.3/cli/conf.d/20-simplexml.ini, /etc/php/8.3/cli/conf.d/20-sockets.ini, /etc/php/8.3/cli/conf.d/20-sysvmsg.ini, /etc/php/8.3/cli/conf.d/20-sysvsem.ini, /etc/php/8.3/cli/conf.d/20-sysvshm.ini, /etc/php/8.3/cli/conf.d/20-tokenizer.ini, /etc/php/8.3/cli/conf.d/20-xmlreader.ini, /etc/php/8.3/cli/conf.d/20-xmlwriter.ini, /etc/php/8.3/cli/conf.d/20-xsl.ini, /etc/php/8.3/cli/conf.d/20-yaml.ini, /etc/php/8.3/cli/conf.d/20-zip.ini, /etc/php/8.3/cli/conf.d/25-mailparse.ini + /etc/php/8.3/cli/php.ini - + + + + - @@ -80,11 +82,13 @@ + - + + @@ -93,15 +97,15 @@ - + + - - + @@ -110,6 +114,8 @@ + + diff --git a/docs/classes/Seven-Api-BaseClient.html b/docs/classes/Seven-Api-BaseClient.html deleted file mode 100644 index 081076e..0000000 --- a/docs/classes/Seven-Api-BaseClient.html +++ /dev/null @@ -1,759 +0,0 @@ - - - - - seven API - - - - - - - - - - - - - - - - - - - - -
-

seven API

- - - - - -
- -
-
- - - - -
- - -
-

- BaseClient - - -
- in package - -
- - -

- - - - -
- - - - - - - - -

- Table of Contents - -

- -
-
- BASE_URI - -  = 'https://gateway.seven.io/api' -
-
- -
- $apiKey - -  : string -
-
- -
- $sentWith - -  : string -
-
- -
- __construct() - -  : mixed -
-
- -
- delete() - -  : mixed -
-
- -
- get() - -  : mixed -
-
- -
- getApiKey() - -  : string -
-
- -
- getSentWith() - -  : string -
-
- -
- post() - -  : mixed -
-
- -
- request() - -  : mixed -
-
- -
- - - - -
-

- Constants - -

-
-

- BASE_URI - -

- - - - - - public - mixed - BASE_URI - = 'https://gateway.seven.io/api' - - - -
- -
- - - -
-
- - -
-

- Properties - -

-
-

- $apiKey - - - -

- - - - - protected - string - $apiKey - - -
- -
- - - -
-
-

- $sentWith - - - -

- - - - - protected - string - $sentWith - - -
- -
- - - -
-
- -
-

- Methods - -

-
-

- __construct() - -

- - - - - public - __construct(string $apiKey[, string $sentWith = 'php-api' ]) : mixed - - -
Parameters
-
-
- $apiKey - : string -
-
-
- -
-
- $sentWith - : string - = 'php-api'
-
-
- -
-
- - -
- Tags - -
-
-
- throws -
-
- Exception - - -
-
- -
Return values
- mixed - — - - -
-
-

- delete() - -

- - - - - public - delete(string $path[, array<string|int, mixed> $options = [] ]) : mixed - - -
Parameters
-
-
- $path - : string -
-
-
- -
-
- $options - : array<string|int, mixed> - = []
-
-
- -
-
- - - -
Return values
- mixed - — - - -
-
-

- get() - -

- - - - - public - get(string $path[, array<string|int, mixed> $options = [] ]) : mixed - - -
Parameters
-
-
- $path - : string -
-
-
- -
-
- $options - : array<string|int, mixed> - = []
-
-
- -
-
- - - -
Return values
- mixed - — - - -
-
-

- getApiKey() - -

- - - - - public - getApiKey() : string - -
- - - - -
Return values
- string - — - - -
-
-

- getSentWith() - -

- - - - - public - getSentWith() : string - -
- - - - -
Return values
- string - — - - -
-
-

- post() - -

- - - - - public - post(string $path[, array<string|int, mixed> $options = [] ]) : mixed - - -
Parameters
-
-
- $path - : string -
-
-
- -
-
- $options - : array<string|int, mixed> - = []
-
-
- -
-
- - - -
Return values
- mixed - — - - -
-
-

- request() - -

- - - - - protected - request(string $path, string $method[, array<string|int, mixed> $options = [] ]) : mixed - - -
Parameters
-
-
- $path - : string -
-
-
- -
-
- $method - : string -
-
-
- -
-
- $options - : array<string|int, mixed> - = []
-
-
- -
-
- - - -
Return values
- mixed - — - - -
-
- - - - -
-
-
-
-

Search results

- -
-
-
    -
    -
    -
    -
    -
    - - -
    - - - - - - - - diff --git a/docs/classes/Seven-Api-Client.html b/docs/classes/Seven-Api-Client.html index 3998b1e..eabf12b 100644 --- a/docs/classes/Seven-Api-Client.html +++ b/docs/classes/Seven-Api-Client.html @@ -10,7 +10,7 @@ - + @@ -19,6 +19,7 @@ + @@ -52,7 +53,7 @@

    sev -

    >

    delete() - + +

    public - delete(string $path[, array<string|int, mixed> $options = [] ]) : mixed + delete(string $path[, array<string|int, mixed> $options = [] ][, array<string|int, mixed> $headers = [] ]) : mixed +
    +
    Parameters
    @@ -899,25 +533,26 @@
    Parameters
    : string
    -
    - +
    $options : array<string|int, mixed> = []
    -
    - + +
    +
    + $headers + : array<string|int, mixed> + = []
    +
    +
    -
    Return values
    - mixed - — -
    Return values >

    get() - + +

    public - get(string $path[, array<string|int, mixed> $options = [] ]) : mixed + get(string $path[, array<string|int, mixed> $params = [] ][, array<string|int, mixed> $headers = [] ]) : mixed +
    +
    Parameters
    @@ -950,25 +588,26 @@
    Parameters
    : string
    -
    - +
    - $options + $params : array<string|int, mixed> = []
    -
    - + +
    +
    + $headers + : array<string|int, mixed> + = []
    +
    +
    -
    Return values
    - mixed - — -
    Return values >

    getApiKey() - + +

    @@ -993,16 +633,17 @@

    public getApiKey() : string -
    - +
    +
    + +
    Return values
    - string - — - - + string +
    +

    Return values >

    getSentWith() - + +

    @@ -1026,15 +668,71 @@

    public getSentWith() : string -
    - +
    +
    + +
    Return values
    - string - — - + string +
    + +

    +
    +

    + patch() + + +

    + + + + + public + patch(string $path[, array<string|int, mixed> $payload = [] ][, array<string|int, mixed> $headers = [] ]) : mixed + +
    +
    + +
    Parameters
    +
    +
    + $path + : string +
    +
    + +
    +
    + $payload + : array<string|int, mixed> + = []
    +
    + +
    +
    + $headers + : array<string|int, mixed> + = []
    +
    + +
    +
    + + +
    Return values >

    post() - + +

    public - post(string $path[, array<string|int, mixed> $options = [] ]) : mixed + post(string $path[, array<string|int, mixed> $payload = [] ][, array<string|int, mixed> $headers = [] ]) : mixed +
    +
    Parameters
    @@ -1067,25 +768,26 @@
    Parameters
    : string
    -
    - +
    - $options + $payload : array<string|int, mixed> = []
    -
    - + +
    +
    + $headers + : array<string|int, mixed> + = []
    +
    +
    -
    Return values
    - mixed - — -
    Return values >

    request() - + +

    protected - request(string $path, string $method[, array<string|int, mixed> $options = [] ]) : mixed + request(string $path, HttpMethod $method[, array<string|int, mixed> $payload = [] ][, array<string|int, mixed> $headers = [] ]) : mixed +
    +
    Parameters
    @@ -1118,101 +823,181 @@
    Parameters
    : string
    -
    - +
    $method - : string + : HttpMethod
    -
    - +
    - $options + $payload : array<string|int, mixed> = []
    -
    - + +
    +
    + $headers + : array<string|int, mixed> + = []
    +
    +
    -
    Return values
    - mixed - — -
    - - -
    +
    +
    + +
    + On this page + + +
    + +
    + +

    Search results

    @@ -1223,7 +1008,6 @@

    Search results

    - diff --git a/docs/classes/Seven-Api-Constant-AnalyticsGroupBy.html b/docs/classes/Seven-Api-Constant-AnalyticsGroupBy.html deleted file mode 100644 index e023644..0000000 --- a/docs/classes/Seven-Api-Constant-AnalyticsGroupBy.html +++ /dev/null @@ -1,431 +0,0 @@ - - - - - seven API - - - - - - - - - - - - - - - - - - - - -
    -

    seven API

    - - - - - -
    - -
    -
    - - - - -
    - - -
    -

    - AnalyticsGroupBy - - -
    - in package - -
    - - - - Uses - Reflectable -

    - - - - -
    - - - - - - - - -

    - Table of Contents - -

    - -
    -
    - COUNTRY - -  = 'country' -
    -
    - -
    - DATE - -  = 'date' -
    -
    - -
    - LABEL - -  = 'label' -
    -
    - -
    - SUBACCOUNT - -  = 'subaccount' -
    -
    - -
    - values() - -  : array<string|int, mixed> -
    -
    - -
    - - - - -
    -

    - Constants - -

    -
    -

    - COUNTRY - -

    - - - - - - public - mixed - COUNTRY - = 'country' - - - -
    - -
    - - - -
    -
    -

    - DATE - -

    - - - - - - public - mixed - DATE - = 'date' - - - -
    - -
    - - - -
    -
    -

    - LABEL - -

    - - - - - - public - mixed - LABEL - = 'label' - - - -
    - -
    - - - -
    -
    -

    - SUBACCOUNT - -

    - - - - - - public - mixed - SUBACCOUNT - = 'subaccount' - - - -
    - -
    - - - -
    -
    - - - -
    -

    - Methods - -

    -
    -

    - values() - -

    - - - - - public - static values() : array<string|int, mixed> - -
    - - - - -
    Return values
    - array<string|int, mixed> - — - - -
    -
    - - - - -
    -
    -
    -
    -

    Search results

    - -
    -
    -
      -
      -
      -
      -
      -
      - - -
      - - - - - - - - diff --git a/docs/classes/Seven-Api-Constant-AnalyticsSubaccounts.html b/docs/classes/Seven-Api-Constant-AnalyticsSubaccounts.html index 0f86e87..ebc24e4 100644 --- a/docs/classes/Seven-Api-Constant-AnalyticsSubaccounts.html +++ b/docs/classes/Seven-Api-Constant-AnalyticsSubaccounts.html @@ -10,7 +10,7 @@ - + @@ -19,6 +19,7 @@ + @@ -52,7 +53,7 @@

      sev -

      setState() +