commit 29b2ddd1a542c3223e7453b866b6b205a46c7673 Author: magdev Date: Sat Jul 12 20:27:07 2025 +0200 initial commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..32173cf --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.php] +indent_size = 4 + +[composer.*] +indent_size = 4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a1470d --- /dev/null +++ b/.gitignore @@ -0,0 +1,145 @@ +vendor/autoload.php +vendor/composer/autoload_classmap.php +vendor/composer/autoload_files.php +vendor/composer/autoload_namespaces.php +vendor/composer/autoload_psr4.php +vendor/composer/autoload_real.php +vendor/composer/autoload_static.php +vendor/composer/ClassLoader.php +vendor/composer/installed.json +vendor/composer/installed.php +vendor/composer/InstalledVersions.php +vendor/composer/LICENSE +vendor/composer/platform_check.php +vendor/psr/container/.gitignore +vendor/psr/container/composer.json +vendor/psr/container/LICENSE +vendor/psr/container/README.md +vendor/psr/container/src/ContainerExceptionInterface.php +vendor/psr/container/src/ContainerInterface.php +vendor/psr/container/src/NotFoundExceptionInterface.php +vendor/psr/log/composer.json +vendor/psr/log/LICENSE +vendor/psr/log/README.md +vendor/psr/log/src/AbstractLogger.php +vendor/psr/log/src/InvalidArgumentException.php +vendor/psr/log/src/LoggerAwareInterface.php +vendor/psr/log/src/LoggerAwareTrait.php +vendor/psr/log/src/LoggerInterface.php +vendor/psr/log/src/LoggerTrait.php +vendor/psr/log/src/LogLevel.php +vendor/psr/log/src/NullLogger.php +vendor/symfony/deprecation-contracts/CHANGELOG.md +vendor/symfony/deprecation-contracts/composer.json +vendor/symfony/deprecation-contracts/function.php +vendor/symfony/deprecation-contracts/LICENSE +vendor/symfony/deprecation-contracts/README.md +vendor/symfony/http-client/AmpHttpClient.php +vendor/symfony/http-client/AsyncDecoratorTrait.php +vendor/symfony/http-client/CachingHttpClient.php +vendor/symfony/http-client/CHANGELOG.md +vendor/symfony/http-client/composer.json +vendor/symfony/http-client/CurlHttpClient.php +vendor/symfony/http-client/DecoratorTrait.php +vendor/symfony/http-client/EventSourceHttpClient.php +vendor/symfony/http-client/HttpClient.php +vendor/symfony/http-client/HttpClientTrait.php +vendor/symfony/http-client/HttplugClient.php +vendor/symfony/http-client/HttpOptions.php +vendor/symfony/http-client/LICENSE +vendor/symfony/http-client/MockHttpClient.php +vendor/symfony/http-client/NativeHttpClient.php +vendor/symfony/http-client/NoPrivateNetworkHttpClient.php +vendor/symfony/http-client/Psr18Client.php +vendor/symfony/http-client/README.md +vendor/symfony/http-client/RetryableHttpClient.php +vendor/symfony/http-client/ScopingHttpClient.php +vendor/symfony/http-client/ThrottlingHttpClient.php +vendor/symfony/http-client/TraceableHttpClient.php +vendor/symfony/http-client/UriTemplateHttpClient.php +vendor/symfony/http-client/Chunk/DataChunk.php +vendor/symfony/http-client/Chunk/ErrorChunk.php +vendor/symfony/http-client/Chunk/FirstChunk.php +vendor/symfony/http-client/Chunk/InformationalChunk.php +vendor/symfony/http-client/Chunk/LastChunk.php +vendor/symfony/http-client/Chunk/ServerSentEvent.php +vendor/symfony/http-client/DataCollector/HttpClientDataCollector.php +vendor/symfony/http-client/DependencyInjection/HttpClientPass.php +vendor/symfony/http-client/Exception/ClientException.php +vendor/symfony/http-client/Exception/EventSourceException.php +vendor/symfony/http-client/Exception/HttpExceptionTrait.php +vendor/symfony/http-client/Exception/InvalidArgumentException.php +vendor/symfony/http-client/Exception/JsonException.php +vendor/symfony/http-client/Exception/RedirectionException.php +vendor/symfony/http-client/Exception/ServerException.php +vendor/symfony/http-client/Exception/TimeoutException.php +vendor/symfony/http-client/Exception/TransportException.php +vendor/symfony/http-client/Internal/AmpBodyV4.php +vendor/symfony/http-client/Internal/AmpBodyV5.php +vendor/symfony/http-client/Internal/AmpClientStateV4.php +vendor/symfony/http-client/Internal/AmpClientStateV5.php +vendor/symfony/http-client/Internal/AmpListenerV4.php +vendor/symfony/http-client/Internal/AmpListenerV5.php +vendor/symfony/http-client/Internal/AmpResolverV4.php +vendor/symfony/http-client/Internal/AmpResolverV5.php +vendor/symfony/http-client/Internal/Canary.php +vendor/symfony/http-client/Internal/ClientState.php +vendor/symfony/http-client/Internal/CurlClientState.php +vendor/symfony/http-client/Internal/DnsCache.php +vendor/symfony/http-client/Internal/HttplugWaitLoop.php +vendor/symfony/http-client/Internal/NativeClientState.php +vendor/symfony/http-client/Internal/PushedResponse.php +vendor/symfony/http-client/Messenger/PingWebhookMessage.php +vendor/symfony/http-client/Messenger/PingWebhookMessageHandler.php +vendor/symfony/http-client/Response/AmpResponseV4.php +vendor/symfony/http-client/Response/AmpResponseV5.php +vendor/symfony/http-client/Response/AsyncContext.php +vendor/symfony/http-client/Response/AsyncResponse.php +vendor/symfony/http-client/Response/CommonResponseTrait.php +vendor/symfony/http-client/Response/CurlResponse.php +vendor/symfony/http-client/Response/HttplugPromise.php +vendor/symfony/http-client/Response/JsonMockResponse.php +vendor/symfony/http-client/Response/MockResponse.php +vendor/symfony/http-client/Response/NativeResponse.php +vendor/symfony/http-client/Response/ResponseStream.php +vendor/symfony/http-client/Response/StreamableInterface.php +vendor/symfony/http-client/Response/StreamWrapper.php +vendor/symfony/http-client/Response/TraceableResponse.php +vendor/symfony/http-client/Response/TransportResponseTrait.php +vendor/symfony/http-client/Retry/GenericRetryStrategy.php +vendor/symfony/http-client/Retry/RetryStrategyInterface.php +vendor/symfony/http-client/Test/HarFileResponseFactory.php +vendor/symfony/http-client-contracts/CHANGELOG.md +vendor/symfony/http-client-contracts/ChunkInterface.php +vendor/symfony/http-client-contracts/composer.json +vendor/symfony/http-client-contracts/HttpClientInterface.php +vendor/symfony/http-client-contracts/LICENSE +vendor/symfony/http-client-contracts/README.md +vendor/symfony/http-client-contracts/ResponseInterface.php +vendor/symfony/http-client-contracts/ResponseStreamInterface.php +vendor/symfony/http-client-contracts/Exception/ClientExceptionInterface.php +vendor/symfony/http-client-contracts/Exception/DecodingExceptionInterface.php +vendor/symfony/http-client-contracts/Exception/ExceptionInterface.php +vendor/symfony/http-client-contracts/Exception/HttpExceptionInterface.php +vendor/symfony/http-client-contracts/Exception/RedirectionExceptionInterface.php +vendor/symfony/http-client-contracts/Exception/ServerExceptionInterface.php +vendor/symfony/http-client-contracts/Exception/TimeoutExceptionInterface.php +vendor/symfony/http-client-contracts/Exception/TransportExceptionInterface.php +vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php +vendor/symfony/http-client-contracts/Test/TestHttpServer.php +vendor/symfony/http-client-contracts/Test/Fixtures/web/index.php +vendor/symfony/service-contracts/CHANGELOG.md +vendor/symfony/service-contracts/composer.json +vendor/symfony/service-contracts/LICENSE +vendor/symfony/service-contracts/README.md +vendor/symfony/service-contracts/ResetInterface.php +vendor/symfony/service-contracts/ServiceCollectionInterface.php +vendor/symfony/service-contracts/ServiceLocatorTrait.php +vendor/symfony/service-contracts/ServiceMethodsSubscriberTrait.php +vendor/symfony/service-contracts/ServiceProviderInterface.php +vendor/symfony/service-contracts/ServiceSubscriberInterface.php +vendor/symfony/service-contracts/ServiceSubscriberTrait.php +vendor/symfony/service-contracts/Attribute/Required.php +vendor/symfony/service-contracts/Attribute/SubscribedService.php +vendor/symfony/service-contracts/Test/ServiceLocatorTest.php +vendor/symfony/service-contracts/Test/ServiceLocatorTestCase.php diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4fabddf --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2025 magdev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..036ebc3 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Listmonk API Client (WiP) + +PHP client library for the [Listmonk](https://listmonk.app/) [API](https://listmonk.app/docs/apis/apis/). diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..0970deb --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "magdev/listmonk-api", + "description": "Listmonk API-Client library", + "type": "library", + "license": "MIT", + "minimum-stability": "stable", + "authors": [ + { + "name": "magdev", + "email": "magdev3.0@gmail.com" + } + ], + "require": { + "symfony/http-client": "^7.3" + }, + "autoload": { + "psr-4": { + "Magdev\\ListmonkApi\\": "src/" + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..3ed60c8 --- /dev/null +++ b/composer.lock @@ -0,0 +1,445 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "5699acfabf0a0d069fc5d390bf89915b", + "packages": [ + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/http-client", + "version": "v7.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/4403d87a2c16f33345dca93407a8714ee8c05a64", + "reference": "4403d87a2c16f33345dca93407a8714ee8c05a64", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "~3.4.4|^3.5.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "amphp/amp": "<2.5", + "amphp/socket": "<1.1", + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/http-client": "^4.2.1|^5.0", + "amphp/http-tunnel": "^1.0|^2.0", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/amphp-http-client-meta": "^1.0|^2.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v7.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-28T07:58:39+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "75d7043853a42837e68111812f4d964b01e5101c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", + "reference": "75d7043853a42837e68111812f4d964b01e5101c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-29T11:18:49+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-25T09:37:31+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/src/Api/AbstractApi.php b/src/Api/AbstractApi.php new file mode 100644 index 0000000..08b693f --- /dev/null +++ b/src/Api/AbstractApi.php @@ -0,0 +1,20 @@ +getNamespace()); + } + + abstract protected function query(string $query): array; + abstract protected function getNamespace(): string; +} diff --git a/src/Api/ApiInterface.php b/src/Api/ApiInterface.php new file mode 100644 index 0000000..85ca8ad --- /dev/null +++ b/src/Api/ApiInterface.php @@ -0,0 +1,8 @@ +setClient($client); + } + } + + public function connect(string $hostname, string $username, string $token): static + { + if ($this->client instanceof HttpClientInterface) { + return $this; + } + + $this->client = HttpClient::createForBaseUri($hostname, [ + 'headers' => [ + 'Authorization' => sprintf('token %s:%s', $username, $token), + ] + ]); + + return $this; + } + + public function getClient(): ?HttpClientInterface + { + if (is_null($this->client)) { + throw new ListmonkClientException('You have to connect to a server first or set the client manually'); + } + + return $this->client; + } + + public function setClient(HttpClientInterface $client): static + { + $this->client = $client; + + return $this; + } + + public function subscribers(): SubscriberApi + { + return new SubscriberApi($this->getClient()); + } + + public function transactional(): TransactionalApi + { + return new TransactionalApi($this->getClient()); + } + + public function lists(): ListApi + { + return new ListApi($this->getClient()); + } + + public function bounces(): BounceApi + { + return new BounceApi($this->getClient()); + } + + public function templates(): TemplateApi + { + return new TemplateApi($this->getClient()); + } + + public function media(): MediaApi + { + return new MediaApi($this->getClient()); + } + + public function campaigns(): CampaignApi + { + return new CampaignApi($this->getClient()); + } + + public function import(): ImportApi + { + return new ImportApi($this->getClient()); + } +} diff --git a/src/ListmonkClientException.php b/src/ListmonkClientException.php new file mode 100644 index 0000000..4f6fa03 --- /dev/null +++ b/src/ListmonkClientException.php @@ -0,0 +1,8 @@ +fromArray($data); + } + } +} diff --git a/src/Model/CampaignModel.php b/src/Model/CampaignModel.php new file mode 100644 index 0000000..1e43a04 --- /dev/null +++ b/src/Model/CampaignModel.php @@ -0,0 +1,359 @@ +setName($data['name']); + } + if (isset($data['type'])) { + $this->setType($data['type']); + } + if (isset($data['from_email'])) { + $this->setFromEmail($data['from_email']); + } + if (isset($data['views'])) { + $this->setViews($data['views']); + } + if (isset($data['clicks'])) { + $this->setClicks($data['clicks']); + } + if (isset($data['to_send'])) { + $this->setToSend($data['to_send']); + } + if (isset($data['sent'])) { + $this->setSent($data['sent']); + } + if (isset($data['send_at'])) { + $this->setSendAt($data['send_at']); + } + if (isset($data['started_at'])) { + $this->setStartedAt($data['started_at']); + } + if (isset($data['subject'])) { + $this->setSubject($data['subject']); + } + if (isset($data['body'])) { + $this->setBody($data['body']); + } + if (isset($data['body_source'])) { + $this->setBodySource($data['body_source']); + } + if (isset($data['status'])) { + $this->setStatus($data['status']); + } + if (isset($data['content_type'])) { + $this->setContentType($data['content_type']); + } + if (isset($data['tags'])) { + $this->setTags($data['tags']); + } + if (isset($data['messenger'])) { + $this->setMessenger($data['messenger']); + } + if (isset($data['template_id'])) { + $this->setTemplateId($data['template_id']); + } + + if (isset($data['lists']) && is_array($data['lists'])) { + foreach ($data['lists'] as $listData) { + $this->addList(new ListModel($listData)); + } + } + + return $this; + } + + public function toArray(): array + { + $data = array_merge(parent::toArray(), [ + 'name' => $this->getName(), + 'type' => $this->getType(), + 'from_email' => $this->getFromEmail(), + 'views' => $this->getViews(), + 'clicks' => $this->getClicks(), + 'to_send' => $this->getToSend(), + 'sent' => $this->getSent(), + 'send_at' => $this->getSendAt(), + 'started_at' => $this->getStartedAt(), + 'subject' => $this->getSubject(), + 'body' => $this->getBody(), + 'body_source' => $this->getBodySource(), + 'status' => $this->getStatus(), + 'content_type' => $this->getContentType(), + 'tags' => $this->getTags(), + 'messenger' => $this->getMessenger(), + 'template_id' => $this->getTemplateId(), + 'lists' => [], + ]); + + if ($lists = $this->getLists()) { + foreach ($lists as $list) { + $data['lists'][] = $list->toArray(); + } + } + + return $data; + } + + public function getViews(): ?int + { + return $this->views; + } + + public function setViews(?int $views): self + { + $this->views = $views; + + return $this; + } + + public function getClicks(): ?int + { + return $this->clicks; + } + + public function setClicks(?int $clicks): self + { + $this->clicks = $clicks; + + return $this; + } + + /** + * @return ListModel[]|null + */ + public function getLists(): ?array + { + return $this->lists; + } + + /** + * @param ListModel[]|null + */ + public function setLists(?array $lists): self + { + $this->lists = $lists; + + return $this; + } + + public function addList(ListModel $list): self + { + $this->lists[] = $list; + + return $this; + } + + public function getStartedAt(): ?\DateTimeInterface + { + return $this->startedAt; + } + + public function setStartedAt(\DateTimeInterface|string|null $startedAt): self + { + if (is_string($startedAt)) { + $startedAt = new \DateTime($startedAt); + } + + $this->startedAt = $startedAt; + + return $this; + } + + public function getSendAt(): ?\DateTimeInterface + { + return $this->sendAt; + } + + public function setSendAt(\DateTimeInterface|string|null $sendAt): self + { + if (is_string($sendAt)) { + $sendAt = new \DateTime($sendAt); + } + + $this->sendAt = $sendAt; + + return $this; + } + + public function getToSend(): ?int + { + return $this->toSend; + } + + public function setToSend(?int $toSend): self + { + $this->toSend = $toSend; + + return $this; + } + + public function getSent(): ?int + { + return $this->sent; + } + + public function setSent(?int $sent): self + { + $this->sent = $sent; + + return $this; + } + + public function getType(): ?string + { + return $this->type; + } + + public function setType(?string $type): self + { + $this->type = $type; + + return $this; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(?string $name): self + { + $this->name = $name; + + return $this; + } + + public function getSubject(): ?string + { + return $this->subject; + } + + public function setSubject(?string $subject): self + { + $this->subject = $subject; + + return $this; + } + + public function getFromEmail(): ?string + { + return $this->fromEmail; + } + + public function setFromEmail(?string $fromEmail): self + { + $this->fromEmail = $fromEmail; + + return $this; + } + + public function getBody(): ?string + { + return $this->body; + } + + public function setBody(?string $body): self + { + $this->body = $body; + + return $this; + } + + public function getBodySource(): ?string + { + return $this->bodySource; + } + + public function setBodySource(?string $bodySource): self + { + $this->bodySource = $bodySource; + + return $this; + } + + public function getStatus(): ?string + { + return $this->status; + } + + public function setStatus(?string $status): self + { + $this->status = $status; + + return $this; + } + + public function getContentType(): ?string + { + return $this->contentType; + } + + public function setContentType(?string $contentType): self + { + $this->contentType = $contentType; + + return $this; + } + + public function getTags(): ?array + { + return $this->tags; + } + + public function setTags(?array $tags): self + { + $this->tags = $tags; + + return $this; + } + + public function getMessenger(): ?string + { + return $this->messenger; + } + + public function setMessenger(?string $messenger): self + { + $this->messenger = $messenger; + + return $this; + } + + public function getTemplateId(): ?int + { + return $this->templateId; + } + + public function setTemplateId(?int $templateId): self + { + $this->templateId = $templateId; + + return $this; + } +} diff --git a/src/Model/ListModel.php b/src/Model/ListModel.php new file mode 100644 index 0000000..dcf9261 --- /dev/null +++ b/src/Model/ListModel.php @@ -0,0 +1,123 @@ +setName($data['name']); + } + if (isset($data['type'])) { + $this->setType($data['type']); + } + if (isset($data['tags'])) { + $this->setTags($data['tags']); + } + if (isset($data['optin'])) { + $this->setOptin($data['optin']); + } + if (isset($data['subscription_status'])) { + $this->setSubscriptionStatus($data['subscription_status']); + } + if (isset($data['subscriber_count'])) { + $this->setSubscriberCount($data['subscriber_count']); + } + + return $this; + } + + public function toArray(): array + { + return array_merge(parent::toArray(), [ + 'name' => $this->getName(), + 'type' => $this->getType(), + 'tags' => $this->getTags(), + 'optin' => $this->getOptin(), + 'subscription_status' => $this->getSubscriptionStatus(), + 'subscriber_count' => $this->getSubscriberCount(), + ]); + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(?string $name): self + { + $this->name = $name; + + return $this; + } + + public function getType(): ?string + { + return $this->type; + } + + public function setType(?string $type): self + { + $this->type = $type; + + return $this; + } + + public function getTags(): ?array + { + return $this->tags; + } + + public function setTags(?array $tags): self + { + $this->tags = $tags; + + return $this; + } + + public function getOptin(): ?string + { + return $this->optin; + } + + public function setOptin(?string $optin): self + { + $this->optin = $optin; + + return $this; + } + + public function getSubscriptionStatus(): ?string + { + return $this->subscriptionStatus; + } + + public function setSubscriptionStatus(?string $subscriptionStatus): self + { + $this->subscriptionStatus = $subscriptionStatus; + + return $this; + } + + public function getSubscriberCount(): ?int + { + return $this->subscriberCount; + } + + public function setSubscriberCount(?int $subscriberCount): self + { + $this->subscriberCount = $subscriberCount; + + return $this; + } +} diff --git a/src/Model/ModelInterface.php b/src/Model/ModelInterface.php new file mode 100644 index 0000000..b87a732 --- /dev/null +++ b/src/Model/ModelInterface.php @@ -0,0 +1,9 @@ +setEmail($data['email']); + } + if (isset($data['name'])) { + $this->setName($data['name']); + } + if (isset($data['attribs'])) { + $this->setAttribs($data['attribs']); + } + if (isset($data['status'])) { + $this->setStatus($data['status']); + } + + if (isset($data['lists']) && is_array($data['lists'])) { + foreach ($data['lists'] as $listData) { + $this->addList(new ListModel($listData)); + } + } + + return $this; + } + + public function toArray(): array + { + $data = array_merge(parent::toArray(), [ + 'email' => $this->getEmail(), + 'name' => $this->getName(), + 'attribs' => $this->getAttribs(), + 'status' => $this->getStatus(), + 'lists' => [], + ]); + + foreach ($this->getLists() as $list) { + $data['lists'][] = $list->toArray(); + } + + return $data; + } + + public function getEmail(): ?string + { + return $this->email; + } + + public function setEmail(?string $email): self + { + $this->email = $email; + + return $this; + } + + public function getName(): ?string + { + return $this->name; + } + + public function setName(?string $name): self + { + $this->name = $name; + + return $this; + } + + public function getAttribs(): ?array + { + return $this->attribs; + } + + public function setAttribs(?array $attribs): self + { + $this->attribs = $attribs; + + return $this; + } + + public function getStatus(): ?string + { + return $this->status; + } + + public function setStatus(?string $status): self + { + $this->status = $status; + + return $this; + } + + /** + * @return ListModel[]|null + */ + public function getLists(): ?array + { + return $this->lists; + } + + /** + * @param ListModel[]|null + */ + public function setLists(?array $lists): self + { + $this->lists = $lists; + + return $this; + } + + public function addList(ListModel $list): self + { + $this->lists[] = $list; + + return $this; + } +} diff --git a/src/Model/Traits/DefaultPropertiesTrait.php b/src/Model/Traits/DefaultPropertiesTrait.php new file mode 100644 index 0000000..0de9934 --- /dev/null +++ b/src/Model/Traits/DefaultPropertiesTrait.php @@ -0,0 +1,95 @@ +id; + } + + public function setId(?int $id): self + { + $this->id = $id; + + return $this; + } + + public function getUuid(): ?string + { + return $this->uuid; + } + + public function setUuid(?string $uuid): self + { + $this->uuid = $uuid; + + return $this; + } + + public function getCreatedAt(): ?\DateTimeInterface + { + return $this->createdAt; + } + + public function setCreatedAt(\DateTimeInterface|string|null $createdAt): self + { + if (is_string($createdAt)) { + $createdAt = new \DateTime($createdAt); + } + + $this->createdAt = $createdAt; + + return $this; + } + + public function getUpdatedAt(): ?\DateTimeInterface + { + return $this->updatedAt; + } + + public function setUpdatedAt(\DateTimeInterface|string|null $updatedAt): self + { + if (is_string($updatedAt)) { + $updatedAt = new \DateTime($updatedAt); + } + + $this->updatedAt = $updatedAt; + + return $this; + } + + public function fromArray(array $data): static + { + if (isset($data['id'])) { + $this->setId($data['id']); + } + if (isset($data['uuid'])) { + $this->setUuid($data['uuid']); + } + if (isset($data['created_at'])) { + $this->setCreatedAt($data['created_at']); + } + if (isset($data['updated_at'])) { + $this->setUpdatedAt($data['updated_at']); + } + + return $this; + } + + public function toArray(): array + { + return [ + 'id' => $this->getId(), + 'uuid' => $this->getUuid(), + 'created_at' => $this->getCreatedAt(), + 'updated_at' => $this->getUpdatedAt(), + ]; + } +}