├── .gitignore ├── tests ├── params.json.dist ├── Request │ ├── TimeGetRequestTest.php │ ├── GetSegmentSizeGetRequestTest.php │ ├── DataTablesClearTableRequestTest.php │ ├── SubscribersDeleteRequestTest.php │ ├── SnoozedSubscribersGetRequestTest.php │ ├── TriggersPostRequestTest.php │ ├── SegmentsGetRequestTest.php │ ├── DataTablesGetTablesRequestTest.php │ ├── ActivitiesGetRequestTest.php │ ├── DataTablesDeleteRowPostRequestTest.php │ ├── RemovedSubscriberGetRequestTest.php │ ├── SubscribersGetRequestTest.php │ ├── DataTablesUpdateRowRequestTest.php │ ├── DataTablesAddMultipleRowsPostRequestTest.php │ ├── DataTablesGetDataCountRequestTest.php │ ├── DataTablesDeleteRowsPostRequestTest.php │ ├── DataTablesGetDataPostRequestTest.php │ └── SnoozedSubscribersPostRequestTest.php └── Response │ ├── CountResponseTest.php │ ├── ActivitiesGetResponse │ ├── ConfirmationsActivityGetResponseTest.php │ ├── SubscriptionsActivityGetResponseTest.php │ ├── BouncesActivityGetResponseTest.php │ ├── ComplaintsActivityGetResponseTest.php │ ├── GoalsActivityGetResponseTest.php │ ├── ClicksActivityGetResponseTest.php │ └── RemovalsActivityGetResponseTest.php │ ├── SegmentsGetResponseTest.php │ ├── SubscribersPostResponseTest.php │ ├── BounceGetResponseTest.php │ ├── TimeGetResponseTest.php │ └── SnoozedSubscribersGetResponseTest.php ├── .travis.yml ├── phpstan.neon ├── src ├── Exception │ ├── ExpertSenderApiException.php │ ├── InvalidUseOfClassException.php │ ├── ParseResponseException.php │ ├── TryToAccessDataFromErrorResponseException.php │ └── NotValidXmlException.php ├── RequestSenderInterface.php ├── Enum │ ├── RemovedSubscribersGetRequest │ │ ├── Option.php │ │ └── RemoveType.php │ ├── DataTablesGetDataPostRequest │ │ ├── Direction.php │ │ └── Operator.php │ ├── ActivitiesGetRequest │ │ ├── ReturnColumnsSet.php │ │ ├── BounceReason.php │ │ ├── RemovalReason.php │ │ └── ActivityType.php │ ├── HttpMethod.php │ ├── SubscribersResponse │ │ ├── StateOnListStatus.php │ │ └── SubscriberPropertyType.php │ ├── DataTablesDeleteRowsPostRequest │ │ └── FilterOperator.php │ ├── SubscribersPostRequest │ │ ├── MatchingMode.php │ │ └── Mode.php │ ├── BouncesGetRequest │ │ └── BounceType.php │ ├── DataType.php │ ├── BouncesGetResponse │ │ └── BounceType.php │ ├── SubscriberPropertySource.php │ └── SubscribersGetRequest │ │ └── DataOption.php ├── AbstractResource.php ├── Response │ ├── CountResponse.php │ ├── SegmentsGetResponse.php │ ├── TransactionalPostResponse.php │ ├── SubscribersGetLongResponse.php │ ├── BouncesGetResponse.php │ ├── ActivitiesGetResponse │ │ ├── ConfirmationsActivityGetResponse.php │ │ ├── SubscriptionsActivityGetResponse.php │ │ ├── OpensActivityGetResponse.php │ │ ├── SendsActivityGetResponse.php │ │ ├── ComplaintsActivityGetResponse.php │ │ ├── GoalsActivityGetResponse.php │ │ ├── ClicksActivityGetResponse.php │ │ ├── BouncesActivityGetResponse.php │ │ └── RemovalsActivityGetResponse.php │ ├── SubscribersPostResponse.php │ ├── SnoozedSubscribersGetResponse.php │ ├── TimeGetResponse.php │ ├── GetSegmentSizeGetResponse.php │ ├── DataTablesGetTablesSummaryResponse.php │ ├── SubscribersGetFullResponse.php │ ├── SubscribersGetEventsHistoryResponse.php │ ├── RemovedSubscribersGetResponse.php │ ├── SubscribersGetShortResponse.php │ └── DataTablesGetTablesDetailsResponse.php ├── Request │ ├── SystemTransactionalPostRequest.php │ ├── TimeGetRequest.php │ ├── SegmentsGetRequest.php │ ├── GetSegmentSizeGetRequest.php │ ├── DataTablesClearTableRequest.php │ ├── DataTablesGetTablesRequest.php │ ├── SubscribersGetRequest.php │ ├── BouncesGetRequest.php │ ├── DataTablesAddMultipleRowsPostRequest.php │ ├── DataTablesGetDataCountRequest.php │ ├── DataTablesDeleteRowsPostRequest.php │ ├── TriggersPostRequest.php │ ├── DataTablesDeleteRowPostRequest.php │ └── SubscribersDeleteRequest.php ├── RequestInterface.php ├── Model │ ├── DataTablesAddMultipleRowsPostRequest │ │ └── Row.php │ ├── DataTablesGetDataPostRequest │ │ ├── WhereCondition.php │ │ └── OrderByRule.php │ ├── SegmentsGetResponse │ │ └── Segment.php │ ├── SubscribersPostRequest │ │ ├── Property.php │ │ └── Options.php │ ├── Column.php │ ├── TransactionalPostRequest │ │ ├── Snippet.php │ │ └── Attachment.php │ ├── ActivitiesGetResponse │ │ ├── AbstractActivity.php │ │ ├── ConfirmationActivity.php │ │ └── SubscriptionActivity.php │ ├── ErrorMessage.php │ ├── DataTablesGetTablesSummaryResponse │ │ ├── TableSummary.php │ │ └── TableDetails.php │ ├── DataTablesDeleteRowsPostRequest │ │ └── Filter.php │ ├── TriggersPostRequest │ │ └── Receiver.php │ ├── WhereCondition.php │ ├── SnoozedSubscribersGetResponse │ │ └── SnoozedSubscriber.php │ ├── SubscribersPostResponse │ │ └── SubscriberData.php │ ├── BouncesGetResponse │ │ └── Bounce.php │ ├── SubscribersGetResponse │ │ └── StateOnList.php │ ├── RemovedSubscribersGetResponse │ │ └── RemovedSubscriber.php │ └── SubscriberData.php ├── Event │ ├── ResponseReceivedEvent.php │ └── RequestExceptionThrown.php ├── Traits │ ├── WhereConditionToXmlConverterTrait.php │ └── ColumnToXmlConverterTrait.php ├── CsvReader.php ├── ResponseInterface.php ├── Utils.php ├── SpecificXmlMethodResponse.php ├── SpecificCsvMethodResponse.php └── ExpertSenderApi.php ├── phpunit.xml.dist ├── LICENSE └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /.idea/ 3 | tests/params.json 4 | -------------------------------------------------------------------------------- /tests/params.json.dist: -------------------------------------------------------------------------------- 1 | { 2 | "url": null, 3 | "key": null, 4 | "testList": null, 5 | "testTrigger": null, 6 | "testTransactional": null, 7 | "testGmailEmailPattern": null, 8 | "testTableName": null 9 | } 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | sudo: false 4 | dist: trusty 5 | 6 | php: 7 | - 7.1 8 | - 7.2 9 | - 7.3 10 | 11 | cache: 12 | directories: 13 | - $HOME/.composer/cache 14 | 15 | before_script: 16 | - composer install 17 | 18 | script: composer test -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | ignoreErrors: 3 | # problems with case of methods in PHP documentation and reflection 4 | - '#Call to method XMLWriter::.*#' 5 | # reflection can not find those properties 6 | - '#Access to an undefined property LibXMLError::\$message#' 7 | -------------------------------------------------------------------------------- /src/Exception/ExpertSenderApiException.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class ExpertSenderApiException extends \RuntimeException 12 | { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/RequestSenderInterface.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | interface RequestSenderInterface 12 | { 13 | /** 14 | * Send request 15 | * 16 | * @param RequestInterface $request Request 17 | * 18 | * @return ResponseInterface Response 19 | */ 20 | public function send(RequestInterface $request): ResponseInterface; 21 | } 22 | -------------------------------------------------------------------------------- /src/Enum/RemovedSubscribersGetRequest/Option.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class Option extends Enum 16 | { 17 | /** 18 | * Return all subscriber properties and some general information 19 | */ 20 | const CUSTOMS = 'Customs'; 21 | } 22 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | tests/ 6 | tests/ExpertSenderTest.php 7 | 8 | 9 | tests/ExpertSenderTest.php 10 | 11 | 12 | 13 | 14 | src/ 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Enum/DataTablesGetDataPostRequest/Direction.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | final class Direction extends Enum 17 | { 18 | /** 19 | * Ascending 20 | */ 21 | const ASCENDING = 'Ascending'; 22 | 23 | /** 24 | * Descending 25 | */ 26 | const DESCENDING = 'Descending'; 27 | } 28 | -------------------------------------------------------------------------------- /src/AbstractResource.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class AbstractResource 12 | { 13 | /** 14 | * @var RequestSenderInterface Request sender 15 | */ 16 | protected $requestSender; 17 | 18 | /** 19 | * Constructor. 20 | * 21 | * @param RequestSenderInterface $requestSender Request sender 22 | */ 23 | public function __construct(RequestSenderInterface $requestSender) 24 | { 25 | $this->requestSender = $requestSender; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Enum/ActivitiesGetRequest/ReturnColumnsSet.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | final class ReturnColumnsSet extends Enum 17 | { 18 | /** 19 | * Default set 20 | */ 21 | const STANDARD = 'Standard'; 22 | 23 | /** 24 | * Additional columns are returned in the response 25 | */ 26 | const EXTENDED = 'Extended'; 27 | } 28 | -------------------------------------------------------------------------------- /tests/Request/TimeGetRequestTest.php: -------------------------------------------------------------------------------- 1 | getQueryParams()); 16 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::GET())); 17 | Assert::assertEquals('/v2/Api/Time', $request->getUri()); 18 | Assert::assertEquals('', $request->toXml()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Enum/HttpMethod.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | final class HttpMethod extends Enum 19 | { 20 | /** 21 | * POST 22 | */ 23 | const POST = 'POST'; 24 | 25 | /** 26 | * GET 27 | */ 28 | const GET = 'GET'; 29 | 30 | /** 31 | * PUT 32 | */ 33 | const PUT = 'PUT'; 34 | 35 | /** 36 | * DELETE 37 | */ 38 | const DELETE = 'DELETE'; 39 | } 40 | -------------------------------------------------------------------------------- /src/Response/CountResponse.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class CountResponse extends SpecificXmlMethodResponse 15 | { 16 | /** 17 | * Get count 18 | * 19 | * @return int Count 20 | */ 21 | public function getCount(): int 22 | { 23 | if (!$this->isOk()) { 24 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 25 | } 26 | 27 | return intval($this->getSimpleXml()->xpath('/ApiResponse/Count')[0]); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Request/SystemTransactionalPostRequest.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class SystemTransactionalPostRequest extends TransactionalPostRequest 19 | { 20 | /** 21 | * {@inheritdoc} 22 | */ 23 | public function getUri(): string 24 | { 25 | return '/v2/Api/SystemTransactionals/' . $this->transactionMessageId; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Request/GetSegmentSizeGetRequestTest.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class GetSegmentSizeGetRequestTest extends \PHPUnit_Framework_TestCase 16 | { 17 | public function testCommonUsage() 18 | { 19 | $request = new GetSegmentSizeGetRequest(25); 20 | Assert::assertEquals(['id' => 25], $request->getQueryParams()); 21 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::GET())); 22 | Assert::assertEquals('', $request->toXml()); 23 | Assert::assertEquals('/v2/Api/GetSegmentSize', $request->getUri()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Exception/InvalidUseOfClassException.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class InvalidUseOfClassException extends ExpertSenderApiException 12 | { 13 | /** 14 | * Create exception for case, when property can not be null 15 | * 16 | * @param object $object Object 17 | * @param string $propertyName Property name 18 | * 19 | * @return static Exception when somehow someone break architecture of class 20 | */ 21 | public static function createPropertyOfClassCanNotBeNull($object, $propertyName) 22 | { 23 | return new static( 24 | 'Invalid use of class, ' . get_class($object) . '::$' . $propertyName . 'property can not be null' 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Enum/DataTablesGetDataPostRequest/Operator.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | final class Operator extends Enum 19 | { 20 | /** 21 | * Equals 22 | * 23 | * Can't name it like "EQUALS", because class Enum already has "exists" method 24 | */ 25 | const EQUAL = 'Equals'; 26 | 27 | /** 28 | * Greater 29 | */ 30 | const GREATER = 'Greater'; 31 | 32 | /** 33 | * Lower 34 | */ 35 | const LOWER = 'Lower'; 36 | 37 | /** 38 | * Like 39 | */ 40 | const LIKE = 'Like'; 41 | } 42 | -------------------------------------------------------------------------------- /src/RequestInterface.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | interface RequestInterface 14 | { 15 | /** 16 | * Get XML representation 17 | * 18 | * @return string XML representation 19 | */ 20 | public function toXml(): string; 21 | 22 | /** 23 | * Get query parameters 24 | * 25 | * @return mixed[] Query parameters 26 | */ 27 | public function getQueryParams(): array; 28 | 29 | /** 30 | * Get HTTP method 31 | * 32 | * @return HttpMethod HTTP method 33 | */ 34 | public function getMethod(): HttpMethod; 35 | 36 | /** 37 | * Get URI 38 | * 39 | * @return string URI 40 | */ 41 | public function getUri(): string; 42 | } 43 | -------------------------------------------------------------------------------- /src/Enum/SubscribersResponse/StateOnListStatus.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | final class StateOnListStatus extends Enum 19 | { 20 | /** 21 | * Unsubscribed 22 | */ 23 | const UNSUBSCRIBED = 'Unsubscribed'; 24 | 25 | /** 26 | * Active 27 | */ 28 | const ACTIVE = 'Active'; 29 | 30 | /** 31 | * Snoozed 32 | */ 33 | const SNOOZED = 'Snoozed'; 34 | 35 | /** 36 | * Not Confirmed 37 | */ 38 | const NOT_CONFIRMED = 'NotConfirmed'; 39 | } 40 | -------------------------------------------------------------------------------- /src/Response/SegmentsGetResponse.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class SegmentsGetResponse extends SpecificXmlMethodResponse 15 | { 16 | /** 17 | * Get segments 18 | * 19 | * @return Segment[] Segments 20 | */ 21 | public function getSegments(): array 22 | { 23 | $nodes = $this->getSimpleXml()->xpath('/ApiResponse/Data/Segments/Segment'); 24 | $segments = []; 25 | foreach ($nodes as $node) { 26 | $segments[] = new Segment( 27 | (int)$node->Id, 28 | (string)$node->Name 29 | ); 30 | } 31 | 32 | return $segments; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Model/DataTablesAddMultipleRowsPostRequest/Row.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class Row 15 | { 16 | /** 17 | * @var Column[]|iterable Columns 18 | */ 19 | private $columns; 20 | 21 | /** 22 | * Constructor 23 | * 24 | * @param Column[]|iterable $columns Columns 25 | */ 26 | public function __construct(iterable $columns) 27 | { 28 | Assert::notEmpty($columns); 29 | $this->columns = $columns; 30 | } 31 | 32 | /** 33 | * Get columns 34 | * 35 | * @return Column[]|iterable Columns 36 | */ 37 | public function getColumns() 38 | { 39 | return $this->columns; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/Enum/DataTablesDeleteRowsPostRequest/FilterOperator.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class FilterOperator extends Enum 20 | { 21 | /** 22 | * Equals 23 | */ 24 | const EQ = 'EQ'; 25 | 26 | /** 27 | * Greater than 28 | */ 29 | const GT = 'GT'; 30 | 31 | /** 32 | * Less than 33 | */ 34 | const LT = 'LT'; 35 | 36 | /** 37 | * Greater or equals 38 | */ 39 | const GE = 'GE'; 40 | 41 | /** 42 | * Less or equals 43 | */ 44 | const LE = 'LE'; 45 | } 46 | -------------------------------------------------------------------------------- /src/Event/ResponseReceivedEvent.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class ResponseReceivedEvent extends Event 15 | { 16 | /** 17 | * @var ResponseInterface Response 18 | */ 19 | private $response; 20 | 21 | /** 22 | * Constructor. 23 | * 24 | * @param ResponseInterface $response Response 25 | */ 26 | public function __construct(ResponseInterface $response) 27 | { 28 | $this->response = $response; 29 | } 30 | 31 | /** 32 | * Get response 33 | * 34 | * @return ResponseInterface Response 35 | */ 36 | public function getResponse(): ResponseInterface 37 | { 38 | return $this->response; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Enum/SubscribersPostRequest/MatchingMode.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | final class MatchingMode extends Enum 21 | { 22 | /** 23 | * Email 24 | */ 25 | const EMAIL = 'Email'; 26 | 27 | /** 28 | * Custom subscriber ID 29 | */ 30 | const CUSTOMER_SUBSCRIBER_ID = 'CustomSubscriberId'; 31 | 32 | /** 33 | * Subscriber ID 34 | */ 35 | const ID = 'Id'; 36 | 37 | /** 38 | * Subscriber's phone 39 | */ 40 | const PHONE = 'Phone'; 41 | } 42 | -------------------------------------------------------------------------------- /src/Exception/ParseResponseException.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class ParseResponseException extends ExpertSenderApiException 14 | { 15 | /** 16 | * Constructor 17 | * 18 | * @param string $message Message 19 | * @param ResponseInterface $response Response 20 | * 21 | * @return static Exception while parse ExpertSender API's response 22 | */ 23 | public static function createFromResponse(string $message, ResponseInterface $response) 24 | { 25 | return new static( 26 | sprintf( 27 | '%s. Content: [%s...]', 28 | $message, 29 | substr($response->getContent(), 0, 100) 30 | ) 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Request/DataTablesClearTableRequestTest.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class DataTablesClearTableRequestTest extends \PHPUnit_Framework_TestCase 16 | { 17 | /** 18 | * Test 19 | */ 20 | public function testCommonUsage() 21 | { 22 | $request = new DataTablesClearTableRequest('table-name'); 23 | Assert::assertEquals([], $request->getQueryParams()); 24 | Assert::assertEquals('/v2/Api/DataTablesClearTable', $request->getUri()); 25 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::POST())); 26 | Assert::assertEquals('table-name', $request->toXml()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Request/TimeGetRequest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class TimeGetRequest implements RequestInterface 15 | { 16 | /** 17 | * {@inheritdoc} 18 | */ 19 | public function toXml(): string 20 | { 21 | return ''; 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function getMethod(): HttpMethod 28 | { 29 | return HttpMethod::GET(); 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | public function getUri(): string 36 | { 37 | return '/v2/Api/Time'; 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | */ 43 | public function getQueryParams(): array 44 | { 45 | return []; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Request/SegmentsGetRequest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class SegmentsGetRequest implements RequestInterface 15 | { 16 | /** 17 | * {@inheritdoc} 18 | */ 19 | public function toXml(): string 20 | { 21 | return ''; 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | public function getQueryParams(): array 28 | { 29 | return []; 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | public function getMethod(): HttpMethod 36 | { 37 | return HttpMethod::GET(); 38 | } 39 | 40 | /** 41 | * {@inheritdoc} 42 | */ 43 | public function getUri(): string 44 | { 45 | return '/v2/Api/Segments'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Model/DataTablesGetDataPostRequest/WhereCondition.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class WhereCondition extends \Citilink\ExpertSenderApi\Model\WhereCondition 16 | { 17 | /** 18 | * Constructor. 19 | * 20 | * @param string $columnName Column name 21 | * @param Operator $operator Operator 22 | * @param float|int|string $value Value 23 | */ 24 | public function __construct($columnName, Operator $operator, $value) 25 | { 26 | @trigger_error('use \Citilink\ExpertSenderApi\Model\WhereCondition instead', E_USER_DEPRECATED); 27 | 28 | parent::__construct($columnName, $operator, $value); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Traits/WhereConditionToXmlConverterTrait.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | trait WhereConditionToXmlConverterTrait 14 | { 15 | /** 16 | * Convert where condition into xml 17 | * 18 | * @param WhereCondition $whereCondition Where condition 19 | * @param \XMLWriter $xmlWriter Xml writer 20 | */ 21 | public function convertWhereConditionToXml(WhereCondition $whereCondition, \XMLWriter $xmlWriter) 22 | { 23 | $xmlWriter->startElement('Where'); 24 | $xmlWriter->writeElement('ColumnName', $whereCondition->getColumnName()); 25 | $xmlWriter->writeElement('Operator', $whereCondition->getOperator()->getValue()); 26 | $xmlWriter->writeElement('Value', $whereCondition->getValue()); 27 | $xmlWriter->endElement(); // Where 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/Request/SubscribersDeleteRequestTest.php: -------------------------------------------------------------------------------- 1 | toXml()); 16 | Assert::assertEquals('/v2/Api/Subscribers', $request->getUri()); 17 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::DELETE())); 18 | Assert::assertEquals(['id' => 12, 'listId' => 25], $request->getQueryParams()); 19 | } 20 | 21 | public function testCreateWithEmail() 22 | { 23 | $request = SubscribersDeleteRequest::createFromEmail('mail@mail.com'); 24 | Assert::assertEquals(['email' => 'mail@mail.com'], $request->getQueryParams()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Exception/TryToAccessDataFromErrorResponseException.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class TryToAccessDataFromErrorResponseException extends ExpertSenderApiException 14 | { 15 | /** 16 | * Constructor 17 | * 18 | * @param ResponseInterface $response ExpertSender API's Response 19 | * 20 | * @return static Exception of get data on not success response 21 | */ 22 | public static function createFromResponse(ResponseInterface $response) 23 | { 24 | return new static( 25 | sprintf( 26 | 'Trying to get data from not successful response. Response content: ' 27 | . '[%s], HTTP status code: %d', 28 | $response->getContent(), 29 | $response->getHttpStatusCode() 30 | ) 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Model/SegmentsGetResponse/Segment.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class Segment 12 | { 13 | /** 14 | * @var int Identifier 15 | */ 16 | private $id; 17 | 18 | /** 19 | * @var string Name 20 | */ 21 | private $name; 22 | 23 | /** 24 | * Constructor. 25 | * 26 | * @param int $id Identifier 27 | * @param string $name Name 28 | */ 29 | public function __construct(int $id, string $name) 30 | { 31 | $this->id = $id; 32 | $this->name = $name; 33 | } 34 | 35 | /** 36 | * Get identifier 37 | * 38 | * @return int Identifier 39 | */ 40 | public function getId(): int 41 | { 42 | return $this->id; 43 | } 44 | 45 | /** 46 | * Get name 47 | * 48 | * @return string Name 49 | */ 50 | public function getName(): string 51 | { 52 | return $this->name; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Response/TransactionalPostResponse.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class TransactionalPostResponse extends SpecificXmlMethodResponse 15 | { 16 | /** 17 | * Get GUID of sent message 18 | * 19 | * This GUID only shows when set returnGuid=true in {@see PostTransactionalRequest} 20 | * 21 | * @return string|null GUID of sent message 22 | */ 23 | public function getGuid(): ?string 24 | { 25 | if (!$this->isOk()) { 26 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 27 | } 28 | 29 | $matches = []; 30 | if (preg_match('#(.*)#', $this->getContent(), $matches)) { 31 | return $matches[1]; 32 | } 33 | 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Citilink 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/Enum/BouncesGetRequest/BounceType.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class BounceType extends Enum 20 | { 21 | /** 22 | * Email does not exist 23 | */ 24 | const USER_UNKNOWN = 1; 25 | 26 | /** 27 | * Mailbox is full or otherwise temporary inaccessible 28 | */ 29 | const MAILBOX_FULL = 2; 30 | 31 | /** 32 | * Message blocked, usually for spam-related reasons 33 | */ 34 | const BLOCKED = 3; 35 | 36 | /** 37 | * Unknown reason when bounce cannot be classified 38 | */ 39 | const UNKNOWN = 6; 40 | 41 | /** 42 | * Other bounce reason. This category contains transport-related issues, mail server bugs etc 43 | */ 44 | const OTHER = 7; 45 | } 46 | -------------------------------------------------------------------------------- /src/Enum/DataType.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | final class DataType extends Enum 22 | { 23 | /** 24 | * Boolean 25 | */ 26 | const BOOLEAN = 'boolean'; 27 | 28 | /** 29 | * Double 30 | */ 31 | const DOUBLE = 'double'; 32 | 33 | /** 34 | * String 35 | */ 36 | const STRING = 'string'; 37 | 38 | /** 39 | * Integer 40 | */ 41 | const INTEGER = 'int'; 42 | 43 | /** 44 | * Date 45 | */ 46 | const DATE = 'date'; 47 | 48 | /** 49 | * DateTime 50 | */ 51 | const DATETIME = 'dateTime'; 52 | 53 | /** 54 | * Decimal 55 | */ 56 | const DECIMAL = 'decimal'; 57 | } 58 | -------------------------------------------------------------------------------- /src/Traits/ColumnToXmlConverterTrait.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | trait ColumnToXmlConverterTrait 14 | { 15 | /** 16 | * Converts column to xml element 17 | * 18 | * @param Column $column Column 19 | * @param \XMLWriter $xmlWriter Xml writer 20 | */ 21 | protected function convertColumnToXml(Column $column, \XMLWriter $xmlWriter): void 22 | { 23 | $xmlWriter->startElement('Column'); 24 | $xmlWriter->writeElement('Name', $column->getName()); 25 | $value = $column->getValue(); 26 | if ($value === null) { 27 | $xmlWriter->startElement('Value'); 28 | $xmlWriter->writeAttributeNS('xsi', 'nil', null, 'true'); 29 | $xmlWriter->endElement(); // Value 30 | } else { 31 | $xmlWriter->writeElement('Value', $column->getValue()); 32 | } 33 | 34 | $xmlWriter->endElement(); // Column 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Model/SubscribersPostRequest/Property.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Property 14 | { 15 | /** 16 | * @var int ID 17 | */ 18 | protected $id; 19 | 20 | /** 21 | * @var Value Value 22 | */ 23 | private $value; 24 | 25 | /** 26 | * Constructor 27 | * 28 | * @param int $id ID 29 | * @param Value $value Value 30 | */ 31 | public function __construct(int $id, Value $value) 32 | { 33 | Assert::notEmpty($id); 34 | $this->id = $id; 35 | $this->value = $value; 36 | } 37 | 38 | /** 39 | * Get ID 40 | * 41 | * @return int ID 42 | */ 43 | public function getId(): int 44 | { 45 | return $this->id; 46 | } 47 | 48 | /** 49 | * Get value 50 | * 51 | * @return Value Value 52 | */ 53 | public function getValue(): Value 54 | { 55 | return $this->value; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Response/SubscribersGetLongResponse.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class SubscribersGetLongResponse extends SubscribersGetShortResponse 14 | { 15 | /** 16 | * Get stop-lists which contains subscriber 17 | * 18 | * @return array Stop-lists which contains subscriber [ => ''] 19 | */ 20 | public function getSuppressionStopLists(): array 21 | { 22 | if (!$this->isOk()) { 23 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 24 | } 25 | 26 | $xml = $this->getSimpleXml(); 27 | $nodes = $xml->xpath('/ApiResponse/Data/EmailInSuppressionLists/SuppressionList'); 28 | $suppressionLists = []; 29 | foreach ($nodes as $node) { 30 | $suppressionLists[intval($node->Id)] = strval($node->Name); 31 | } 32 | 33 | return $suppressionLists; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Enum/BouncesGetResponse/BounceType.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class BounceType extends Enum 20 | { 21 | /** 22 | * Email does not exist 23 | */ 24 | const USER_UNKNOWN = 'UserUnknown'; 25 | 26 | /** 27 | * Mailbox is full or otherwise temporary inaccessible 28 | */ 29 | const MAILBOX_FULL = 'MailboxFull'; 30 | 31 | /** 32 | * Message blocked, usually for spam-related reasons 33 | */ 34 | const BLOCKED = 'Blocked'; 35 | 36 | /** 37 | * Unknown reason when bounce cannot be classified 38 | */ 39 | const UNKNOWN = 'Unknown'; 40 | 41 | /** 42 | * Other bounce reason. This category contains transport-related issues, mail server bugs etc 43 | */ 44 | const OTHER = 'Other'; 45 | } 46 | -------------------------------------------------------------------------------- /src/Response/BouncesGetResponse.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class BouncesGetResponse extends SpecificCsvMethodResponse 17 | { 18 | /** 19 | * Get bounces 20 | * 21 | * @return Bounce[]|\Generator Bounces 22 | */ 23 | public function getBounces(): \Generator 24 | { 25 | if (!$this->isOk()) { 26 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 27 | } 28 | 29 | foreach ($this->getCsvReader()->fetchAll() as $row) { 30 | yield new Bounce( 31 | new \DateTime($row['Date']), 32 | $row['Email'], 33 | $row['BounceCode'], 34 | new BounceType($row['BounceType']) 35 | ); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Model/Column.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Column 14 | { 15 | /** 16 | * @var string Name 17 | */ 18 | private $name; 19 | 20 | /** 21 | * @var string|null Value 22 | */ 23 | private $value; 24 | 25 | /** 26 | * Constructor 27 | * 28 | * @param $name 29 | * @param int|float|string|null $value 30 | */ 31 | public function __construct(string $name, $value) 32 | { 33 | Assert::nullOrScalar($value); 34 | Assert::notEmpty($name); 35 | $this->name = $name; 36 | $this->value = $value !== null ? strval($value) : null; 37 | } 38 | 39 | /** 40 | * Get name 41 | * 42 | * @return string Name 43 | */ 44 | public function getName(): string 45 | { 46 | return $this->name; 47 | } 48 | 49 | /** 50 | * Get value 51 | * 52 | * @return string|null Value 53 | */ 54 | public function getValue(): ?string 55 | { 56 | return $this->value; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/Response/CountResponseTest.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class CountResponseTest extends \PHPUnit_Framework_TestCase 16 | { 17 | /** 18 | * Test 19 | */ 20 | public function testGetCount() 21 | { 22 | $xml = '25'; 24 | $response = new CountResponse( 25 | new Response( 26 | new \GuzzleHttp\Psr7\Response( 27 | 200, 28 | ['Content-Type' => 'text/xml', 'Content-Length' => strlen($xml)], 29 | $xml 30 | ) 31 | ) 32 | ); 33 | 34 | Assert::assertTrue($response->isOk()); 35 | Assert::assertFalse($response->isEmpty()); 36 | Assert::assertEquals(25, $response->getCount()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Model/TransactionalPostRequest/Snippet.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Snippet 14 | { 15 | /** 16 | * @var string Name 17 | */ 18 | private $name; 19 | 20 | /** 21 | * @var string Value 22 | */ 23 | private $value; 24 | 25 | /** 26 | * Constructor. 27 | * 28 | * @param string $name Name 29 | * @param string|int|float $value Value 30 | */ 31 | public function __construct(string $name, $value) 32 | { 33 | Assert::notEmpty($name); 34 | Assert::scalar($value); 35 | $this->name = $name; 36 | $this->value = strval($value); 37 | } 38 | 39 | /** 40 | * Get name 41 | * 42 | * @return string Name 43 | */ 44 | public function getName(): string 45 | { 46 | return $this->name; 47 | } 48 | 49 | /** 50 | * Get value 51 | * 52 | * @return string Value 53 | */ 54 | public function getValue(): string 55 | { 56 | return $this->value; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Response/ActivitiesGetResponse/ConfirmationsActivityGetResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class ConfirmationsActivityGetResponse extends SpecificCsvMethodResponse 16 | { 17 | /** 18 | * Get subscriptions 19 | * 20 | * @return ConfirmationActivity[]|iterable Subscriptions 21 | */ 22 | public function getConfirmations(): iterable 23 | { 24 | if (!$this->isOk()) { 25 | throw new TryToAccessDataFromErrorResponseException($this); 26 | } 27 | 28 | foreach ($this->getCsvReader()->fetchAll() as $row) { 29 | yield new ConfirmationActivity( 30 | $row['Email'], 31 | new \DateTime($row['Date']), 32 | intval($row['ListId']), 33 | $row['ListName'] 34 | ); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Response/ActivitiesGetResponse/SubscriptionsActivityGetResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class SubscriptionsActivityGetResponse extends SpecificCsvMethodResponse 16 | { 17 | /** 18 | * Get subscriptions 19 | * 20 | * @return SubscriptionActivity[]|iterable Subscriptions 21 | */ 22 | public function getSubscriptions(): iterable 23 | { 24 | if (!$this->isOk()) { 25 | throw new TryToAccessDataFromErrorResponseException($this); 26 | } 27 | 28 | foreach ($this->getCsvReader()->fetchAll() as $row) { 29 | yield new SubscriptionActivity( 30 | $row['Email'], 31 | new \DateTime($row['Date']), 32 | intval($row['ListId']), 33 | $row['ListName'] 34 | ); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Model/ActivitiesGetResponse/AbstractActivity.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | abstract class AbstractActivity 12 | { 13 | /** 14 | * @var string Subscriber's email 15 | */ 16 | private $email; 17 | 18 | /** 19 | * @var \DateTime Subscription date 20 | */ 21 | private $date; 22 | 23 | /** 24 | * AbstractActivity constructor. 25 | * 26 | * @param string $email Subscriber's email 27 | * @param \DateTime $date Subscription date 28 | */ 29 | public function __construct(string $email, \DateTime $date) 30 | { 31 | $this->email = $email; 32 | $this->date = $date; 33 | } 34 | 35 | /** 36 | * Get subscriber's email 37 | * 38 | * @return string Subscriber's email 39 | */ 40 | public function getEmail(): string 41 | { 42 | return $this->email; 43 | } 44 | 45 | /** 46 | * Get subscription date 47 | * 48 | * @return \DateTime Subscription date 49 | */ 50 | public function getDate(): \DateTime 51 | { 52 | return $this->date; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/Request/SnoozedSubscribersGetRequestTest.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class SnoozedSubscribersGetRequestTest extends \PHPUnit_Framework_TestCase 16 | { 17 | /** 18 | * Test 19 | */ 20 | public function testCommonUsage() 21 | { 22 | $request = new SnoozedSubscribersGetRequest( 23 | [1, 2, 3, 4], 24 | new \DateTime('2017-01-01'), 25 | new \DateTime('2017-02-02') 26 | ); 27 | 28 | Assert::assertEquals('', $request->toXml()); 29 | Assert::assertEquals( 30 | [ 31 | 'listIds' => '1,2,3,4', 32 | 'startDate' => '2017-01-01', 33 | 'endDate' => '2017-02-02', 34 | ], 35 | $request->getQueryParams() 36 | ); 37 | Assert::assertEquals('/v2/Api/SnoozedSubscribers', $request->getUri()); 38 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::GET())); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Response/SubscribersPostResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class SubscribersPostResponse extends SpecificXmlMethodResponse 16 | { 17 | /** 18 | * Get subscribers info after add/edit 19 | * 20 | * @return SubscriberData[] Subscribers info after add/edit 21 | */ 22 | public function getChangedSubscribersData(): array 23 | { 24 | $nodes = $this->getSimpleXml()->xpath('/ApiResponse/Data/SubscriberData'); 25 | $subscriberDataList = []; 26 | foreach ($nodes as $node) { 27 | $subscriberDataList[] = new SubscriberData( 28 | strval($node->Email), 29 | intval($node->Id), 30 | Utils::convertStringBooleanEquivalentToBool(strval($node->WasAdded)), 31 | Utils::convertStringBooleanEquivalentToBool(strval($node->WasIgnored)) 32 | ); 33 | } 34 | 35 | return $subscriberDataList; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Response/SnoozedSubscribersGetResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class SnoozedSubscribersGetResponse extends SpecificXmlMethodResponse 16 | { 17 | /** 18 | * Get snoozed subscribers 19 | * 20 | * @return SnoozedSubscriber[]|iterable Snoozed subscribers 21 | */ 22 | public function getSnoozedSubscribers(): iterable 23 | { 24 | if (!$this->isOk()) { 25 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 26 | } 27 | 28 | $nodes = $this->getSimpleXml()->xpath('/ApiResponse/Data/SnoozedSubscribers/SnoozedSubscriber'); 29 | foreach ($nodes as $node) { 30 | yield new SnoozedSubscriber( 31 | strval($node->Email), 32 | intval($node->ListId), 33 | new \DateTime(strval($node->SnoozedUntil)) 34 | ); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/Request/TriggersPostRequestTest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class TriggersPostRequestTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * Test 20 | */ 21 | public function testCommonUsage() 22 | { 23 | $request = new TriggersPostRequest( 24 | 24, 25 | [ 26 | Receiver::createFromEmail('mail@mail.com'), 27 | Receiver::createFromId(23), 28 | ] 29 | ); 30 | 31 | $xml = 'mail@mail.com' 32 | . '23'; 33 | Assert::assertEquals($xml, $request->toXml()); 34 | Assert::assertEquals([], $request->getQueryParams()); 35 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::POST())); 36 | Assert::assertEquals('/v2/Api/Triggers/24', $request->getUri()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Response/TimeGetResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class TimeGetResponse extends SpecificXmlMethodResponse 16 | { 17 | /** 18 | * Get server time 19 | * 20 | * @throws ParseResponseException If response is invalid, or Data content is not valid datetime string 21 | * 22 | * @return \DateTime Server time 23 | */ 24 | public function getServerTime(): \DateTime 25 | { 26 | if (!$this->isOk()) { 27 | throw new TryToAccessDataFromErrorResponseException(); 28 | } 29 | 30 | $dataAsString = strval($this->getSimpleXml()->xpath('/ApiResponse/Data')[0]); 31 | try { 32 | return new \DateTime($dataAsString); 33 | } catch (\Exception $e) { 34 | throw new ParseResponseException( 35 | sprintf('Cant\'t create DateTime object from string "%s"', $dataAsString), 36 | 0, 37 | $e 38 | ); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Response/GetSegmentSizeGetResponse.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class GetSegmentSizeGetResponse extends SpecificXmlMethodResponse 15 | { 16 | /** 17 | * Get size of segment 18 | * 19 | * @return int Size of segment 20 | */ 21 | public function getSize(): int 22 | { 23 | if (!$this->isOk()) { 24 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 25 | } 26 | 27 | return intval($this->getSimpleXml()->xpath('/ApiResponse/Data/Size')[0]); 28 | } 29 | 30 | /** 31 | * Get date of last segment size recalculation 32 | * 33 | * @return \DateTime Date of last segment size recalculation 34 | */ 35 | public function getCountDate(): \DateTime 36 | { 37 | if (!$this->isOk()) { 38 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 39 | } 40 | 41 | return new \DateTime(strval($this->getSimpleXml()->xpath('/ApiResponse/Data/CountDate')[0])); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Request/GetSegmentSizeGetRequest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class GetSegmentSizeGetRequest implements RequestInterface 15 | { 16 | /** 17 | * @var int Segment ID 18 | */ 19 | private $segmentId; 20 | 21 | /** 22 | * Constructor. 23 | * 24 | * @param int $segmentId Segment ID 25 | */ 26 | public function __construct($segmentId) 27 | { 28 | $this->segmentId = $segmentId; 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function toXml(): string 35 | { 36 | return ''; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function getQueryParams(): array 43 | { 44 | return ['id' => $this->segmentId]; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function getMethod(): HttpMethod 51 | { 52 | return HttpMethod::GET(); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function getUri(): string 59 | { 60 | return '/v2/Api/GetSegmentSize'; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "citilink/expert-sender-api", 3 | "description": "API for expert sender service", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "LinugaLeo", 8 | "email": "backend@lingualeo.com" 9 | }, 10 | { 11 | "name": "Citilink", 12 | "email": "devops@citilink.ru" 13 | } 14 | ], 15 | "require": { 16 | "php": "^7.1.0", 17 | "psr/log": "^1.0.0", 18 | "myclabs/php-enum": "^1.5.2", 19 | "guzzlehttp/guzzle": "^6.0.0", 20 | "symfony/event-dispatcher": "^3.0.0|^4.0.0|^5.0.0" 21 | }, 22 | "require-dev" : { 23 | "phpunit/phpunit" : "^5.0.0", 24 | "nikic/iter": "^1.5.0", 25 | "phpstan/phpstan": "^0.8.0" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "Citilink\\ExpertSenderApi\\": "src/" 30 | } 31 | }, 32 | "autoload-dev": { 33 | "psr-4" : { 34 | "Citilink\\ExpertSenderApi\\Tests\\": "tests/" 35 | } 36 | }, 37 | "scripts": { 38 | "phpunit": [ 39 | "vendor/bin/phpunit" 40 | ], 41 | "phpstan": [ 42 | "vendor/bin/phpstan analyze src tests -c phpstan.neon --level=7" 43 | ], 44 | "test": [ 45 | "@phpunit", 46 | "@phpstan" 47 | ] 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Response/ActivitiesGetResponse/OpensActivityGetResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class OpensActivityGetResponse extends SpecificCsvMethodResponse 16 | { 17 | /** 18 | * Get open activities 19 | * 20 | * @return OpenActivity[]|iterable Open activities 21 | */ 22 | public function getOpens(): iterable 23 | { 24 | if (!$this->isOk()) { 25 | throw new TryToAccessDataFromErrorResponseException($this); 26 | } 27 | 28 | foreach ($this->getCsvReader()->fetchAll() as $row) { 29 | yield new OpenActivity( 30 | $row['Email'], 31 | new \DateTime($row['Date']), 32 | intval($row['MessageId']), 33 | $row['MessageSubject'], 34 | isset($row['ListId']) ? intval($row['ListId']) : null, 35 | $row['ListName'] ?? null, 36 | $row['MessageGuid'] ?? null 37 | ); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Response/ActivitiesGetResponse/SendsActivityGetResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class SendsActivityGetResponse extends SpecificCsvMethodResponse 16 | { 17 | /** 18 | * Get send activities 19 | * 20 | * @return SendActivity[]|iterable Send activities 21 | */ 22 | public function getSends(): iterable 23 | { 24 | if (!$this->isOk()) { 25 | throw new TryToAccessDataFromErrorResponseException($this); 26 | } 27 | 28 | foreach ($this->getCsvReader()->fetchAll() as $row) { 29 | yield new SendActivity( 30 | $row['Email'], 31 | new \DateTime($row['Date']), 32 | intval($row['MessageId']), 33 | $row['MessageSubject'], 34 | isset($row['ListId']) ? intval($row['ListId']) : null, 35 | $row['ListName'] ?? null, 36 | $row['MessageGuid'] ?? null 37 | ); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Enum/RemovedSubscribersGetRequest/RemoveType.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | class RemoveType extends Enum 21 | { 22 | /** 23 | * Subscriber clicked unsubscribe link in email 24 | */ 25 | const OPT_OUT_LINK = 'OptOutLink'; 26 | 27 | /** 28 | * Removed manually using user interface (ExpertSender panel) 29 | */ 30 | const UI = 'Ui'; 31 | 32 | /** 33 | * Removed because limit of bounced messages was reached 34 | */ 35 | const BOUNCE_LIMIT = 'BounceLimit'; 36 | 37 | /** 38 | * Subscriber issued a spam complaint 39 | */ 40 | const COMPLAINT = 'Complaint'; 41 | 42 | /** 43 | * Removed because email server returned User Unknown bounce (email address does not exist) 44 | */ 45 | const USER_UNKNOWN = 'UserUnknown'; 46 | 47 | /** 48 | * Removed using API 49 | */ 50 | const API = 'Api'; 51 | } 52 | -------------------------------------------------------------------------------- /src/Model/ActivitiesGetResponse/ConfirmationActivity.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class ConfirmationActivity extends AbstractActivity 12 | { 13 | /** 14 | * @var int List ID 15 | */ 16 | private $listId; 17 | 18 | /** 19 | * @var string List name 20 | */ 21 | private $listName; 22 | 23 | /** 24 | * Constructor. 25 | * 26 | * @param string $email Subscriber's email 27 | * @param \DateTime $date Confirmation date 28 | * @param int $listId List ID 29 | * @param string $listName List name 30 | */ 31 | public function __construct(string $email, \DateTime $date, int $listId, string $listName) 32 | { 33 | parent::__construct($email, $date); 34 | $this->listId = $listId; 35 | $this->listName = $listName; 36 | } 37 | 38 | /** 39 | * Get List ID 40 | * 41 | * @return int List ID 42 | */ 43 | public function getListId(): int 44 | { 45 | return $this->listId; 46 | } 47 | 48 | /** 49 | * Get list name 50 | * 51 | * @return string List name 52 | */ 53 | public function getListName(): string 54 | { 55 | return $this->listName; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Model/ActivitiesGetResponse/SubscriptionActivity.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class SubscriptionActivity extends AbstractActivity 12 | { 13 | /** 14 | * @var int List ID 15 | */ 16 | private $listId; 17 | 18 | /** 19 | * @var string List name 20 | */ 21 | private $listName; 22 | 23 | /** 24 | * Constructor. 25 | * 26 | * @param string $email Subscriber's email 27 | * @param \DateTime $date Subscription date 28 | * @param int $listId List ID 29 | * @param string $listName List name 30 | */ 31 | public function __construct(string $email, \DateTime $date, int $listId, string $listName) 32 | { 33 | parent::__construct($email, $date); 34 | $this->listId = $listId; 35 | $this->listName = $listName; 36 | } 37 | 38 | /** 39 | * Get List ID 40 | * 41 | * @return int List ID 42 | */ 43 | public function getListId(): int 44 | { 45 | return $this->listId; 46 | } 47 | 48 | /** 49 | * Get list name 50 | * 51 | * @return string List name 52 | */ 53 | public function getListName(): string 54 | { 55 | return $this->listName; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Model/ErrorMessage.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class ErrorMessage 12 | { 13 | /** 14 | * @var string Message 15 | */ 16 | private $message; 17 | 18 | /** 19 | * @var array Options of error message 20 | */ 21 | private $options; 22 | 23 | /** 24 | * Constructor. 25 | * 26 | * @param string $message Message 27 | * @param array $options Options of error message 28 | */ 29 | public function __construct(string $message, array $options = []) 30 | { 31 | $this->message = $message; 32 | $this->options = $options; 33 | } 34 | 35 | /** 36 | * Get message 37 | * 38 | * @return string Message 39 | */ 40 | public function getMessage(): string 41 | { 42 | return $this->message; 43 | } 44 | 45 | /** 46 | * Get options of error message 47 | * 48 | * @return array Options of error message 49 | */ 50 | public function getOptions(): array 51 | { 52 | return $this->options; 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | public function __toString(): string 59 | { 60 | return $this->message . '[' . implode(', ', $this->options) . ']'; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Enum/ActivitiesGetRequest/BounceReason.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | class BounceReason extends Enum 21 | { 22 | /** 23 | * Email does not exist. 24 | */ 25 | const USER_UNKNOWN = 'UserUnknown'; 26 | 27 | /** 28 | * Subscriber’s mailbox is full or otherwise temporary inaccessible. 29 | */ 30 | const MAILBOX_FULL = 'MailboxFull'; 31 | 32 | /** 33 | * Sent message was blocked, possibly for spam-related reasons. 34 | */ 35 | const BLOCKED = 'Blocked'; 36 | 37 | /** 38 | * Mailbox returned automated “out of office” reply. 39 | */ 40 | const OUT_OF_OFFICE = 'OutOfOffice'; 41 | 42 | /** 43 | * Unknown reason. 44 | */ 45 | const UNKNOWN = 'Unknown'; 46 | 47 | /** 48 | * Other bounce reason. This category contains transport-related issues, mail server bugs etc. 49 | */ 50 | const OTHER = 'Other'; 51 | } 52 | -------------------------------------------------------------------------------- /src/Enum/SubscriberPropertySource.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | final class SubscriberPropertySource extends Enum 21 | { 22 | /** 23 | * Property was added/modified using a subscription webform 24 | */ 25 | const WEB = 'Web'; 26 | 27 | /** 28 | * Property was added/modified manually by user in ExpertSender application 29 | */ 30 | const PANEL = 'Panel'; 31 | 32 | /** 33 | * Property was added/modified during an import 34 | */ 35 | const IMPORT = 'Import'; 36 | 37 | /** 38 | * Property was added/modified using ExpertSender REST API 39 | */ 40 | const API = 'Api'; 41 | 42 | /** 43 | * Subscriber added/modified the property on Preference Center page 44 | */ 45 | const PREF_CENTER = 'PrefCenter'; 46 | 47 | /** 48 | * Source not set 49 | */ 50 | const NOT_SET = 'NotSet'; 51 | } 52 | -------------------------------------------------------------------------------- /src/Response/ActivitiesGetResponse/ComplaintsActivityGetResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class ComplaintsActivityGetResponse extends SpecificCsvMethodResponse 16 | { 17 | /** 18 | * Get complaint activities 19 | * 20 | * @return ComplaintActivity[]|iterable Complaint activities 21 | */ 22 | public function getComplaints(): iterable 23 | { 24 | if (!$this->isOk()) { 25 | throw new TryToAccessDataFromErrorResponseException($this); 26 | } 27 | 28 | foreach ($this->getCsvReader()->fetchAll() as $row) { 29 | yield new ComplaintActivity( 30 | $row['Email'], 31 | new \DateTime($row['Date']), 32 | intval($row['MessageId']), 33 | $row['MessageSubject'], 34 | isset($row['ListId']) ? intval($row['ListId']) : null, 35 | $row['ListName'] ?? null, 36 | $row['MessageGuid'] ?? null 37 | ); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Response/ActivitiesGetResponse/GoalsActivityGetResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class GoalsActivityGetResponse extends SpecificCsvMethodResponse 16 | { 17 | /** 18 | * Get goal activities 19 | * 20 | * @return GoalActivity[]|iterable Goal activities 21 | */ 22 | public function getGoals(): iterable 23 | { 24 | if (!$this->isOk()) { 25 | throw new TryToAccessDataFromErrorResponseException($this); 26 | } 27 | 28 | foreach ($this->getCsvReader()->fetchAll() as $row) { 29 | yield new GoalActivity( 30 | $row['Email'], 31 | new \DateTime($row['Date']), 32 | intval($row['MessageId']), 33 | $row['MessageSubject'], 34 | intval($row['GoalValue']), 35 | isset($row['ListId']) ? intval($row['ListId']) : null, 36 | $row['ListName'] ?? null, 37 | $row['MessageGuid'] ?? null 38 | ); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Request/SegmentsGetRequestTest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class SegmentsGetRequestTest extends \PHPUnit_Framework_TestCase 15 | { 16 | /** 17 | * Test 18 | */ 19 | public function testToXmlShouldReturnEmptyString() 20 | { 21 | $request = new SegmentsGetRequest(); 22 | 23 | $this->assertSame('', $request->toXml()); 24 | } 25 | 26 | /** 27 | * Test 28 | */ 29 | public function testGetQueryParamsShouldReturnEmptyArray() 30 | { 31 | $request = new SegmentsGetRequest(); 32 | 33 | $this->assertSame([], $request->getQueryParams()); 34 | } 35 | 36 | /** 37 | * Test 38 | */ 39 | public function testGetMethodShouldReturnGetHttpMethod() 40 | { 41 | $request = new SegmentsGetRequest(); 42 | 43 | $this->assertTrue($request->getMethod()->equals(HttpMethod::GET())); 44 | } 45 | 46 | /** 47 | * Test 48 | */ 49 | public function testGetUriShouldReturnProperUri() 50 | { 51 | $request = new SegmentsGetRequest(); 52 | 53 | $this->assertSame('/v2/Api/Segments', $request->getUri()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Model/DataTablesGetDataPostRequest/OrderByRule.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class OrderByRule 15 | { 16 | /** 17 | * @var string Column name 18 | */ 19 | private $columnName; 20 | 21 | /** 22 | * @var Direction Direction 23 | */ 24 | private $direction; 25 | 26 | /** 27 | * Constructor 28 | * 29 | * @param string $columnName Column name 30 | * @param Direction $direction Sort order 31 | */ 32 | public function __construct(string $columnName, Direction $direction) 33 | { 34 | Assert::notEmpty($columnName); 35 | $this->columnName = $columnName; 36 | $this->direction = $direction; 37 | } 38 | 39 | /** 40 | * Get column name 41 | * 42 | * @return string Column name 43 | */ 44 | public function getColumnName(): string 45 | { 46 | return $this->columnName; 47 | } 48 | 49 | /** 50 | * Get direction 51 | * 52 | * @return Direction Direction 53 | */ 54 | public function getDirection(): Direction 55 | { 56 | return $this->direction; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Response/DataTablesGetTablesSummaryResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class DataTablesGetTablesSummaryResponse extends SpecificXmlMethodResponse 16 | { 17 | /** 18 | * Get tables 19 | * 20 | * @return TableSummary[]|iterable Tables 21 | */ 22 | public function getTables(): iterable 23 | { 24 | if (!$this->isOk()) { 25 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 26 | } 27 | 28 | $xml = $this->getSimpleXml(); 29 | $nodes = $xml->xpath('/ApiResponse/TableList/Tables/Table'); 30 | foreach ($nodes as $node) { 31 | yield new TableSummary( 32 | intval($node->Id), 33 | strval($node->Name), 34 | intval($node->ColumnsCount), 35 | intval($node->RelationshipsCount), 36 | intval($node->RelationshipsDestinationCount), 37 | intval($node->Rows), 38 | floatval($node->Size) 39 | ); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/Request/DataTablesGetTablesRequestTest.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class DataTablesGetTablesRequestTest extends \PHPUnit_Framework_TestCase 16 | { 17 | /** 18 | * Test 19 | */ 20 | public function testCreateWithTableName() 21 | { 22 | $request = new DataTablesGetTablesRequest('table-name'); 23 | Assert::assertEquals(['name' => 'table-name'], $request->getQueryParams()); 24 | Assert::assertEquals('/v2/Api/DataTablesGetTables', $request->getUri()); 25 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::GET())); 26 | Assert::assertEquals('', $request->toXml()); 27 | } 28 | 29 | /** 30 | * Test 31 | */ 32 | public function testCreateWithoutTableName() 33 | { 34 | $request = new DataTablesGetTablesRequest(null); 35 | Assert::assertEquals([], $request->getQueryParams()); 36 | Assert::assertEquals('/v2/Api/DataTablesGetTables', $request->getUri()); 37 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::GET())); 38 | Assert::assertEquals('', $request->toXml()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Response/ActivitiesGetResponse/ClicksActivityGetResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class ClicksActivityGetResponse extends SpecificCsvMethodResponse 16 | { 17 | /** 18 | * Get open activities 19 | * 20 | * @return ClickActivity[]|iterable Open activities 21 | */ 22 | public function getClicks(): iterable 23 | { 24 | if (!$this->isOk()) { 25 | throw new TryToAccessDataFromErrorResponseException($this); 26 | } 27 | 28 | foreach ($this->getCsvReader()->fetchAll() as $row) { 29 | yield new ClickActivity( 30 | $row['Email'], 31 | new \DateTime($row['Date']), 32 | intval($row['MessageId']), 33 | $row['MessageSubject'], 34 | $row['Url'], 35 | $row['Title'], 36 | isset($row['ListId']) ? intval($row['ListId']) : null, 37 | $row['ListName'] ?? null, 38 | $row['MessageGuid'] ?? null 39 | ); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Response/SubscribersGetFullResponse.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class SubscribersGetFullResponse extends SubscribersGetLongResponse 17 | { 18 | /** 19 | * @var SubscriberDataParser Subscriber data parse 20 | */ 21 | private $parser; 22 | 23 | /** 24 | * Constructor 25 | * 26 | * @param ResponseInterface $response Response of ExpertSender API 27 | */ 28 | public function __construct(ResponseInterface $response) 29 | { 30 | parent::__construct($response); 31 | 32 | $this->parser = new SubscriberDataParser(); 33 | } 34 | 35 | /** 36 | * Get subscriber's data 37 | * 38 | * @return SubscriberData Subscriber's data 39 | */ 40 | public function getSubscriberData(): SubscriberData 41 | { 42 | if (!$this->isOk()) { 43 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 44 | } 45 | 46 | return $this->parser->parse($this->getSimpleXml()->xpath('/ApiResponse/Data')[0]); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Enum/ActivitiesGetRequest/RemovalReason.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | final class RemovalReason extends Enum 21 | { 22 | /** 23 | * Subscriber has unsubscribed from link using an unsubscribe link or otherwise. 24 | */ 25 | const SUBSCRIBER = 'Subscriber'; 26 | 27 | /** 28 | * Subscriber was manually removed by user. 29 | */ 30 | const USER = 'User'; 31 | 32 | /** 33 | * Subscriber was automatically removed because of reaching bounce limit. 34 | */ 35 | const BOUNCE = 'Bounce'; 36 | 37 | /** 38 | * Subscriber was automatically removed after sending spam complaint. 39 | */ 40 | const SPAM = 'Spam'; 41 | 42 | /** 43 | * Subscriber was automatically removed because the email address does not exist (caused “user unknown” bounce). 44 | */ 45 | const USER_UNKNOWN = 'UserUnknown'; 46 | 47 | /** 48 | * Subscriber was removed using API. 49 | */ 50 | const API = 'Api'; 51 | } 52 | -------------------------------------------------------------------------------- /src/Response/ActivitiesGetResponse/BouncesActivityGetResponse.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class BouncesActivityGetResponse extends SpecificCsvMethodResponse 17 | { 18 | /** 19 | * Get removal activities 20 | * 21 | * @return BounceActivity[]|iterable Removal activities 22 | */ 23 | public function getBounces(): iterable 24 | { 25 | if (!$this->isOk()) { 26 | throw new TryToAccessDataFromErrorResponseException($this); 27 | } 28 | 29 | foreach ($this->getCsvReader()->fetchAll() as $row) { 30 | yield new BounceActivity( 31 | $row['Email'], 32 | new \DateTime($row['Date']), 33 | new BounceReason($row['Reason']), 34 | $row['DiagnosticCode'], 35 | isset($row['ListId']) ? intval($row['ListId']) : null, 36 | $row['ListName'] ?? null, 37 | $row['MessageGuid'] ?? null 38 | ); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Event/RequestExceptionThrown.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class RequestExceptionThrown extends Event 16 | { 17 | /** 18 | * @var RequestInterface Request 19 | */ 20 | private $request; 21 | 22 | /** 23 | * @var RequestException $exception 24 | */ 25 | private $exception; 26 | 27 | /** 28 | * Constructor 29 | * 30 | * @param RequestInterface $apiRequest Api request 31 | * @param RequestException $exception Thrown exception 32 | */ 33 | public function __construct(RequestInterface $apiRequest, RequestException $exception) 34 | { 35 | $this->request = $apiRequest; 36 | $this->exception = $exception; 37 | } 38 | 39 | /** 40 | * Get api request 41 | * 42 | * @return RequestInterface Api request 43 | */ 44 | public function getRequest(): RequestInterface 45 | { 46 | return $this->request; 47 | } 48 | 49 | /** 50 | * Get thrown exception 51 | * 52 | * @return RequestException Thrown exception 53 | */ 54 | public function getException(): RequestException 55 | { 56 | return $this->exception; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Exception/NotValidXmlException.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class NotValidXmlException extends ParseResponseException 12 | { 13 | /** 14 | * @var \LibXMLError[] Xml errors 15 | */ 16 | private $libXmlErrors = []; 17 | 18 | /** 19 | * Constructor. 20 | * 21 | * @param \LibXMLError[] $libXmlErrors LibXml errors 22 | * @param string $message Message 23 | * @param int $code Code 24 | * @param \Throwable|null $previous Previous exception 25 | */ 26 | public function __construct(array $libXmlErrors, string $message = "", int $code = 0, \Throwable $previous = null) 27 | { 28 | $errorsAsString = []; 29 | foreach ($libXmlErrors as $libXmlError) { 30 | $errorsAsString[] = $libXmlError->message; 31 | } 32 | 33 | $allErrorsAsString = implode('; ', $errorsAsString); 34 | 35 | $message = sprintf('%s. Errors: %s', $message, $allErrorsAsString); 36 | 37 | parent::__construct($message, $code, $previous); 38 | $this->libXmlErrors = $libXmlErrors; 39 | } 40 | 41 | /** 42 | * Get xml errors 43 | * 44 | * @return \LibXMLError[] Xml error 45 | */ 46 | public function getLibXmlErrors(): array 47 | { 48 | return $this->libXmlErrors; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Request/DataTablesClearTableRequest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class DataTablesClearTableRequest implements RequestInterface 15 | { 16 | /** 17 | * @var string Table name 18 | */ 19 | private $tableName; 20 | 21 | /** 22 | * Constructor. 23 | * 24 | * @param string $tableName Table name 25 | */ 26 | public function __construct(string $tableName) 27 | { 28 | $this->tableName = $tableName; 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function toXml(): string 35 | { 36 | $xmlWriter = new \XMLWriter(); 37 | $xmlWriter->openMemory(); 38 | 39 | $xmlWriter->writeElement('TableName', $this->tableName); 40 | 41 | return $xmlWriter->flush(); 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function getQueryParams(): array 48 | { 49 | return []; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getMethod(): HttpMethod 56 | { 57 | return HttpMethod::POST(); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function getUri(): string 64 | { 65 | return '/v2/Api/DataTablesClearTable'; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Response/ActivitiesGetResponse/RemovalsActivityGetResponse.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class RemovalsActivityGetResponse extends SpecificCsvMethodResponse 17 | { 18 | /** 19 | * Get removal activities 20 | * 21 | * @return RemovalActivity[]|iterable Removal activities 22 | */ 23 | public function getRemovals(): iterable 24 | { 25 | if (!$this->isOk()) { 26 | throw new TryToAccessDataFromErrorResponseException($this); 27 | } 28 | 29 | foreach ($this->getCsvReader()->fetchAll() as $row) { 30 | yield new RemovalActivity( 31 | $row['Email'], 32 | new \DateTime($row['Date']), 33 | intval($row['MessageId']), 34 | $row['MessageSubject'], 35 | new RemovalReason($row['Reason']), 36 | isset($row['ListId']) ? intval($row['ListId']) : null, 37 | $row['ListName'] ?? null, 38 | $row['MessageGuid'] ?? null 39 | ); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/Request/ActivitiesGetRequestTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class ActivitiesGetRequestTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testCommonUsage() 23 | { 24 | $request = new ActivitiesGetRequest( 25 | new \DateTime('2017-05-27'), 26 | ActivityType::COMPLAINTS(), 27 | ReturnColumnsSet::EXTENDED(), 28 | true, 29 | true 30 | ); 31 | 32 | Assert::assertEquals('/v2/Api/Activities', $request->getUri()); 33 | Assert::assertEquals( 34 | [ 35 | 'date' => '2017-05-27', 36 | 'type' => 'Complaints', 37 | 'columns' => 'Extended', 38 | 'returnTitle' => 'true', 39 | 'returnGuid' => 'true', 40 | ], 41 | $request->getQueryParams() 42 | ); 43 | Assert::assertEquals('', $request->toXml()); 44 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::GET())); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/CsvReader.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class CsvReader 14 | { 15 | /** 16 | * @var resource Stream 17 | */ 18 | private $stream; 19 | 20 | /** 21 | * Constructor. 22 | * 23 | * @param resource $stream Stream 24 | */ 25 | public function __construct($stream) 26 | { 27 | Assert::resource($stream); 28 | rewind($stream); 29 | $this->stream = $stream; 30 | } 31 | 32 | /** 33 | * Get Rows as associative arrays, where keys are column names 34 | * 35 | * @return iterable Rows as associative arrays, where keys are column names 36 | */ 37 | public function fetchAll(): iterable 38 | { 39 | // pass header 40 | $columnNames = fgetcsv($this->stream); 41 | 42 | // read line by line 43 | while (($row = fgetcsv($this->stream)) !== false) { 44 | // empty line protection, empty line equals [0 => null], and isset on null values always return false 45 | if (!isset($row[0])) { 46 | continue; 47 | } 48 | 49 | // convert to assoc array 50 | $assocRow = []; 51 | foreach ($columnNames as $index => $columnName) { 52 | $assocRow[$columnName] = $row[$index]; 53 | } 54 | 55 | yield $assocRow; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/Request/DataTablesDeleteRowPostRequestTest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class DataTablesDeleteRowPostRequestTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * Test 20 | */ 21 | public function testCommonUsage() 22 | { 23 | $request = new DataTablesDeleteRowPostRequest( 24 | 'table-name', 25 | [ 26 | new Column('Column1', 12), 27 | new Column('Column2', 12.5), 28 | new Column('Column3', 'string'), 29 | ] 30 | ); 31 | 32 | $xml = 'table-nameColumn112' 33 | . 'Column212.5Column3' 34 | . 'string'; 35 | Assert::assertEquals($xml, $request->toXml()); 36 | Assert::assertEquals([], $request->getQueryParams()); 37 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::POST())); 38 | Assert::assertEquals('/v2/Api/DataTablesDeleteRow', $request->getUri()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Response/SubscribersGetEventsHistoryResponse.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class SubscribersGetEventsHistoryResponse extends SpecificXmlMethodResponse 16 | { 17 | /** 18 | * Get events 19 | * 20 | * @throws TryToAccessDataFromErrorResponseException If response has errors 21 | * 22 | * @return Event[]|\Generator Events 23 | */ 24 | public function getEvents(): \Generator 25 | { 26 | if (!$this->isOk()) { 27 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 28 | } 29 | 30 | $nodes = $this->getSimpleXml()->xpath('/ApiResponse/Data/Events/Event'); 31 | foreach ($nodes as $node) { 32 | $event = new Event( 33 | new \DateTime(strval($node->StartDate)), 34 | new \DateTime(strval($node->EndDate)), 35 | strval($node->MessageType), 36 | strval($node->EventType), 37 | intval($node->EventCount), 38 | intval($node->MessageId), 39 | strval($node->MessageSubject) 40 | ); 41 | 42 | yield $event; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/Request/RemovedSubscriberGetRequestTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class RemovedSubscriberGetRequestTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testQueryParams() 23 | { 24 | $request = new RemovedSubscriberGetRequest( 25 | [1, 2, 3], 26 | [RemoveType::API(), RemoveType::COMPLAINT()], 27 | new \DateTime('2017-10-01'), 28 | new \DateTime('2017-10-30'), 29 | Option::CUSTOMS() 30 | ); 31 | 32 | Assert::assertEquals( 33 | [ 34 | 'listIds' => '1,2,3', 35 | 'removeTypes' => 'Api,Complaint', 36 | 'startDate' => '2017-10-01', 37 | 'endDate' => '2017-10-30', 38 | 'option' => 'Customs', 39 | ], 40 | $request->getQueryParams() 41 | ); 42 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::GET())); 43 | Assert::assertEquals('/v2/Api/RemovedSubscribers', $request->getUri()); 44 | Assert::assertEmpty($request->toXml()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Request/DataTablesGetTablesRequest.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class DataTablesGetTablesRequest implements RequestInterface 16 | { 17 | /** 18 | * @var string|null Table name to get details 19 | */ 20 | private $tableName; 21 | 22 | /** 23 | * Constructor. 24 | * 25 | * @param null|string $tableName Table name 26 | */ 27 | public function __construct(?string $tableName) 28 | { 29 | if ($tableName !== null) { 30 | Assert::notEmpty($tableName); 31 | } 32 | $this->tableName = $tableName; 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function toXml(): string 39 | { 40 | return ''; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function getQueryParams(): array 47 | { 48 | $params = []; 49 | if ($this->tableName !== null) { 50 | $params['name'] = $this->tableName; 51 | } 52 | 53 | return $params; 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function getMethod(): HttpMethod 60 | { 61 | return HttpMethod::GET(); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function getUri(): string 68 | { 69 | return '/v2/Api/DataTablesGetTables'; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Enum/SubscribersResponse/SubscriberPropertyType.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | final class SubscriberPropertyType extends Enum 23 | { 24 | /** 25 | * Text (string) property 26 | */ 27 | const TEXT = 'Text'; 28 | 29 | /** 30 | * Whole number, e.g. '0' or '123' 31 | */ 32 | const NUMBER = 'Number'; 33 | 34 | /** 35 | * A number with two decimal places, e.g. '10.99' 36 | */ 37 | const MONEY = 'Money'; 38 | 39 | /** 40 | * Url 41 | */ 42 | const URL = 'Url'; 43 | 44 | /** 45 | * Date, e.g. '2011-01-01' 46 | */ 47 | const DATE = 'Date'; 48 | 49 | /** 50 | * Date and time information, e.g. '2011-01-01 12:00:00' 51 | */ 52 | const DATETIME = 'Datetime'; 53 | 54 | /** 55 | * An enumeration of predefined values with one selected value possible, e.g. 'option 1' 56 | */ 57 | const SINGLE_SELECT = 'SingleSelect'; 58 | 59 | /** 60 | * True/false value 61 | */ 62 | const BOOLEAN = 'Boolean'; 63 | } 64 | -------------------------------------------------------------------------------- /src/Model/DataTablesGetTablesSummaryResponse/TableSummary.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class TableSummary extends AbstractTableData 12 | { 13 | /** 14 | * @var float Size of table in megabytes 15 | */ 16 | private $size; 17 | 18 | /** 19 | * Constructor. 20 | * 21 | * @param int $id ID 22 | * @param string $name Name 23 | * @param int $columnsCount Number of columns in table 24 | * @param int $relationshipsCount Number of relationships 25 | * @param int $relationshipsDestinationCount Number of relationships with other table 26 | * @param int $rowsCount Number of rows in table 27 | * @param float $size Size of data in megabytes 28 | */ 29 | public function __construct( 30 | int $id, 31 | string $name, 32 | int $columnsCount, 33 | int $relationshipsCount, 34 | int $relationshipsDestinationCount, 35 | int $rowsCount, 36 | float $size 37 | ) { 38 | parent::__construct( 39 | $id, 40 | $name, 41 | $columnsCount, 42 | $relationshipsCount, 43 | $relationshipsDestinationCount, 44 | $rowsCount 45 | ); 46 | 47 | $this->size = $size; 48 | } 49 | 50 | /** 51 | * Get size of table in megabytes 52 | * 53 | * @return float Size of table in megabytes 54 | */ 55 | public function getSize(): float 56 | { 57 | return $this->size; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Request/SubscribersGetRequest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class SubscribersGetRequest implements RequestInterface 17 | { 18 | /** 19 | * @var string Email 20 | */ 21 | private $email; 22 | 23 | /** 24 | * @var DataOption DataType of response 25 | */ 26 | private $option; 27 | 28 | /** 29 | * Constructor 30 | * 31 | * @param string $email Email 32 | * @param DataOption $option DataType of response 33 | */ 34 | public function __construct(string $email, DataOption $option) 35 | { 36 | Assert::notEmpty($email); 37 | $this->email = $email; 38 | $this->option = $option; 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function toXml(): string 45 | { 46 | return ''; 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function getMethod(): HttpMethod 53 | { 54 | return HttpMethod::GET(); 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | public function getUri(): string 61 | { 62 | return '/v2/Api/Subscribers'; 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | public function getQueryParams(): array 69 | { 70 | return ['email' => $this->email, 'option' => $this->option->getValue()]; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Model/SubscribersPostRequest/Options.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class Options 12 | { 13 | /** 14 | * @var bool Additional information will be returned for each added subscriber 15 | */ 16 | private $returnAdditionalDataOnResponse = false; 17 | 18 | /** 19 | * @var bool Use verbose errors in response 20 | */ 21 | private $useVerboseErrors = false; 22 | 23 | /** 24 | * Constructor. 25 | * 26 | * @param bool $returnAdditionalDataOnResponse Additional information will be returned for each added subscriber 27 | * @param bool $useVerboseErrors Use verbose errors in response 28 | */ 29 | public function __construct( 30 | $returnAdditionalDataOnResponse = false, 31 | $useVerboseErrors = false 32 | ) { 33 | $this->returnAdditionalDataOnResponse = $returnAdditionalDataOnResponse; 34 | $this->useVerboseErrors = $useVerboseErrors; 35 | } 36 | 37 | /** 38 | * Additional information will be returned for each added subscriber 39 | * 40 | * @return bool Additional information will be returned for each added subscriber 41 | */ 42 | public function isReturnAdditionalDataOnResponse(): bool 43 | { 44 | return $this->returnAdditionalDataOnResponse; 45 | } 46 | 47 | /** 48 | * Use verbose errors in response 49 | * 50 | * @return bool Use verbose errors in response 51 | */ 52 | public function isUseVerboseErrors(): bool 53 | { 54 | return $this->useVerboseErrors; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Enum/SubscribersGetRequest/DataOption.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | final class DataOption extends Enum 21 | { 22 | /** 23 | * Short 24 | * 25 | * * Email state on particular lists 26 | * * Is this mail on Global Black List or Local Black List 27 | */ 28 | const SHORT = 'Short'; 29 | 30 | /** 31 | * Long 32 | * 33 | * Email state on particular lists 34 | * * Is this mail on Global Black List 35 | * * Suppression lists email belongs to 36 | */ 37 | const LONG = 'Long'; 38 | 39 | /** 40 | * Full 41 | * 42 | * * Email state on particular lists 43 | * * Is this mail on Global Black List 44 | * * Suppression lists email belongs to 45 | * * Subscriber’s data: 46 | * * * First name 47 | * * * Last name 48 | * * * IP 49 | * * * Subscriber ID 50 | * * * Vendor 51 | * * * All Properties... 52 | */ 53 | const FULL = 'Full'; 54 | 55 | /** 56 | * Events history 57 | * 58 | * * Information about all events associated with subscriber, such as sending a message, clicks, opens etc 59 | * * This is the same information as can be seen in the panel's Subscriber details 60 | */ 61 | const EVENTS_HISTORY = 'EventsHistory'; 62 | } 63 | -------------------------------------------------------------------------------- /src/Model/DataTablesDeleteRowsPostRequest/Filter.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class Filter 15 | { 16 | /** 17 | * @var string Name 18 | */ 19 | private $name; 20 | 21 | /** 22 | * @var string Value 23 | */ 24 | private $value; 25 | 26 | /** 27 | * @var FilterOperator Operator 28 | */ 29 | private $operator; 30 | 31 | /** 32 | * Constructor. 33 | * 34 | * @param string $name Name 35 | * @param FilterOperator $operator Operator 36 | * @param int|string|float $value Value 37 | */ 38 | public function __construct(string $name, FilterOperator $operator, $value) 39 | { 40 | Assert::notEmpty($name); 41 | Assert::scalar($value); 42 | $this->name = $name; 43 | $this->value = strval($value); 44 | $this->operator = $operator; 45 | } 46 | 47 | /** 48 | * Get name 49 | * 50 | * @return string Name 51 | */ 52 | public function getName(): string 53 | { 54 | return $this->name; 55 | } 56 | 57 | /** 58 | * Get value 59 | * 60 | * @return string Value 61 | */ 62 | public function getValue(): string 63 | { 64 | return $this->value; 65 | } 66 | 67 | /** 68 | * Get operator 69 | * 70 | * @return FilterOperator Operator 71 | */ 72 | public function getOperator(): FilterOperator 73 | { 74 | return $this->operator; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/ResponseInterface.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | interface ResponseInterface 15 | { 16 | /** 17 | * Is response OK (without errors) 18 | * 19 | * @return bool Is response OK (without errors) 20 | */ 21 | public function isOk(): bool; 22 | 23 | /** 24 | * Get HTTP status code 25 | * 26 | * @return int HTTP status code 27 | */ 28 | public function getHttpStatusCode(): int; 29 | 30 | /** 31 | * Get error code if exists 32 | * 33 | * @return int|null Error code or null, if error not exists 34 | */ 35 | public function getErrorCode(): ?int; 36 | 37 | /** 38 | * Content 39 | * 40 | * @return string Content 41 | */ 42 | public function getContent(): string; 43 | 44 | /** 45 | * Stream of content 46 | * 47 | * @return StreamInterface Stream of content 48 | */ 49 | public function getStream(): StreamInterface; 50 | 51 | /** 52 | * Get error messages 53 | * 54 | * Get error messages as array. If response has only one error, then method return array with one element, if 55 | * response has multiple messages, than method return all messages. All attributes of error message you can get from 56 | * {@see ErrorMessage::getOptions} 57 | * 58 | * @return ErrorMessage[] Error messages 59 | */ 60 | public function getErrorMessages(): array; 61 | 62 | /** 63 | * Is empty 64 | * 65 | * @return bool Is empty 66 | */ 67 | public function isEmpty(): bool; 68 | } 69 | -------------------------------------------------------------------------------- /src/Model/TriggersPostRequest/Receiver.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Receiver 14 | { 15 | /** 16 | * @var int|null ID 17 | */ 18 | private $id; 19 | 20 | /** 21 | * @var string|null Email 22 | */ 23 | private $email; 24 | 25 | /** 26 | * Create with ID as identifier 27 | * 28 | * @param int $id ID 29 | * 30 | * @return static Receiver 31 | */ 32 | public static function createFromId(int $id) 33 | { 34 | Assert::notEmpty($id); 35 | 36 | return new static($id); 37 | } 38 | 39 | /** 40 | * Create with email as identifier 41 | * 42 | * @param string $email Email 43 | * 44 | * @return static Receiver 45 | */ 46 | public static function createFromEmail(string $email) 47 | { 48 | Assert::notEmpty($email); 49 | 50 | return new static(null, $email); 51 | } 52 | 53 | /** 54 | * Constructor 55 | * 56 | * @param int $id ID 57 | * @param string $email Email 58 | */ 59 | private function __construct(int $id = null, string $email = null) 60 | { 61 | $this->id = $id; 62 | $this->email = $email; 63 | } 64 | 65 | /** 66 | * Get ID 67 | * 68 | * @return int|null ID 69 | */ 70 | public function getId(): ?int 71 | { 72 | return $this->id; 73 | } 74 | 75 | /** 76 | * Get email 77 | * 78 | * @return null|string Email 79 | */ 80 | public function getEmail(): ?string 81 | { 82 | return $this->email; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Model/TransactionalPostRequest/Attachment.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Attachment 14 | { 15 | /** 16 | * @var string Filename 17 | */ 18 | private $filename; 19 | 20 | /** 21 | * @var string|null MIME type 22 | */ 23 | private $mimeType; 24 | 25 | /** 26 | * @var string Content 27 | */ 28 | private $content; 29 | 30 | /** 31 | * Constructor. 32 | * 33 | * @param string $filename Filename 34 | * @param string $content Content 35 | * @param string $mimeType MIME type 36 | */ 37 | public function __construct(string $filename, string $content, string $mimeType = null) 38 | { 39 | Assert::notEmpty($filename); 40 | Assert::notEmpty($content); 41 | if ($mimeType !== null) { 42 | Assert::notEmpty($mimeType); 43 | } 44 | 45 | $this->filename = $filename; 46 | $this->mimeType = $mimeType; 47 | $this->content = $content; 48 | } 49 | 50 | /** 51 | * Get filename 52 | * 53 | * @return string Filename 54 | */ 55 | public function getFilename() 56 | { 57 | return $this->filename; 58 | } 59 | 60 | /** 61 | * Get MIME type 62 | * 63 | * @return null|string MIME type 64 | */ 65 | public function getMimeType(): ?string 66 | { 67 | return $this->mimeType; 68 | } 69 | 70 | /** 71 | * Get content 72 | * 73 | * @return string Content 74 | */ 75 | public function getContent(): string 76 | { 77 | return $this->content; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Model/WhereCondition.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class WhereCondition 15 | { 16 | /** 17 | * @var string Column name 18 | */ 19 | private $columnName; 20 | 21 | /** 22 | * @var Operator Operator 23 | */ 24 | private $operator; 25 | 26 | /** 27 | * @var string Value 28 | */ 29 | private $value; 30 | 31 | /** 32 | * Constructor 33 | * 34 | * @param string $columnName Column name 35 | * @param Operator $operator Operator 36 | * @param string|int|float $value Value 37 | */ 38 | public function __construct(string $columnName, Operator $operator, $value) 39 | { 40 | Assert::scalar($value); 41 | Assert::notEmpty($columnName); 42 | Assert::notEmpty($value); 43 | $this->columnName = $columnName; 44 | $this->operator = $operator; 45 | $this->value = strval($value); 46 | } 47 | 48 | /** 49 | * Get column name 50 | * 51 | * @return string Column name 52 | */ 53 | public function getColumnName(): string 54 | { 55 | return $this->columnName; 56 | } 57 | 58 | /** 59 | * Get operator 60 | * 61 | * @return Operator Operator 62 | */ 63 | public function getOperator(): Operator 64 | { 65 | return $this->operator; 66 | } 67 | 68 | /** 69 | * Get value 70 | * 71 | * @return string Value 72 | */ 73 | public function getValue(): string 74 | { 75 | return $this->value; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tests/Request/SubscribersGetRequestTest.php: -------------------------------------------------------------------------------- 1 | getUri()); 20 | Assert::assertEquals(['email' => 'email@email.ru', 'option' => 'Short'], $request->getQueryParams()); 21 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::GET())); 22 | Assert::assertEquals('', $request->toXml()); 23 | 24 | $requestLong = new SubscribersGetRequest('email@email.ru', DataOption::LONG()); 25 | Assert::assertEquals(['email' => 'email@email.ru', 'option' => 'Long'], $requestLong->getQueryParams()); 26 | 27 | $requestFull = new SubscribersGetRequest('email@email.ru', DataOption::FULL()); 28 | Assert::assertEquals(['email' => 'email@email.ru', 'option' => 'Full'], $requestFull->getQueryParams()); 29 | 30 | $requestEventsHistory = new SubscribersGetRequest('email@email.ru', DataOption::EVENTS_HISTORY()); 31 | Assert::assertEquals( 32 | ['email' => 'email@email.ru', 'option' => 'EventsHistory'], 33 | $requestEventsHistory->getQueryParams() 34 | ); 35 | } 36 | 37 | /** 38 | * @expectedException \InvalidArgumentException 39 | */ 40 | public function testThrowExceptionIfEmailIsEmpty() 41 | { 42 | new SubscribersGetRequest('', DataOption::SHORT()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Request/DataTablesUpdateRowRequestTest.php: -------------------------------------------------------------------------------- 1 | table-nameColumn112' 31 | . 'Column212.5Column3' 32 | . 'stringColumn4' 33 | . '15Column515.8' 34 | . 'Column6string2Column7' 35 | . ''; 36 | Assert::assertEquals($xml, $request->toXml()); 37 | Assert::assertEquals([], $request->getQueryParams()); 38 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::POST())); 39 | Assert::assertEquals('/v2/Api/DataTablesUpdateRow', $request->getUri()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Model/SnoozedSubscribersGetResponse/SnoozedSubscriber.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class SnoozedSubscriber 12 | { 13 | /** 14 | * @var string Email 15 | */ 16 | private $email; 17 | 18 | /** 19 | * @var int Identifier of list that subscriber snoozed his subscription from 20 | */ 21 | private $listId; 22 | 23 | /** 24 | * @var \DateTime Date and time when subscription suspension expires 25 | */ 26 | private $snoozedUntil; 27 | 28 | /** 29 | * Constructor. 30 | * 31 | * @param string $email Email 32 | * @param int $listId Identifier of list that subscriber snoozed his subscription from 33 | * @param \DateTime $snoozedUntil Date and time when subscription suspension expires 34 | */ 35 | public function __construct(string $email, int $listId, \DateTime $snoozedUntil) 36 | { 37 | $this->email = $email; 38 | $this->listId = $listId; 39 | $this->snoozedUntil = $snoozedUntil; 40 | } 41 | 42 | /** 43 | * Get email 44 | * 45 | * @return string Email 46 | */ 47 | public function getEmail(): string 48 | { 49 | return $this->email; 50 | } 51 | 52 | /** 53 | * Get identifier of list that subscriber snoozed his subscription from 54 | * 55 | * @return int Identifier of list that subscriber snoozed his subscription from 56 | */ 57 | public function getListId(): int 58 | { 59 | return $this->listId; 60 | } 61 | 62 | /** 63 | * Get date and time when subscription suspension expires 64 | * 65 | * @return \DateTime Date and time when subscription suspension expires 66 | */ 67 | public function getSnoozedUntil(): \DateTime 68 | { 69 | return $this->snoozedUntil; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Model/DataTablesGetTablesSummaryResponse/TableDetails.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class TableDetails extends AbstractTableData 12 | { 13 | /** 14 | * @var string Description 15 | */ 16 | private $description; 17 | 18 | /** 19 | * @var TableColumnData[]|iterable Columns 20 | */ 21 | private $columns; 22 | 23 | /** 24 | * Constructor. 25 | * 26 | * @param int $id ID 27 | * @param string $name Name 28 | * @param int $columnsCount Number of columns in table 29 | * @param int $relationshipsCount Number of relationships 30 | * @param int $relationshipsDestinationCount Number of relationships with other table 31 | * @param int $rowsCount Number of rows in table 32 | * @param string $description Description 33 | * @param TableColumnData[]|iterable $columns Columns 34 | */ 35 | public function __construct( 36 | int $id, 37 | string $name, 38 | int $columnsCount, 39 | int $relationshipsCount, 40 | int $relationshipsDestinationCount, 41 | int $rowsCount, 42 | string $description, 43 | iterable $columns 44 | ) { 45 | parent::__construct($id, $name, $columnsCount, $relationshipsCount, $relationshipsDestinationCount, $rowsCount); 46 | $this->description = $description; 47 | $this->columns = $columns; 48 | } 49 | 50 | /** 51 | * Get description 52 | * 53 | * @return string Description 54 | */ 55 | public function getDescription(): string 56 | { 57 | return $this->description; 58 | } 59 | 60 | /** 61 | * Get columns 62 | * 63 | * @return TableColumnData[]|iterable Columns 64 | */ 65 | public function getColumns(): iterable 66 | { 67 | return $this->columns; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Utils.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Utils 14 | { 15 | /** 16 | * Convert bool value to string equivalent for ExpertSender API 17 | * 18 | * @param bool $bool Value 19 | * 20 | * @return string String equivalent of bool value for ExpertSender API 21 | */ 22 | public static function convertBoolToStringEquivalent(bool $bool): string 23 | { 24 | return $bool ? 'true' : 'false'; 25 | } 26 | 27 | /** 28 | * Convert boolean string equivalent to boolean value 29 | * 30 | * @param string $boolStringEquivalent Equivalent of boolean value from API 31 | * 32 | * @return bool Boolean value 33 | */ 34 | public static function convertStringBooleanEquivalentToBool(string $boolStringEquivalent): bool 35 | { 36 | return $boolStringEquivalent === 'true'; 37 | } 38 | 39 | /** 40 | * Create SimpleXML from string 41 | * 42 | * @param string $string Xml string 43 | * 44 | * @throws NotValidXmlException If xml is not valid and can't create SimpleXML object 45 | * 46 | * @return \SimpleXMLElement SimpleXML 47 | */ 48 | public static function createSimpleXml($string): \SimpleXMLElement 49 | { 50 | $oldValue = libxml_use_internal_errors(true); 51 | 52 | $simpleXml = simplexml_load_string($string); 53 | if ($simpleXml === false) { 54 | $errors = libxml_get_errors(); 55 | libxml_use_internal_errors($oldValue); 56 | throw new NotValidXmlException( 57 | $errors, 58 | 'Can\'t create SimpleXml object. Maybe content is empty, or contains non xml data' 59 | ); 60 | } 61 | 62 | libxml_use_internal_errors($oldValue); 63 | 64 | return $simpleXml; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Enum/ActivitiesGetRequest/ActivityType.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class SubscriberData 12 | { 13 | /** 14 | * @var string Email 15 | */ 16 | private $email; 17 | 18 | /** 19 | * @var int ID 20 | */ 21 | private $id; 22 | 23 | /** 24 | * @var bool Subscriber was added 25 | */ 26 | private $isWasAdded; 27 | 28 | /** 29 | * @var bool Subscriber was ignored 30 | */ 31 | private $isWasIgnored; 32 | 33 | /** 34 | * Constructor. 35 | * 36 | * @param string $email Email 37 | * @param int $id Id 38 | * @param bool $isWasAdded Subscriber was added 39 | * @param bool $isWasIgnored Subscriber was ignored 40 | */ 41 | public function __construct(string $email, int $id, bool $isWasAdded, bool $isWasIgnored) 42 | { 43 | $this->email = $email; 44 | $this->id = $id; 45 | $this->isWasAdded = $isWasAdded; 46 | $this->isWasIgnored = $isWasIgnored; 47 | } 48 | 49 | /** 50 | * Get email 51 | * 52 | * @return string Email 53 | */ 54 | public function getEmail(): string 55 | { 56 | return $this->email; 57 | } 58 | 59 | /** 60 | * Get ID 61 | * 62 | * @return int ID 63 | */ 64 | public function getId(): int 65 | { 66 | return $this->id; 67 | } 68 | 69 | /** 70 | * Is subscriber was added 71 | * 72 | * @return bool Is subscriber was added 73 | */ 74 | public function isWasAdded(): bool 75 | { 76 | return $this->isWasAdded; 77 | } 78 | 79 | /** 80 | * Is subscriber was ignored 81 | * 82 | * @return bool Is subscriber was ignored 83 | */ 84 | public function isWasIgnored(): bool 85 | { 86 | return $this->isWasIgnored; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /tests/Request/DataTablesAddMultipleRowsPostRequestTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class DataTablesAddMultipleRowsPostRequestTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testCommonUsage() 23 | { 24 | $request = new DataTablesAddMultipleRowsPostRequest( 25 | 'table-name', [ 26 | new Row( 27 | [ 28 | new Column('string', 'string'), 29 | new Column('null', null), 30 | ] 31 | ), 32 | new Row( 33 | [ 34 | new Column('float', 5.67), 35 | new Column('int', 12), 36 | ] 37 | ), 38 | ] 39 | ); 40 | 41 | $xml = 'table-namestringstring' 42 | . 'null' 43 | . 'float5.67int12' 44 | . ''; 45 | Assert::assertEquals($xml, $request->toXml()); 46 | Assert::assertEquals([], $request->getQueryParams()); 47 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::POST())); 48 | Assert::assertEquals('/v2/Api/DataTablesAddMultipleRows', $request->getUri()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/Request/DataTablesGetDataCountRequestTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class DataTablesGetDataCountRequestTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testCommonUsage() 23 | { 24 | $request = new DataTablesGetDataCountRequest( 25 | 'table-name', 26 | [ 27 | new WhereCondition('Column1', Operator::EQUAL(), 12), 28 | new WhereCondition('Column2', Operator::GREATER(), 12.53), 29 | new WhereCondition('Column3', Operator::LOWER(), -0.56), 30 | new WhereCondition('Column5', Operator::LIKE(), 'string'), 31 | ] 32 | ); 33 | 34 | Assert::assertEquals([], $request->getQueryParams()); 35 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::POST())); 36 | Assert::assertEquals('/v2/Api/DataTablesGetDataCount', $request->getUri()); 37 | Assert::assertEquals( 38 | 'table-nameColumn1' 39 | . 'Equals12Column2' 40 | . 'Greater12.53Column3' 41 | . 'Lower-0.56Column5' 42 | . 'Likestring', 43 | $request->toXml() 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Model/BouncesGetResponse/Bounce.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Bounce 14 | { 15 | /** 16 | * @var \DateTime Date 17 | */ 18 | private $date; 19 | 20 | /** 21 | * @var string Email 22 | */ 23 | private $email; 24 | 25 | /** 26 | * @var string Bounce code 27 | */ 28 | private $bounceCode; 29 | 30 | /** 31 | * @var BounceType Bounce type 32 | */ 33 | private $bounceType; 34 | 35 | /** 36 | * Constructor. 37 | * 38 | * @param \DateTime $date Date 39 | * @param string $email Email 40 | * @param string $bounceCode Bounce code 41 | * @param BounceType $bounceType Bounce type 42 | */ 43 | public function __construct(\DateTime $date, string $email, string $bounceCode, BounceType $bounceType) 44 | { 45 | $this->date = $date; 46 | $this->email = $email; 47 | $this->bounceCode = $bounceCode; 48 | $this->bounceType = $bounceType; 49 | } 50 | 51 | /** 52 | * Get date 53 | * 54 | * @return \DateTime Date 55 | */ 56 | public function getDate(): \DateTime 57 | { 58 | return $this->date; 59 | } 60 | 61 | /** 62 | * Get email 63 | * 64 | * @return string Email 65 | */ 66 | public function getEmail(): string 67 | { 68 | return $this->email; 69 | } 70 | 71 | /** 72 | * Get bounce code 73 | * 74 | * @return string Bounce code 75 | */ 76 | public function getBounceCode(): string 77 | { 78 | return $this->bounceCode; 79 | } 80 | 81 | /** 82 | * Get bounce type 83 | * 84 | * @return BounceType Bounce type 85 | */ 86 | public function getBounceType(): BounceType 87 | { 88 | return $this->bounceType; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Response/RemovedSubscribersGetResponse.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class RemovedSubscribersGetResponse extends SpecificXmlMethodResponse 18 | { 19 | /** 20 | * @var SubscriberDataParser Subscriber data parser 21 | */ 22 | private $parser; 23 | 24 | /** 25 | * Constructor 26 | * 27 | * @param ResponseInterface $response Response 28 | */ 29 | public function __construct(ResponseInterface $response) 30 | { 31 | parent::__construct($response); 32 | 33 | $this->parser = new SubscriberDataParser(); 34 | } 35 | 36 | /** 37 | * Get removed subscribers 38 | * 39 | * @return RemovedSubscriber[]|\Generator Removed subscribers 40 | */ 41 | public function getRemovedSubscribers(): \Generator 42 | { 43 | if (!$this->isOk()) { 44 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 45 | } 46 | 47 | $nodes = $this->getSimpleXml()->xpath('/ApiResponse/Data/RemovedSubscribers/RemovedSubscriber'); 48 | foreach ($nodes as $node) { 49 | $subscriberData = null; 50 | // check, if additional data exists 51 | if (strval($node->Id) !== '') { 52 | $subscriberData = $this->parser->parse($node); 53 | } 54 | 55 | yield new RemovedSubscriber( 56 | strval($node->Email), 57 | intval($node->ListId), 58 | new \DateTime(strval($node->UnsubscribedOn)), 59 | $subscriberData 60 | ); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Enum/SubscribersPostRequest/Mode.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | final class Mode extends Enum 21 | { 22 | /** 23 | * Add new subscribers and update custom fields of subscribers existing on the list 24 | */ 25 | const ADD_AND_UPDATE = 'AddAndUpdate'; 26 | 27 | /** 28 | * Add new subscribers and replace custom fields of subscribers existing on the list 29 | */ 30 | const ADD_AND_REPLACE = 'AddAndReplace'; 31 | 32 | /** 33 | * Add new subscribers and do not update or replace custom fields of subscribers existing on the list 34 | */ 35 | const ADD_AND_IGNORE = 'AddAndIgnore'; 36 | 37 | /** 38 | * Do not add new subscribers, only update custom fields of subscribers existing on the list 39 | */ 40 | const IGNORE_AND_UPDATE = 'IgnoreAndUpdate'; 41 | 42 | /** 43 | * Do not add new subscribers, only replace custom fields of subscribers existing on the list 44 | */ 45 | const IGNORE_AND_REPLACE = 'IgnoreAndReplace'; 46 | 47 | /** 48 | * Has add mod 49 | * 50 | * @return bool Has add method 51 | */ 52 | public function isAddEnabled(): bool 53 | { 54 | return in_array($this->value, [self::ADD_AND_UPDATE, self::ADD_AND_IGNORE, self::ADD_AND_REPLACE]); 55 | } 56 | 57 | /** 58 | * Has edit mod 59 | * 60 | * @return bool Has edit mod 61 | */ 62 | public function isEditEnabled(): bool 63 | { 64 | return in_array( 65 | $this->value, 66 | [self::IGNORE_AND_UPDATE, self::IGNORE_AND_REPLACE, self::ADD_AND_UPDATE, self::ADD_AND_REPLACE] 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Request/BouncesGetRequest.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class BouncesGetRequest implements RequestInterface 16 | { 17 | /** 18 | * @var \DateTime Start date 19 | */ 20 | private $startDate; 21 | 22 | /** 23 | * @var \DateTime End data 24 | */ 25 | private $endDate; 26 | 27 | /** 28 | * @var BounceType|null Bounce type 29 | */ 30 | private $bounceType; 31 | 32 | /** 33 | * Constructor. 34 | * 35 | * @param \DateTime $startDate Start date 36 | * @param \DateTime $endDate End data 37 | * @param BounceType $bounceType Bounce type 38 | */ 39 | public function __construct(\DateTime $startDate, \DateTime $endDate, BounceType $bounceType = null) 40 | { 41 | $this->startDate = $startDate; 42 | $this->endDate = $endDate; 43 | $this->bounceType = $bounceType; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function toXml(): string 50 | { 51 | return ''; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | public function getQueryParams(): array 58 | { 59 | $params = [ 60 | 'startDate' => $this->startDate->format('Y-m-d'), 61 | 'endDate' => $this->endDate->format('Y-m-d'), 62 | ]; 63 | 64 | if ($this->bounceType !== null) { 65 | $params['bounceType'] = $this->bounceType->getValue(); 66 | } 67 | 68 | return $params; 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function getMethod(): HttpMethod 75 | { 76 | return HttpMethod::GET(); 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | public function getUri(): string 83 | { 84 | return '/v2/Api/Bounces'; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Model/SubscribersGetResponse/StateOnList.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class StateOnList 14 | { 15 | /** 16 | * @var int List ID 17 | */ 18 | private $listId; 19 | 20 | /** 21 | * @var string List name 22 | */ 23 | private $name; 24 | 25 | /** 26 | * @var StateOnListStatus Status 27 | */ 28 | private $status; 29 | 30 | /** 31 | * @var \DateTime Subscription date 32 | */ 33 | private $subscriptionDate; 34 | 35 | /** 36 | * Constructor 37 | * 38 | * @param int $listId List ID 39 | * @param string $name List name 40 | * @param StateOnListStatus $status Status 41 | * @param \DateTime $subscriptionDate Subscription date 42 | */ 43 | public function __construct(int $listId, string $name, StateOnListStatus $status, \DateTime $subscriptionDate) 44 | { 45 | $this->listId = $listId; 46 | $this->name = $name; 47 | $this->status = $status; 48 | $this->subscriptionDate = $subscriptionDate; 49 | } 50 | 51 | /** 52 | * Get list ID 53 | * 54 | * @return int List ID 55 | */ 56 | public function getListId(): int 57 | { 58 | return $this->listId; 59 | } 60 | 61 | /** 62 | * Get list name 63 | * 64 | * @return string List name 65 | */ 66 | public function getName(): string 67 | { 68 | return $this->name; 69 | } 70 | 71 | /** 72 | * Get status 73 | * 74 | * @return StateOnListStatus Status 75 | */ 76 | public function getStatus(): StateOnListStatus 77 | { 78 | return $this->status; 79 | } 80 | 81 | /** 82 | * Get subscription date 83 | * 84 | * @return \DateTime Subscription date 85 | */ 86 | public function getSubscriptionDate(): \DateTime 87 | { 88 | return $this->subscriptionDate; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Response/SubscribersGetShortResponse.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class SubscribersGetShortResponse extends SpecificXmlMethodResponse 18 | { 19 | /** 20 | * Is subscriber in black list (local or global) 21 | * 22 | * @return bool Is subscriber in black list (local or global) 23 | */ 24 | public function isInBlackList() 25 | { 26 | if (!$this->isOk()) { 27 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 28 | } 29 | 30 | $xml = $this->getSimpleXml(); 31 | $nodes = $xml->xpath('/ApiResponse/Data/BlackList'); 32 | if (count($nodes) === 0) { 33 | throw ParseResponseException::createFromResponse('Can\'t fine BlackList element' , $this); 34 | } 35 | 36 | return strval(reset($nodes)) === 'true'; 37 | } 38 | 39 | /** 40 | * Get all state on list 41 | * 42 | * @return StateOnList[] States on list 43 | */ 44 | public function getStateOnLists(): array 45 | { 46 | if (!$this->isOk()) { 47 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 48 | } 49 | 50 | $xml = $this->getSimpleXml(); 51 | $nodes = $xml->xpath('/ApiResponse/Data/StateOnLists/StateOnList'); 52 | 53 | $array = []; 54 | foreach ($nodes as $node) { 55 | $array[] = new StateOnList( 56 | intval($node->ListId), 57 | strval($node->Name), 58 | new StateOnListStatus(strval($node->Status)), 59 | new \DateTime(strval($node->SubscriptionDate)) 60 | ); 61 | } 62 | 63 | return $array; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/Response/ActivitiesGetResponse/ConfirmationsActivityGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class ConfirmationsActivityGetResponseTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testCommonUsage() 23 | { 24 | $csv = 'Date,Email,ListId,ListName 25 | 2017-02-02 00:01:00,mail@mail.com,18,Registration 26 | 2017-02-02 00:02:00,mail2@gmail.su,156,List name test'; 27 | $response = new ConfirmationsActivityGetResponse( 28 | new Response( 29 | new \GuzzleHttp\Psr7\Response( 30 | 200, 31 | ['Content-Type' => 'text/csv', 'Content-Length' => strlen($csv)], 32 | $csv 33 | ) 34 | ) 35 | ); 36 | 37 | Assert::assertTrue($response->isOk()); 38 | Assert::assertFalse($response->isEmpty()); 39 | /** @var ConfirmationActivity[] $confirmations */ 40 | $confirmations = toArray($response->getConfirmations()); 41 | 42 | Assert::assertCount(2, $confirmations); 43 | 44 | Assert::assertSame('2017-02-02 00:01:00', $confirmations[0]->getDate()->format('Y-m-d H:i:s')); 45 | Assert::assertSame('mail@mail.com', $confirmations[0]->getEmail()); 46 | Assert::assertSame(18, $confirmations[0]->getListId()); 47 | Assert::assertSame('Registration', $confirmations[0]->getListName()); 48 | 49 | Assert::assertSame('2017-02-02 00:02:00', $confirmations[1]->getDate()->format('Y-m-d H:i:s')); 50 | Assert::assertSame('mail2@gmail.su', $confirmations[1]->getEmail()); 51 | Assert::assertSame(156, $confirmations[1]->getListId()); 52 | Assert::assertSame('List name test', $confirmations[1]->getListName()); 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/Response/ActivitiesGetResponse/SubscriptionsActivityGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class SubscriptionsActivityGetResponseTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testCommonUsage() 23 | { 24 | $csv = 'Date,Email,ListId,ListName 25 | 2017-02-02 00:01:00,mail@mail.com,18,Registration 26 | 2017-02-02 00:02:00,mail2@gmail.su,156,List name test'; 27 | $response = new SubscriptionsActivityGetResponse( 28 | new Response( 29 | new \GuzzleHttp\Psr7\Response( 30 | 200, 31 | ['Content-Type' => 'text/csv', 'Content-Length' => strlen($csv)], 32 | $csv 33 | ) 34 | ) 35 | ); 36 | 37 | Assert::assertTrue($response->isOk()); 38 | Assert::assertFalse($response->isEmpty()); 39 | /** @var SubscriptionActivity[] $subscriptions */ 40 | $subscriptions = toArray($response->getSubscriptions()); 41 | 42 | Assert::assertCount(2, $subscriptions); 43 | 44 | Assert::assertSame('2017-02-02 00:01:00', $subscriptions[0]->getDate()->format('Y-m-d H:i:s')); 45 | Assert::assertSame('mail@mail.com', $subscriptions[0]->getEmail()); 46 | Assert::assertSame(18, $subscriptions[0]->getListId()); 47 | Assert::assertSame('Registration', $subscriptions[0]->getListName()); 48 | 49 | Assert::assertSame('2017-02-02 00:02:00', $subscriptions[1]->getDate()->format('Y-m-d H:i:s')); 50 | Assert::assertSame('mail2@gmail.su', $subscriptions[1]->getEmail()); 51 | Assert::assertSame(156, $subscriptions[1]->getListId()); 52 | Assert::assertSame('List name test', $subscriptions[1]->getListName()); 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/Response/SegmentsGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class SegmentsGetResponseTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * Test 20 | */ 21 | public function testGetSegments() 22 | { 23 | $xml = ' 25 | 26 | 27 | 28 | 1 29 | Clickers segment 30 | 31 | 32 | 3 33 | New subscribers 34 | 35 | 36 | 4 37 | Car owners 38 | 39 | 40 | 41 | '; 42 | $response = new SegmentsGetResponse( 43 | new Response( 44 | new \GuzzleHttp\Psr7\Response( 45 | 200, 46 | ['Content-Length' => strlen($xml), 'Content-Type' => 'text/xml'], 47 | $xml 48 | ) 49 | ) 50 | ); 51 | 52 | $this->assertTrue($response->isOk()); 53 | $this->assertFalse($response->isEmpty()); 54 | /** @var Segment[] $segments */ 55 | $segments = toArray($response->getSegments()); 56 | 57 | $this->assertCount(3, $segments); 58 | 59 | $this->assertEquals(1, $segments[0]->getId()); 60 | $this->assertEquals('Clickers segment', $segments[0]->getName()); 61 | 62 | $this->assertEquals(3, $segments[1]->getId()); 63 | $this->assertEquals('New subscribers', $segments[1]->getName()); 64 | 65 | $this->assertEquals(4, $segments[2]->getId()); 66 | $this->assertEquals('Car owners', $segments[2]->getName()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /tests/Response/SubscribersPostResponseTest.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class SubscribersPostResponseTest extends \PHPUnit_Framework_TestCase 16 | { 17 | /** 18 | * Test 19 | */ 20 | public function testValidResponseParsesCorrectly() 21 | { 22 | $xml = ' 24 | 25 | 26 | john.smith@domain2.com 27 | 4238647 28 | true 29 | false 30 | 31 | 32 | jane.doe@domain2.com 33 | 4238648 34 | false 35 | true 36 | 37 | 38 | '; 39 | $response = new SubscribersPostResponse( 40 | new Response(new \GuzzleHttp\Psr7\Response(201, ['Content-Length' => strlen($xml)], $xml)) 41 | ); 42 | Assert::assertTrue($response->isOk()); 43 | $subscriberDataList = $response->getChangedSubscribersData(); 44 | Assert::assertCount(2, $subscriberDataList); 45 | 46 | Assert::assertEquals('john.smith@domain2.com', $subscriberDataList[0]->getEmail()); 47 | Assert::assertEquals(4238647, $subscriberDataList[0]->getId()); 48 | Assert::assertEquals(true, $subscriberDataList[0]->isWasAdded()); 49 | Assert::assertEquals(false, $subscriberDataList[0]->isWasIgnored()); 50 | 51 | Assert::assertEquals('jane.doe@domain2.com', $subscriberDataList[1]->getEmail()); 52 | Assert::assertEquals(4238648, $subscriberDataList[1]->getId()); 53 | Assert::assertEquals(false, $subscriberDataList[1]->isWasAdded()); 54 | Assert::assertEquals(true, $subscriberDataList[1]->isWasIgnored()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/Response/BounceGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class BounceGetResponseTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * Test 20 | */ 21 | public function testCommonExample() 22 | { 23 | $csv = 'Date,Email,BounceCode,BounceType' . PHP_EOL 24 | . '2010-10-01 17:10:00,test1@yahoo.com,some test bounce code,UserUnknown' . PHP_EOL 25 | . PHP_EOL 26 | . '2010-10-01 17:10:00,test2@yahoo.com,some test bounce code 1,MailboxFull' . PHP_EOL; 27 | 28 | $response = new BouncesGetResponse( 29 | new Response( 30 | new \GuzzleHttp\Psr7\Response( 31 | 200, 32 | ['Content-Type' => 'text/csv', 'Content-Length' => strlen($csv)], 33 | $csv 34 | ) 35 | ) 36 | ); 37 | 38 | Assert::assertTrue($response->isOk()); 39 | Assert::assertFalse($response->isEmpty()); 40 | Assert::assertNull($response->getErrorCode()); 41 | Assert::assertEmpty($response->getErrorMessages()); 42 | 43 | /** @var Bounce[] $bounces */ 44 | $bounces = iterator_to_array($response->getBounces()); 45 | 46 | Assert::assertCount(2, $bounces); 47 | Assert::assertEquals('2010-10-01 17:10:00', $bounces[0]->getDate()->format('Y-m-d H:i:s')); 48 | Assert::assertEquals('test1@yahoo.com', $bounces[0]->getEmail()); 49 | Assert::assertEquals('some test bounce code', $bounces[0]->getBounceCode()); 50 | Assert::assertEquals('UserUnknown', $bounces[0]->getBounceType()); 51 | 52 | Assert::assertEquals('2010-10-01 17:10:00', $bounces[1]->getDate()->format('Y-m-d H:i:s')); 53 | Assert::assertEquals('test2@yahoo.com', $bounces[1]->getEmail()); 54 | Assert::assertEquals('some test bounce code 1', $bounces[1]->getBounceCode()); 55 | Assert::assertEquals('MailboxFull', $bounces[1]->getBounceType()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Model/RemovedSubscribersGetResponse/RemovedSubscriber.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class RemovedSubscriber 14 | { 15 | /** 16 | * @var string Email 17 | */ 18 | private $email; 19 | 20 | /** 21 | * @var int List ID 22 | */ 23 | private $listId; 24 | 25 | /** 26 | * @var \DateTime Date of unsubscription 27 | */ 28 | private $unsubscribedOn; 29 | 30 | /** 31 | * @var SubscriberData|null Subscriber's data 32 | */ 33 | private $subscriberData; 34 | 35 | /** 36 | * RemovedSubscriber constructor. 37 | * 38 | * @param string $email Email 39 | * @param int $listId List ID 40 | * @param \DateTime $unsubscribedOn Date of unsubscription 41 | * @param SubscriberData $subscriberData Subscriber's data 42 | */ 43 | public function __construct($email, $listId, \DateTime $unsubscribedOn, SubscriberData $subscriberData = null) 44 | { 45 | $this->email = $email; 46 | $this->listId = $listId; 47 | $this->unsubscribedOn = $unsubscribedOn; 48 | $this->subscriberData = $subscriberData; 49 | } 50 | 51 | /** 52 | * Get email 53 | * 54 | * @return string Email 55 | */ 56 | public function getEmail(): string 57 | { 58 | return $this->email; 59 | } 60 | 61 | /** 62 | * Get list ID 63 | * 64 | * @return int List ID 65 | */ 66 | public function getListId(): int 67 | { 68 | return $this->listId; 69 | } 70 | 71 | /** 72 | * Get date of unsubscription 73 | * 74 | * @return \DateTime Date of unsubscription 75 | */ 76 | public function getUnsubscribedOn(): \DateTime 77 | { 78 | return $this->unsubscribedOn; 79 | } 80 | 81 | /** 82 | * Get subscriber's data 83 | * 84 | * If you want get subscriber's data, you should set option="Customs" in 85 | * {@see RemovedSubscribersGetRequest} 86 | * 87 | * @return SubscriberData|null Subscriber's data 88 | */ 89 | public function getSubscriberData(): ?SubscriberData 90 | { 91 | return $this->subscriberData; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /tests/Request/DataTablesDeleteRowsPostRequestTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class DataTablesDeleteRowsPostRequestTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testCommonUsage() 23 | { 24 | $request = new DataTablesDeleteRowsPostRequest( 25 | 'table-name', 26 | [ 27 | new Filter('Column1', FilterOperator::EQ(), 12), 28 | new Filter('Column2', FilterOperator::GE(), 56.7), 29 | new Filter('Column3', FilterOperator::EQ(), 'string'), 30 | new Filter('Column4', FilterOperator::GT(), 89.234), 31 | new Filter('Column5', FilterOperator::LT(), 87.3), 32 | new Filter('Column6', FilterOperator::LE(), 98), 33 | ] 34 | ); 35 | 36 | Assert::assertEquals([], $request->getQueryParams()); 37 | Assert::assertEquals('/v2/Api/DataTablesDeleteRows/', $request->getUri()); 38 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::POST())); 39 | Assert::assertEquals( 40 | 'table-nameColumn1' 41 | . 'EQ12Column2' 42 | . 'GE56.7Column3' 43 | . 'EQstringColumn4' 44 | . 'GT89.234Column5' 45 | . 'LT87.3Column6' 46 | . 'LE98', 47 | $request->toXml() 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Request/DataTablesAddMultipleRowsPostRequest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class DataTablesAddMultipleRowsPostRequest implements RequestInterface 17 | { 18 | use ColumnToXmlConverterTrait; 19 | /** 20 | * @var string Table name 21 | */ 22 | private $tableName; 23 | 24 | /** 25 | * @var Row[]|iterable Rows 26 | */ 27 | private $rows; 28 | 29 | /** 30 | * Constructor 31 | * 32 | * @param string $tableName Table name 33 | * @param Row[]|iterable $rows Rows 34 | */ 35 | public function __construct($tableName, iterable $rows) 36 | { 37 | $this->tableName = $tableName; 38 | $this->rows = $rows; 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function toXml(): string 45 | { 46 | $xmlWriter = new \XMLWriter(); 47 | $xmlWriter->openMemory(); 48 | $xmlWriter->writeElement('TableName', $this->tableName); 49 | $xmlWriter->startElement('Data'); 50 | foreach ($this->rows as $row) { 51 | $xmlWriter->startElement('Row'); 52 | $xmlWriter->startElement('Columns'); 53 | foreach ($row->getColumns() as $column) { 54 | $this->convertColumnToXml($column, $xmlWriter); 55 | } 56 | 57 | $xmlWriter->endElement(); // Columns 58 | $xmlWriter->endElement(); // Row 59 | } 60 | 61 | $xmlWriter->endElement(); // Data 62 | 63 | return $xmlWriter->flush(); 64 | } 65 | 66 | /** 67 | * {@inheritdoc} 68 | */ 69 | public function getQueryParams(): array 70 | { 71 | return []; 72 | } 73 | 74 | /** 75 | * {@inheritdoc} 76 | */ 77 | public function getMethod(): HttpMethod 78 | { 79 | return HttpMethod::POST(); 80 | } 81 | 82 | /** 83 | * {@inheritdoc} 84 | */ 85 | public function getUri(): string 86 | { 87 | return '/v2/Api/DataTablesAddMultipleRows'; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Response/DataTablesGetTablesDetailsResponse.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class DataTablesGetTablesDetailsResponse extends SpecificXmlMethodResponse 18 | { 19 | /** 20 | * Get table details 21 | * 22 | * @return TableDetails Table details 23 | */ 24 | public function getDetails(): TableDetails 25 | { 26 | if (!$this->isOk()) { 27 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 28 | } 29 | 30 | $node = $this->getSimpleXml()->xpath('/ApiResponse/Details')[0]; 31 | 32 | return new TableDetails( 33 | intval($node->Id), 34 | strval($node->Name), 35 | intval($node->ColumnsCount), 36 | intval($node->RelationshipsCount), 37 | intval($node->RelationshipsDestinationCount), 38 | intval($node->Rows), 39 | strval($node->Description), 40 | $this->getColumns() 41 | ); 42 | } 43 | 44 | /** 45 | * Get columns 46 | * 47 | * @return TableColumnData[]|iterable Columns 48 | */ 49 | private function getColumns(): iterable 50 | { 51 | $nodes = $this->getSimpleXml()->xpath('/ApiResponse/Details/Columns/TableColumn'); 52 | foreach ($nodes as $node) { 53 | yield new TableColumnData( 54 | strval($node->Name), 55 | strval($node->ColumnType), 56 | intval($node->Length), 57 | isset($node->DefaultValue) ? strval($node->DefaultValue) : null, 58 | isset($node->IsPrimaryKey) ? Utils::convertStringBooleanEquivalentToBool( 59 | strval($node->IsPrimaryKey) 60 | ) : false, 61 | isset($node->IsRequired) ? Utils::convertStringBooleanEquivalentToBool( 62 | strval($node->IsRequired) 63 | ) : false 64 | ); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests/Response/ActivitiesGetResponse/BouncesActivityGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class BouncesActivityGetResponseTest extends \PHPUnit_Framework_TestCase 19 | { 20 | /** 21 | * Test 22 | */ 23 | public function testGetCommonUsage() 24 | { 25 | $csv = 'Date,Email,Reason,DiagnosticCode,ListId,ListName,MessageGuid 26 | 2017-06-01 06:40:00,6846253@gmail.ru,Blocked,diagnostic_code,' 27 | . '81,Torl,8f5268e3-5980-473b-a369-c9b97cca0bc6 28 | 2017-06-01 15:31:00,skol@mail.com,Blocked,diagnostic_code,,15,Registration,' 29 | . 'db481b7d-0a2d-4b4e-a526-0f5994f71d9b'; 30 | 31 | $response = new BouncesActivityGetResponse( 32 | new Response( 33 | new \GuzzleHttp\Psr7\Response( 34 | 200, 35 | ['Content-Type' => 'text/csv', 'Content-Length' => strlen($csv)], 36 | $csv 37 | ) 38 | ) 39 | ); 40 | 41 | Assert::assertTrue($response->isOk()); 42 | Assert::assertFalse($response->isEmpty()); 43 | /** @var BounceActivity[] $bounceActivities */ 44 | $bounceActivities = toArray($response->getBounces()); 45 | 46 | Assert::assertCount(2, $bounceActivities); 47 | 48 | Assert::assertSame('2017-06-01 06:40:00', $bounceActivities[0]->getDate()->format('Y-m-d H:i:s')); 49 | Assert::assertSame('6846253@gmail.ru', $bounceActivities[0]->getEmail()); 50 | Assert::assertSame(81, $bounceActivities[0]->getListId()); 51 | Assert::assertSame('Torl', $bounceActivities[0]->getListName()); 52 | Assert::assertSame('8f5268e3-5980-473b-a369-c9b97cca0bc6', $bounceActivities[0]->getMessageGuid()); 53 | Assert::assertTrue($bounceActivities[0]->getReason()->equals(BounceReason::BLOCKED())); 54 | Assert::assertSame('diagnostic_code', $bounceActivities[0]->getDiagnosticCode()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Request/DataTablesGetDataCountRequest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class DataTablesGetDataCountRequest implements RequestInterface 18 | { 19 | use WhereConditionToXmlConverterTrait; 20 | 21 | /** 22 | * @var string Table name 23 | */ 24 | private $tableName; 25 | 26 | /** 27 | * @var WhereCondition[] Where conditions 28 | */ 29 | private $whereConditions = []; 30 | 31 | /** 32 | * Constructor. 33 | * 34 | * @param string $tableName Table name 35 | * @param WhereCondition[]|array $whereConditions Where conditions 36 | */ 37 | public function __construct(string $tableName, array $whereConditions) 38 | { 39 | Assert::notEmpty($tableName); 40 | Assert::allIsInstanceOf($whereConditions, WhereCondition::class); 41 | Assert::notEmpty($whereConditions); 42 | $this->tableName = $tableName; 43 | $this->whereConditions = $whereConditions; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function toXml(): string 50 | { 51 | $xmlWriter = new \XMLWriter(); 52 | $xmlWriter->openMemory(); 53 | $xmlWriter->writeElement('TableName', $this->tableName); 54 | $xmlWriter->startElement('WhereConditions'); 55 | foreach ($this->whereConditions as $whereCondition) { 56 | $this->convertWhereConditionToXml($whereCondition, $xmlWriter); 57 | } 58 | 59 | $xmlWriter->endElement(); // WhereConditions 60 | 61 | return $xmlWriter->flush(); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function getQueryParams(): array 68 | { 69 | return []; 70 | } 71 | 72 | /** 73 | * {@inheritdoc} 74 | */ 75 | public function getMethod(): HttpMethod 76 | { 77 | return HttpMethod::POST(); 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | public function getUri(): string 84 | { 85 | return '/v2/Api/DataTablesGetDataCount'; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/SpecificXmlMethodResponse.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class SpecificXmlMethodResponse implements ResponseInterface 14 | { 15 | /** 16 | * @var ResponseInterface Response of ExpertSender API 17 | */ 18 | protected $response; 19 | 20 | /** 21 | * @var \SimpleXMLElement SimpleXML 22 | */ 23 | private $simpleXml; 24 | 25 | /** 26 | * Constructor 27 | * 28 | * @param ResponseInterface $response Response of ExpertSender API 29 | */ 30 | public function __construct(ResponseInterface $response) 31 | { 32 | $this->response = $response; 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function isOk(): bool 39 | { 40 | return $this->response->isOk(); 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function getErrorCode(): ?int 47 | { 48 | return $this->response->getErrorCode(); 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | public function getHttpStatusCode(): int 55 | { 56 | return $this->response->getHttpStatusCode(); 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | public function getContent(): string 63 | { 64 | return $this->response->getContent(); 65 | } 66 | 67 | /** 68 | * {@inheritdoc} 69 | */ 70 | public function getStream(): StreamInterface 71 | { 72 | return $this->response->getStream(); 73 | } 74 | 75 | /** 76 | * Get SimpleXML object of response content 77 | * 78 | * @return \SimpleXMLElement XML 79 | */ 80 | public function getSimpleXml(): \SimpleXMLElement 81 | { 82 | if ($this->simpleXml === null) { 83 | $this->simpleXml = Utils::createSimpleXml($this->getContent()); 84 | } 85 | 86 | return $this->simpleXml; 87 | } 88 | 89 | /** 90 | * {@inheritdoc} 91 | */ 92 | public function getErrorMessages(): array 93 | { 94 | return $this->response->getErrorMessages(); 95 | } 96 | 97 | /** 98 | * {@inheritdoc} 99 | */ 100 | public function isEmpty(): bool 101 | { 102 | return $this->response->isEmpty(); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /tests/Response/TimeGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 19 | 2013-04-24T10:33:09.4338472Z 20 | '; 21 | 22 | $response = new TimeGetResponse(new Response(new \GuzzleHttp\Psr7\Response(200, [], $body))); 23 | Assert::assertTrue($response->isOk()); 24 | Assert::assertEquals('2013-04-24T10:33:09', $response->getServerTime()->format('Y-m-d\TH:i:s')); 25 | Assert::assertEquals(200, $response->getHttpStatusCode()); 26 | Assert::assertCount(0, $response->getErrorMessages()); 27 | Assert::assertNull($response->getErrorCode()); 28 | } 29 | 30 | /** 31 | * Test 32 | * 33 | * @expectedException \Citilink\ExpertSenderApi\Exception\ParseResponseException 34 | */ 35 | public function testThrowExceptionIfDateStringIsWrong() 36 | { 37 | $body = ' 39 | WRONG_DATA 40 | '; 41 | 42 | $response = new TimeGetResponse( 43 | new Response( 44 | new \GuzzleHttp\Psr7\Response( 45 | 200, 46 | ['Content-Type' => 'text/xml', 'Content-Length' => strlen($body)], 47 | $body 48 | ) 49 | ) 50 | ); 51 | Assert::assertTrue($response->isOk()); 52 | Assert::assertEquals('2013-04-24T10:33:09', $response->getServerTime()->format('Y-m-d\TH:i:s')); 53 | Assert::assertEquals(200, $response->getHttpStatusCode()); 54 | } 55 | 56 | /** 57 | * Test 58 | * 59 | * @expectedException \Citilink\ExpertSenderApi\Exception\TryToAccessDataFromErrorResponseException 60 | */ 61 | public function testThrowExceptionIfTryingGetServerTimeOnNotOkResponse() 62 | { 63 | $response = new TimeGetResponse(new Response(new \GuzzleHttp\Psr7\Response(500, [], ''))); 64 | $response->getServerTime(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/Request/DataTablesGetDataPostRequestTest.php: -------------------------------------------------------------------------------- 1 | table-nameColumn1Column2' 35 | . 'Column1Equals' 36 | . '12Column2Greater' 37 | . '12.53Column3Lower' 38 | . '-0.56Column5Like' 39 | . 'string' 40 | . 'Column1Descending' 41 | . 'Columne2Ascending' 42 | . '25'; 43 | Assert::assertEquals($xml, $request->toXml()); 44 | Assert::assertEquals([], $request->getQueryParams()); 45 | Assert::assertTrue($request->getMethod()->equals(HttpMethod::POST())); 46 | Assert::assertEquals('/v2/Api/DataTablesGetData', $request->getUri()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Request/DataTablesDeleteRowsPostRequest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class DataTablesDeleteRowsPostRequest implements RequestInterface 17 | { 18 | /** 19 | * @var string Table name 20 | */ 21 | private $tableName; 22 | 23 | /** 24 | * @var Filter[] Filters. This is an equivalent of SQL "WHERE" directive. 25 | */ 26 | private $filters; 27 | 28 | /** 29 | * Constructor. 30 | * 31 | * @param string $tableName Table name 32 | * @param Filter[] $filters Filters. This is an equivalent of SQL "WHERE" directive 33 | */ 34 | public function __construct(string $tableName, array $filters) 35 | { 36 | Assert::notEmpty($tableName); 37 | Assert::allIsInstanceOf($filters, Filter::class); 38 | $this->tableName = $tableName; 39 | $this->filters = $filters; 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | public function toXml(): string 46 | { 47 | $xmlWriter = new \XMLWriter(); 48 | $xmlWriter->openMemory(); 49 | $xmlWriter->writeElement('TableName', $this->tableName); 50 | $xmlWriter->startElement('Filters'); 51 | foreach ($this->filters as $filter) { 52 | $xmlWriter->startElement('Filter'); 53 | $xmlWriter->startElement('Column'); 54 | $xmlWriter->writeElement('Name', $filter->getName()); 55 | $xmlWriter->writeElement('Operator', $filter->getOperator()->getValue()); 56 | $xmlWriter->writeElement('Value', $filter->getValue()); 57 | $xmlWriter->endElement(); // Column 58 | $xmlWriter->endElement(); // Filter 59 | } 60 | 61 | $xmlWriter->endElement(); // Filters 62 | 63 | return $xmlWriter->flush(); 64 | } 65 | 66 | /** 67 | * {@inheritdoc} 68 | */ 69 | public function getQueryParams(): array 70 | { 71 | return []; 72 | } 73 | 74 | /** 75 | * {@inheritdoc} 76 | */ 77 | public function getMethod(): HttpMethod 78 | { 79 | return HttpMethod::POST(); 80 | } 81 | 82 | /** 83 | * {@inheritdoc} 84 | */ 85 | public function getUri(): string 86 | { 87 | return '/v2/Api/DataTablesDeleteRows/'; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/Request/TriggersPostRequest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class TriggersPostRequest implements RequestInterface 17 | { 18 | /** 19 | * @var int Trigger message ID 20 | */ 21 | private $triggerMessageId; 22 | 23 | /** 24 | * @var Receiver[] Receivers 25 | */ 26 | private $receivers; 27 | 28 | /** 29 | * Constructor 30 | * 31 | * @param int $triggerMessageId Trigger message ID 32 | * @param Receiver[] $receivers Receivers 33 | */ 34 | public function __construct($triggerMessageId, array $receivers) 35 | { 36 | Assert::notEmpty($triggerMessageId); 37 | Assert::notEmpty($receivers); 38 | Assert::allIsInstanceOf($receivers, Receiver::class); 39 | $this->triggerMessageId = $triggerMessageId; 40 | $this->receivers = $receivers; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function toXml(): string 47 | { 48 | $xmlWriter = new \XMLWriter(); 49 | $xmlWriter->openMemory(); 50 | $xmlWriter->startElement('Data'); 51 | $xmlWriter->writeAttributeNS('xsi', 'type', null, 'TriggerReceivers'); 52 | $xmlWriter->startElement('Receivers'); 53 | foreach ($this->receivers as $receiver) { 54 | $xmlWriter->startElement('Receiver'); 55 | if (!empty($receiver->getId())) { 56 | $xmlWriter->writeElement('Id', strval($receiver->getId())); 57 | } 58 | 59 | if (!empty($receiver->getEmail())) { 60 | $xmlWriter->writeElement('Email', $receiver->getEmail()); 61 | } 62 | 63 | $xmlWriter->endElement(); // Receiver 64 | } 65 | 66 | $xmlWriter->endElement(); // Receivers 67 | $xmlWriter->endElement(); // Data 68 | 69 | return $xmlWriter->flush(); 70 | } 71 | 72 | /** 73 | * {@inheritdoc} 74 | */ 75 | public function getQueryParams(): array 76 | { 77 | return []; 78 | } 79 | 80 | /** 81 | * {@inheritdoc} 82 | */ 83 | public function getMethod(): HttpMethod 84 | { 85 | return HttpMethod::POST(); 86 | } 87 | 88 | /** 89 | * {@inheritdoc} 90 | */ 91 | public function getUri(): string 92 | { 93 | return '/v2/Api/Triggers/' . $this->triggerMessageId; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /tests/Response/ActivitiesGetResponse/ComplaintsActivityGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class ComplaintsActivityGetResponseTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testGetCommonUsage() 23 | { 24 | $csv = 'Date,Email,MessageId,MessageSubject,ListId,ListName,MessageGuid 25 | 2017-06-01 06:40:00,6846253@gmail.ru,89,"${Snippet(\'firstname\')}, cCongrats",' 27 | . '81,Torl,8f5268e3-5980-473b-a369-c9b97cca0bc6 28 | 2017-06-01 15:31:00,skol@mail.com,26,"Subject",,15,Registration,' 29 | . 'db481b7d-0a2d-4b4e-a526-0f5994f71d9b'; 30 | 31 | $response = new ComplaintsActivityGetResponse( 32 | new Response( 33 | new \GuzzleHttp\Psr7\Response( 34 | 200, 35 | ['Content-Type' => 'text/csv', 'Content-Length' => strlen($csv)], 36 | $csv 37 | ) 38 | ) 39 | ); 40 | 41 | Assert::assertTrue($response->isOk()); 42 | Assert::assertFalse($response->isEmpty()); 43 | /** @var ComplaintActivity[] $complaintActivities */ 44 | $complaintActivities = toArray($response->getComplaints()); 45 | 46 | Assert::assertCount(2, $complaintActivities); 47 | 48 | Assert::assertSame('2017-06-01 06:40:00', $complaintActivities[0]->getDate()->format('Y-m-d H:i:s')); 49 | Assert::assertSame('6846253@gmail.ru', $complaintActivities[0]->getEmail()); 50 | Assert::assertSame(89, $complaintActivities[0]->getMessageId()); 51 | Assert::assertSame( 52 | '${Snippet(\'firstname\')}, cCongrats', 54 | $complaintActivities[0]->getMessageSubject() 55 | ); 56 | Assert::assertSame(81, $complaintActivities[0]->getListId()); 57 | Assert::assertSame('Torl', $complaintActivities[0]->getListName()); 58 | Assert::assertSame('8f5268e3-5980-473b-a369-c9b97cca0bc6', $complaintActivities[0]->getMessageGuid()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/Response/ActivitiesGetResponse/GoalsActivityGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class GoalsActivityGetResponseTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testGetCommonUsage() 23 | { 24 | $csv = 'Date,Email,MessageId,MessageSubject,GoalValue,ListId,ListName,MessageGuid 25 | 2017-06-01 06:40:00,6846253@gmail.ru,89,"${Snippet(\'firstname\')}, cCongrats",' 27 | . '100,81,Torl,8f5268e3-5980-473b-a369-c9b97cca0bc6 28 | 2017-06-01 15:31:00,skol@mail.com,26,"Subject",,15,Registration,' 29 | . 'db481b7d-0a2d-4b4e-a526-0f5994f71d9b'; 30 | 31 | $response = new GoalsActivityGetResponse( 32 | new Response( 33 | new \GuzzleHttp\Psr7\Response( 34 | 200, 35 | ['Content-Type' => 'text/csv', 'Content-Length' => strlen($csv)], 36 | $csv 37 | ) 38 | ) 39 | ); 40 | 41 | Assert::assertTrue($response->isOk()); 42 | Assert::assertFalse($response->isEmpty()); 43 | /** @var GoalActivity[] $goalActivities */ 44 | $goalActivities = toArray($response->getGoals()); 45 | 46 | Assert::assertCount(2, $goalActivities); 47 | 48 | Assert::assertSame('2017-06-01 06:40:00', $goalActivities[0]->getDate()->format('Y-m-d H:i:s')); 49 | Assert::assertSame('6846253@gmail.ru', $goalActivities[0]->getEmail()); 50 | Assert::assertSame(89, $goalActivities[0]->getMessageId()); 51 | Assert::assertSame( 52 | '${Snippet(\'firstname\')}, cCongrats', 54 | $goalActivities[0]->getMessageSubject() 55 | ); 56 | Assert::assertSame(81, $goalActivities[0]->getListId()); 57 | Assert::assertSame('Torl', $goalActivities[0]->getListName()); 58 | Assert::assertSame('8f5268e3-5980-473b-a369-c9b97cca0bc6', $goalActivities[0]->getMessageGuid()); 59 | Assert::assertSame(100, $goalActivities[0]->getGoalValue()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tests/Response/SnoozedSubscribersGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class SnoozedSubscribersGetResponseTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testCommonUsage() 23 | { 24 | $xml = ' 26 | 27 | 28 | 29 | testsnoozed1@test123.com 30 | 22 31 | 2014-03-05T11:13:04Z 32 | 33 | 34 | testsnoozed2@test123.com 35 | 101 36 | 2014-04-28T15:09:44Z 37 | 38 | 39 | 40 | '; 41 | $response = new SnoozedSubscribersGetResponse( 42 | new Response( 43 | new \GuzzleHttp\Psr7\Response( 44 | 200, 45 | ['Content-Length' => strlen($xml), 'Content-Type' => 'text/xml'], 46 | $xml 47 | ) 48 | ) 49 | ); 50 | 51 | Assert::assertTrue($response->isOk()); 52 | Assert::assertFalse($response->isEmpty()); 53 | /** @var SnoozedSubscriber[] $snoozedSubscribers */ 54 | $snoozedSubscribers = toArray($response->getSnoozedSubscribers()); 55 | 56 | Assert::assertCount(2, $snoozedSubscribers); 57 | 58 | Assert::assertEquals('testsnoozed1@test123.com', $snoozedSubscribers[0]->getEmail()); 59 | Assert::assertEquals(22, $snoozedSubscribers[0]->getListId()); 60 | Assert::assertEquals('2014-03-05 11:13:04', $snoozedSubscribers[0]->getSnoozedUntil()->format('Y-m-d H:i:s')); 61 | 62 | Assert::assertEquals('testsnoozed2@test123.com', $snoozedSubscribers[1]->getEmail()); 63 | Assert::assertEquals(101, $snoozedSubscribers[1]->getListId()); 64 | Assert::assertEquals('2014-04-28 15:09:44', $snoozedSubscribers[1]->getSnoozedUntil()->format('Y-m-d H:i:s')); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/Response/ActivitiesGetResponse/ClicksActivityGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class ClicksActivityGetResponseTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testGetCommonUsage() 23 | { 24 | $csv = 'Date,Email,MessageId,MessageSubject,Url,Title,ListId,ListName,MessageGuid 25 | 2017-06-01 06:40:00,6846253@gmail.ru,89,"${Snippet(\'firstname\')}, cCongrats",' 27 | . 'http://www.google.com/,,81,Torl,8f5268e3-5980-473b-a369-c9b97cca0bc6 28 | 2017-06-01 15:31:00,skol@mail.com,26,"Subject",http://mail.google.com/,,15,Registration,' 29 | . 'db481b7d-0a2d-4b4e-a526-0f5994f71d9b'; 30 | 31 | $response = new ClicksActivityGetResponse( 32 | new Response( 33 | new \GuzzleHttp\Psr7\Response( 34 | 200, 35 | ['Content-Type' => 'text/csv', 'Content-Length' => strlen($csv)], 36 | $csv 37 | ) 38 | ) 39 | ); 40 | 41 | Assert::assertTrue($response->isOk()); 42 | Assert::assertFalse($response->isEmpty()); 43 | /** @var ClickActivity[] $clicks */ 44 | $clicks = toArray($response->getClicks()); 45 | 46 | Assert::assertCount(2, $clicks); 47 | 48 | Assert::assertSame('2017-06-01 06:40:00', $clicks[0]->getDate()->format('Y-m-d H:i:s')); 49 | Assert::assertSame('6846253@gmail.ru', $clicks[0]->getEmail()); 50 | Assert::assertSame(89, $clicks[0]->getMessageId()); 51 | Assert::assertSame( 52 | '${Snippet(\'firstname\')}, cCongrats', 54 | $clicks[0]->getMessageSubject() 55 | ); 56 | Assert::assertSame('http://www.google.com/', $clicks[0]->getUrl()); 57 | Assert::assertSame('', $clicks[0]->getTitle()); 58 | Assert::assertSame(81, $clicks[0]->getListId()); 59 | Assert::assertSame('Torl', $clicks[0]->getListName()); 60 | Assert::assertSame('8f5268e3-5980-473b-a369-c9b97cca0bc6', $clicks[0]->getMessageGuid()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tests/Request/SnoozedSubscribersPostRequestTest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class SnoozedSubscribersPostRequestTest extends \PHPUnit_Framework_TestCase 15 | { 16 | /** 17 | * Test 18 | */ 19 | public function testCreateWithId() 20 | { 21 | $id = 567; 22 | $snoozedWeeks = 23; 23 | $listId = 27; 24 | $request = SnoozedSubscribersPostRequest::createWithId($id, $snoozedWeeks, $listId); 25 | 26 | $this->assertSame([], $request->getQueryParams()); 27 | $this->assertSame('/v2/Api/SnoozedSubscribers', $request->getUri()); 28 | $this->assertSame('5672723', $request->toXml()); 29 | $this->assertTrue($request->getMethod()->equals(HttpMethod::POST())); 30 | } 31 | 32 | /** 33 | * Test 34 | */ 35 | public function testCreateWithEmail() 36 | { 37 | $email = 'test@test.ru'; 38 | $snoozedWeeks = 23; 39 | $listId = 27; 40 | $request = SnoozedSubscribersPostRequest::createWithEmail($email, $snoozedWeeks, $listId); 41 | 42 | $this->assertSame([], $request->getQueryParams()); 43 | $this->assertSame('/v2/Api/SnoozedSubscribers', $request->getUri()); 44 | $this->assertSame('test@test.ru2723', $request->toXml()); 45 | $this->assertTrue($request->getMethod()->equals(HttpMethod::POST())); 46 | } 47 | 48 | /** 49 | * Test 50 | */ 51 | public function testXmlShouldNotContainListIdIfItValusIsNull() 52 | { 53 | $request = SnoozedSubscribersPostRequest::createWithId(567, 23); 54 | 55 | $this->assertSame('56723', $request->toXml()); 56 | } 57 | 58 | /** 59 | * Test 60 | * 61 | * @expectedException \InvalidArgumentException 62 | * @expectedExceptionMessage Expected a value greater than or equal to 1. Got: 0 63 | */ 64 | public function testConstructorShouldThrowExceptionIfSnoozeWeeksLessThanOne() 65 | { 66 | SnoozedSubscribersPostRequest::createWithId(567, 0); 67 | } 68 | 69 | /** 70 | * Test 71 | * 72 | * @expectedException \InvalidArgumentException 73 | * @expectedExceptionMessage Expected a value less than or equal to 26. Got: 27 74 | */ 75 | public function testConstructorShouldThrowExceptionIfSnoozeWeeksGreaterThan26() 76 | { 77 | SnoozedSubscribersPostRequest::createWithId(567, 27); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests/Response/ActivitiesGetResponse/RemovalsActivityGetResponseTest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class RemovalsActivityGetResponseTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * Test 21 | */ 22 | public function testGetCommonUsage() 23 | { 24 | $csv = 'Date,Email,Reason,MessageId,MessageSubject,ListId,ListName,MessageGuid 25 | 2017-06-01 06:40:00,6846253@gmail.ru,Api,89,"${Snippet(\'firstname\')}, cCongrats",' 27 | . '81,Torl,8f5268e3-5980-473b-a369-c9b97cca0bc6 28 | 2017-06-01 15:31:00,skol@mail.com,User,26,"Subject",,15,Registration,' 29 | . 'db481b7d-0a2d-4b4e-a526-0f5994f71d9b'; 30 | 31 | $response = new Response\ActivitiesGetResponse\RemovalsActivityGetResponse( 32 | new Response( 33 | new \GuzzleHttp\Psr7\Response( 34 | 200, 35 | ['Content-Type' => 'text/csv', 'Content-Length' => strlen($csv)], 36 | $csv 37 | ) 38 | ) 39 | ); 40 | 41 | Assert::assertTrue($response->isOk()); 42 | Assert::assertFalse($response->isEmpty()); 43 | /** @var RemovalActivity[] $removalActivities */ 44 | $removalActivities = toArray($response->getRemovals()); 45 | 46 | Assert::assertCount(2, $removalActivities); 47 | 48 | Assert::assertSame('2017-06-01 06:40:00', $removalActivities[0]->getDate()->format('Y-m-d H:i:s')); 49 | Assert::assertSame('6846253@gmail.ru', $removalActivities[0]->getEmail()); 50 | Assert::assertSame(89, $removalActivities[0]->getMessageId()); 51 | Assert::assertSame( 52 | '${Snippet(\'firstname\')}, cCongrats', 54 | $removalActivities[0]->getMessageSubject() 55 | ); 56 | Assert::assertSame(81, $removalActivities[0]->getListId()); 57 | Assert::assertSame('Torl', $removalActivities[0]->getListName()); 58 | Assert::assertSame('8f5268e3-5980-473b-a369-c9b97cca0bc6', $removalActivities[0]->getMessageGuid()); 59 | Assert::assertTrue($removalActivities[0]->getReason()->equals(RemovalReason::API())); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Request/DataTablesDeleteRowPostRequest.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class DataTablesDeleteRowPostRequest implements RequestInterface 18 | { 19 | use ColumnToXmlConverterTrait; 20 | 21 | /** 22 | * @var string Table name 23 | */ 24 | private $tableName; 25 | 26 | /** 27 | * Primary key columns 28 | * 29 | * Collection of Column elements. Contains unique identifier (PK, primary key) of the row that is supposed to be 30 | * deleted. This is an equivalent of SQL "WHERE" directive 31 | * 32 | * @var Column[] 33 | */ 34 | private $primaryKeyColumns; 35 | 36 | /** 37 | * Constructor 38 | * 39 | * @param string $tableName Table name 40 | * @param Column[] $primaryKeyColumns Primary key columns. Collection of Column elements. Contains unique 41 | * identifier (PK, primary key) of the row that is supposed to be deleted. This is an equivalent of SQL 42 | * "WHERE" directive 43 | */ 44 | public function __construct($tableName, array $primaryKeyColumns) 45 | { 46 | Assert::notEmpty($tableName); 47 | Assert::notEmpty($primaryKeyColumns); 48 | Assert::allIsInstanceOf($primaryKeyColumns, Column::class); 49 | $this->tableName = $tableName; 50 | $this->primaryKeyColumns = $primaryKeyColumns; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | public function toXml(): string 57 | { 58 | $xmlWriter = new \XMLWriter(); 59 | $xmlWriter->openMemory(); 60 | $xmlWriter->writeElement('TableName', $this->tableName); 61 | $xmlWriter->startElement('PrimaryKeyColumns'); 62 | foreach ($this->primaryKeyColumns as $primaryKeyColumn) { 63 | $this->convertColumnToXml($primaryKeyColumn, $xmlWriter); 64 | } 65 | 66 | $xmlWriter->endElement(); // PrimaryKeyColumns 67 | 68 | return $xmlWriter->flush(); 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function getQueryParams(): array 75 | { 76 | return []; 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | public function getMethod(): HttpMethod 83 | { 84 | return HttpMethod::POST(); 85 | } 86 | 87 | /** 88 | * {@inheritdoc} 89 | */ 90 | public function getUri(): string 91 | { 92 | return '/v2/Api/DataTablesDeleteRow'; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/SpecificCsvMethodResponse.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class SpecificCsvMethodResponse implements ResponseInterface 17 | { 18 | /** 19 | * @var ResponseInterface Response 20 | */ 21 | private $response; 22 | 23 | /** 24 | * Constructor. 25 | * 26 | * @param ResponseInterface $response Response 27 | */ 28 | public function __construct(ResponseInterface $response) 29 | { 30 | $this->response = $response; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public function isOk(): bool 37 | { 38 | return $this->response->isOk(); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function getHttpStatusCode(): int 45 | { 46 | return $this->response->getHttpStatusCode(); 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function getErrorCode(): ?int 53 | { 54 | return $this->response->getErrorCode(); 55 | 56 | } 57 | 58 | /** 59 | * {@inheritdoc} 60 | */ 61 | public function getContent(): string 62 | { 63 | return $this->response->getContent(); 64 | } 65 | 66 | /** 67 | * {@inheritdoc} 68 | */ 69 | public function getStream(): StreamInterface 70 | { 71 | return $this->response->getStream(); 72 | } 73 | 74 | /** 75 | * {@inheritdoc} 76 | */ 77 | public function getErrorMessages(): array 78 | { 79 | return $this->response->getErrorMessages(); 80 | } 81 | 82 | /** 83 | * Get csv reader 84 | * 85 | * @throws TryToAccessDataFromErrorResponseException If response has errors 86 | * 87 | * @return CsvReader Csv reader of data 88 | */ 89 | public function getCsvReader(): CsvReader 90 | { 91 | if (!$this->isOk()) { 92 | throw TryToAccessDataFromErrorResponseException::createFromResponse($this); 93 | } 94 | 95 | $newStream = new Stream(fopen('php://temp', 'r+')); 96 | copy_to_stream($this->getStream(), $newStream); 97 | $newStream->rewind(); 98 | $phpStream = $newStream->detach(); 99 | 100 | return new CsvReader($phpStream); 101 | } 102 | 103 | /** 104 | * {@inheritdoc} 105 | */ 106 | public function isEmpty(): bool 107 | { 108 | return $this->response->isEmpty(); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/ExpertSenderApi.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | class ExpertSenderApi 21 | { 22 | /** 23 | * @var RequestSenderInterface Request sender 24 | */ 25 | private $requestSender; 26 | 27 | /** 28 | * Constructor. 29 | * 30 | * @param RequestSenderInterface $requestSender Request sender 31 | */ 32 | public function __construct(RequestSenderInterface $requestSender) 33 | { 34 | $this->requestSender = $requestSender; 35 | } 36 | 37 | /** 38 | * Get Subscribers resource 39 | * 40 | * @return SubscribersResource Subscribers resource 41 | */ 42 | public function subscribers(): SubscribersResource 43 | { 44 | return new SubscribersResource($this->requestSender); 45 | } 46 | 47 | /** 48 | * Get server time response 49 | * 50 | * @return TimeGetResponse Server time response 51 | */ 52 | public function getServerTime(): TimeGetResponse 53 | { 54 | return new TimeGetResponse($this->requestSender->send(new TimeGetRequest())); 55 | } 56 | 57 | /** 58 | * Get bounces data 59 | * 60 | * @param \DateTime $startDate Start date 61 | * @param \DateTime $endDate End date 62 | * @param BounceType|null $bounceType Bounce type 63 | * 64 | * @return BouncesGetResponse Bounces data 65 | */ 66 | public function getBouncesList( 67 | \DateTime $startDate, 68 | \DateTime $endDate, 69 | BounceType $bounceType = null 70 | ): BouncesGetResponse { 71 | return new BouncesGetResponse( 72 | $this->requestSender->send(new BouncesGetRequest($startDate, $endDate, $bounceType)) 73 | ); 74 | } 75 | 76 | /** 77 | * Get data tables resource 78 | * 79 | * @return DataTablesResource Data tables resource 80 | */ 81 | public function dataTables(): DataTablesResource 82 | { 83 | return new DataTablesResource($this->requestSender); 84 | } 85 | 86 | /** 87 | * Get messages resource 88 | * 89 | * @return MessagesResource Messages resource 90 | */ 91 | public function messages(): MessagesResource 92 | { 93 | return new MessagesResource($this->requestSender); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Model/SubscriberData.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class SubscriberData 14 | { 15 | /** 16 | * @var int ID 17 | */ 18 | private $id; 19 | 20 | /** 21 | * @var string Firstname 22 | */ 23 | private $firstname; 24 | 25 | /** 26 | * @var string Lastname 27 | */ 28 | private $lastname; 29 | 30 | /** 31 | * @var string IP 32 | */ 33 | private $ip; 34 | 35 | /** 36 | * @var string Vendor 37 | */ 38 | private $vendor; 39 | 40 | /** 41 | * @var SubscriberProperty[]|iterable Properties 42 | */ 43 | private $properties; 44 | 45 | /** 46 | * Constructor 47 | * 48 | * @param int $id ID 49 | * @param string $firstname Firstname 50 | * @param string $lastname Lastname 51 | * @param string $ip IP 52 | * @param string $vendor Vendor 53 | * @param SubscriberProperty[]|iterable $properties Properties 54 | */ 55 | public function __construct( 56 | int $id, 57 | string $firstname, 58 | string $lastname, 59 | string $ip, 60 | string $vendor, 61 | iterable $properties 62 | ) { 63 | $this->id = $id; 64 | $this->firstname = $firstname; 65 | $this->lastname = $lastname; 66 | $this->ip = $ip; 67 | $this->vendor = $vendor; 68 | $this->properties = $properties; 69 | } 70 | 71 | /** 72 | * Get ID 73 | * 74 | * @return int ID 75 | */ 76 | public function getId(): int 77 | { 78 | return $this->id; 79 | } 80 | 81 | /** 82 | * Get firstname 83 | * 84 | * @return string Firstname 85 | */ 86 | public function getFirstname(): string 87 | { 88 | return $this->firstname; 89 | } 90 | 91 | /** 92 | * Get lastname 93 | * 94 | * @return string Lastname 95 | */ 96 | public function getLastname(): string 97 | { 98 | return $this->lastname; 99 | } 100 | 101 | /** 102 | * Get IP 103 | * 104 | * @return string IP 105 | */ 106 | public function getIp(): string 107 | { 108 | return $this->ip; 109 | } 110 | 111 | /** 112 | * Get vendor 113 | * 114 | * @return string Vendor 115 | */ 116 | public function getVendor(): string 117 | { 118 | return $this->vendor; 119 | } 120 | 121 | /** 122 | * Get properties 123 | * 124 | * @return SubscriberProperty[]|iterable Properties 125 | */ 126 | public function getProperties(): iterable 127 | { 128 | return $this->properties; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/Request/SubscribersDeleteRequest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class SubscribersDeleteRequest implements RequestInterface 15 | { 16 | /** 17 | * @var string|null Subscriber email 18 | */ 19 | private $email; 20 | 21 | /** 22 | * @var int|null Subscriber ID 23 | */ 24 | private $id; 25 | 26 | /** 27 | * @var int|null List ID 28 | */ 29 | private $listId; 30 | 31 | /** 32 | * Create request with ID as identifier 33 | * 34 | * @param int $id Subscriber ID 35 | * @param int|null $listId List ID 36 | * 37 | * @return static Request for delete subscriber 38 | */ 39 | public static function createFromId(int $id, int $listId = null) 40 | { 41 | return new static(null, $id, $listId); 42 | } 43 | 44 | /** 45 | * Create request with email as identifier 46 | * 47 | * @param string $email Subscriber email 48 | * @param int|null $listId List ID 49 | * 50 | * @return static Request for delete subscriber 51 | */ 52 | public static function createFromEmail(string $email, int $listId = null) 53 | { 54 | return new static($email, null, $listId); 55 | } 56 | 57 | /** 58 | * Constructor 59 | * 60 | * @param null|string $email Subscriber email 61 | * @param int|null $id Subscriber ID 62 | * @param int|null $listId List ID 63 | */ 64 | private function __construct(string $email = null, int $id = null, int $listId = null) 65 | { 66 | $this->email = $email; 67 | $this->id = $id; 68 | $this->listId = $listId; 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | */ 74 | public function toXml(): string 75 | { 76 | return ''; 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | */ 82 | public function getQueryParams(): array 83 | { 84 | $params = []; 85 | if (!empty($this->email)) { 86 | $params['email'] = $this->email; 87 | } 88 | 89 | if (!empty($this->id)) { 90 | $params['id'] = $this->id; 91 | } 92 | 93 | if (!empty($this->listId)) { 94 | $params['listId'] = $this->listId; 95 | } 96 | 97 | return $params; 98 | } 99 | 100 | /** 101 | * {@inheritdoc} 102 | */ 103 | public function getMethod(): HttpMethod 104 | { 105 | return HttpMethod::DELETE(); 106 | } 107 | 108 | /** 109 | * {@inheritdoc} 110 | */ 111 | public function getUri(): string 112 | { 113 | return '/v2/Api/Subscribers'; 114 | } 115 | } 116 | --------------------------------------------------------------------------------