diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 6e5393c3..4807506f 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -29,6 +29,7 @@ ->in(__DIR__ . '/src/Services/SonetGroup/') ->in(__DIR__ . '/src/Services/IMOpenLines/') ->in(__DIR__ . '/src/Services/Landing/') + ->in(__DIR__ . '/src/Services/MailService/') ->name('*.php') ->exclude(['vendor', 'storage', 'docker', 'docs']) // Exclude directories ->ignoreDotFiles(true) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4bc3b52..3ced0bc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ ### Added +- Added service `Services\MailService` with support for `mailservice.*` methods, + see [mailservice.* methods](https://apidocs.bitrix24.com/api-reference/mailservice/index.html) ([#495](https://github.com/bitrix24/b24phpsdk/issues/495)): + - `add` creates a new mail service (IMAP integration), with batch calls support + - `update` updates an existing mail service, with batch calls support + - `get` gets information about a mail service by its identifier + - `list` gets the list of active mail services, with batch calls support + - `delete` deletes a mail service, with batch calls support + - `fields` returns localized field labels of a mail service + - `count` counts active mail services + - Added service `Services\Landing\Site\Service\Site` with support methods, see [landing.site.* methods](https://github.com/bitrix24/b24phpsdk/issues/267): - `add` adds a site diff --git a/Makefile b/Makefile index c2fc4a9a..8bc3f4f6 100644 --- a/Makefile +++ b/Makefile @@ -69,7 +69,7 @@ help: @echo "test-integration-landing-role - run Landing Role integration tests" @echo "test-integration-landing-repowidget - run Landing RepoWidget integration tests" @echo "test-integration-scope-landing-template - run Landing Template integration tests" - + @echo "test-integration-mailservice - run MailService integration tests" .PHONY: docker-init docker-init: @@ -492,6 +492,10 @@ test-integration-landing-role: test-integration-landing-repowidget: docker compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_landing_repowidget +.PHONY: test-integration-mailservice +test-integration-mailservice: + docker compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_mailservice + # work dev environment .PHONY: php-dev-server-up php-dev-server-up: diff --git a/phpstan.neon.dist b/phpstan.neon.dist index e6ce503a..055dd738 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -37,6 +37,7 @@ parameters: - tests/Integration/Services/CRM/Documentgenerator/Document - tests/Integration/Services/CRM/Documentgenerator/Template - tests/Integration/Services/Landing + - tests/Integration/Services/MailService excludePaths: - tests/Integration/Services/CRM/Requisites/Service/RequisiteUserfieldUseCaseTest.php - tests/Integration/Services/CRM/Status diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d0187ae5..eda20536 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -262,6 +262,9 @@ ./tests/Integration/Services/Landing/RepoWidget/ + + ./tests/Integration/Services/MailService/ + diff --git a/rector.php b/rector.php index fb38e858..fbbae7cb 100644 --- a/rector.php +++ b/rector.php @@ -78,6 +78,8 @@ __DIR__ . '/tests/Integration/Services/CRM/Documentgenerator/Template', __DIR__ . '/src/Services/Landing', __DIR__ . '/tests/Integration/Services/Landing', + __DIR__ . '/src/Services/MailService', + __DIR__ . '/tests/Integration/Services/MailService', __DIR__ . '/tests/Unit/', ]) ->withCache(cacheDirectory: __DIR__ . '/var/.cache/rector') diff --git a/src/Services/MailService/Batch.php b/src/Services/MailService/Batch.php new file mode 100644 index 00000000..fc87459e --- /dev/null +++ b/src/Services/MailService/Batch.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\MailService; + +use Bitrix24\SDK\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Response\DTO\ResponseData; +use Generator; +use Psr\Log\LoggerInterface; + +/** + * Custom Batch for MailService scope. + * + * Overrides updateEntityItems to pass ID as a top-level key (flat structure), + * matching the mailservice.update parameter format which does not use nested 'fields'. + * + * @see https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-update.html + */ +class Batch extends \Bitrix24\SDK\Core\Batch +{ + public function __construct(CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + /** + * Update mail service items with batch call. + * + * Expects array structure: + * [ + * $mailServiceId => ['NAME' => '...', 'ACTIVE' => 'Y', ...], + * ... + * ] + * + * @param array> $entityItems + * + * @return Generator + * @throws BaseException + */ + #[\Override] + public function updateEntityItems(string $apiMethod, array $entityItems): Generator + { + $this->logger->debug( + 'updateEntityItems.start', + [ + 'apiMethod' => $apiMethod, + 'entityItems' => $entityItems, + ] + ); + + try { + $this->clearCommands(); + foreach ($entityItems as $entityItemId => $entityItem) { + if (!is_int($entityItemId)) { + throw new InvalidArgumentException( + sprintf( + 'invalid type «%s» of mail service id «%s», the id must be integer type', + gettype($entityItemId), + $entityItemId + ) + ); + } + + $entityItem['ID'] = $entityItemId; + $cmdArguments = $entityItem; + + $this->registerCommand($apiMethod, $cmdArguments); + } + + foreach ($this->getTraversable(true) as $cnt => $updatedItemResult) { + yield $cnt => $updatedItemResult; + } + } catch (InvalidArgumentException $exception) { + $errorMessage = sprintf('batch update entity items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + throw $exception; + } catch (\Throwable $exception) { + $errorMessage = sprintf('batch update entity items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + + throw new BaseException($errorMessage, $exception->getCode(), $exception); + } + + $this->logger->debug('updateEntityItems.finish'); + } +} diff --git a/src/Services/MailService/MailServiceServiceBuilder.php b/src/Services/MailService/MailServiceServiceBuilder.php new file mode 100644 index 00000000..ab9ee969 --- /dev/null +++ b/src/Services/MailService/MailServiceServiceBuilder.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\MailService; + +use Bitrix24\SDK\Attributes\ApiServiceBuilderMetadata; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Services\AbstractServiceBuilder; +use Bitrix24\SDK\Services\MailService; + +#[ApiServiceBuilderMetadata(new Scope(['mailservice']))] +class MailServiceServiceBuilder extends AbstractServiceBuilder +{ + public function mailService(): MailService\Service\MailService + { + if (!isset($this->serviceCache[__METHOD__])) { + $batch = new MailService\Batch( + $this->core, + $this->log + ); + $this->serviceCache[__METHOD__] = new MailService\Service\MailService( + new MailService\Service\Batch($batch, $this->log), + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } +} diff --git a/src/Services/MailService/Result/MailServiceItemResult.php b/src/Services/MailService/Result/MailServiceItemResult.php new file mode 100644 index 00000000..d87de3c7 --- /dev/null +++ b/src/Services/MailService/Result/MailServiceItemResult.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\MailService\Result; + +use Bitrix24\SDK\Core\Result\AbstractItem; + +/** + * Mail service item result. + * + * @property-read int $ID + * @property-read string $SITE_ID + * @property-read bool $ACTIVE + * @property-read int $SORT + * @property-read string $NAME + * @property-read string $SERVER + * @property-read int|null $PORT + * @property-read bool $ENCRYPTION + * @property-read string $LINK + * @property-read string|null $ICON + * @property-read string|null $SMTP_SERVER + * @property-read int|null $SMTP_PORT + * @property-read bool $SMTP_LOGIN_AS_IMAP + * @property-read bool $SMTP_PASSWORD_AS_IMAP + * @property-read bool|null $SMTP_ENCRYPTION + * @property-read bool|null $UPLOAD_OUTGOING + */ +class MailServiceItemResult extends AbstractItem +{ + public function __get($offset) + { + return match ($offset) { + 'ID', 'SORT', 'PORT', 'SMTP_PORT' => isset($this->data[$offset]) ? (int)$this->data[$offset] : null, + 'ACTIVE', 'ENCRYPTION', 'SMTP_LOGIN_AS_IMAP', 'SMTP_PASSWORD_AS_IMAP' => $this->data[$offset] === 'Y', + 'SMTP_ENCRYPTION', 'UPLOAD_OUTGOING' => isset($this->data[$offset]) ? $this->data[$offset] === 'Y' : null, + default => $this->data[$offset] ?? null, + }; + } +} diff --git a/src/Services/MailService/Result/MailServiceResult.php b/src/Services/MailService/Result/MailServiceResult.php new file mode 100644 index 00000000..361e5942 --- /dev/null +++ b/src/Services/MailService/Result/MailServiceResult.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\MailService\Result; + +use Bitrix24\SDK\Core\Result\AbstractResult; + +/** + * Single mail service result for mailservice.get. + * + * @see https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-get.html + */ +class MailServiceResult extends AbstractResult +{ + /** + * Get mail service item. + */ + public function mailService(): MailServiceItemResult + { + return new MailServiceItemResult($this->getCoreResponse()->getResponseData()->getResult()); + } +} diff --git a/src/Services/MailService/Result/MailServicesResult.php b/src/Services/MailService/Result/MailServicesResult.php new file mode 100644 index 00000000..8641ace0 --- /dev/null +++ b/src/Services/MailService/Result/MailServicesResult.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\MailService\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +/** + * Mail services list result for mailservice.list. + * + * @see https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-list.html + */ +class MailServicesResult extends AbstractResult +{ + /** + * Get mail service items. + * + * @return MailServiceItemResult[] + * @throws BaseException + */ + public function getMailServices(): array + { + $items = []; + foreach ($this->getCoreResponse()->getResponseData()->getResult() as $item) { + $items[] = new MailServiceItemResult($item); + } + + return $items; + } +} diff --git a/src/Services/MailService/Service/Batch.php b/src/Services/MailService/Service/Batch.php new file mode 100644 index 00000000..6c443298 --- /dev/null +++ b/src/Services/MailService/Service/Batch.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\MailService\Service; + +use Bitrix24\SDK\Attributes\ApiBatchMethodMetadata; +use Bitrix24\SDK\Attributes\ApiBatchServiceMetadata; +use Bitrix24\SDK\Core\Contracts\BatchOperationsInterface; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AddedItemBatchResult; +use Bitrix24\SDK\Core\Result\DeletedItemBatchResult; +use Bitrix24\SDK\Core\Result\UpdatedItemBatchResult; +use Bitrix24\SDK\Services\MailService\Result\MailServiceItemResult; +use Generator; +use Psr\Log\LoggerInterface; + +#[ApiBatchServiceMetadata(new Scope(['mailservice']))] +class Batch +{ + public function __construct(protected BatchOperationsInterface $batch, protected LoggerInterface $log) + { + } + + /** + * Batch list of mail services. + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-list.html + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'mailservice.list', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-list.html', + 'Batch list of mail services' + )] + public function list(?int $limit = null): Generator + { + $this->log->debug( + 'batchList', + [ + 'limit' => $limit, + ] + ); + foreach ($this->batch->getTraversableList('mailservice.list', [], [], [], $limit) as $key => $value) { + yield $key => new MailServiceItemResult($value); + } + } + + /** + * Batch add mail services. + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-add.html + * + * @param array $mailServices + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'mailservice.add', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-add.html', + 'Batch add mail services' + )] + public function add(array $mailServices): Generator + { + foreach ($this->batch->addEntityItems('mailservice.add', $mailServices) as $key => $item) { + yield $key => new AddedItemBatchResult($item); + } + } + + /** + * Batch update mail services. + * + * Array structure: [$mailServiceId => ['NAME' => '...', ...], ...] + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-update.html + * + * @param array> $mailServiceItems + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'mailservice.update', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-update.html', + 'Batch update mail services' + )] + public function update(array $mailServiceItems): Generator + { + foreach ($this->batch->updateEntityItems('mailservice.update', $mailServiceItems) as $key => $item) { + yield $key => new UpdatedItemBatchResult($item); + } + } + + /** + * Batch delete mail services. + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-delete.html + * + * @param int[] $mailServiceIds + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'mailservice.delete', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-delete.html', + 'Batch delete mail services' + )] + public function delete(array $mailServiceIds): Generator + { + foreach ($this->batch->deleteEntityItems('mailservice.delete', $mailServiceIds) as $key => $item) { + yield $key => new DeletedItemBatchResult($item); + } + } +} diff --git a/src/Services/MailService/Service/MailService.php b/src/Services/MailService/Service/MailService.php new file mode 100644 index 00000000..c547935c --- /dev/null +++ b/src/Services/MailService/Service/MailService.php @@ -0,0 +1,206 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Services\MailService\Service; + +use Bitrix24\SDK\Attributes\ApiEndpointMetadata; +use Bitrix24\SDK\Attributes\ApiServiceMetadata; +use Bitrix24\SDK\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Core\Result\AddedItemResult; +use Bitrix24\SDK\Core\Result\DeletedItemResult; +use Bitrix24\SDK\Core\Result\FieldsResult; +use Bitrix24\SDK\Core\Result\UpdatedItemResult; +use Bitrix24\SDK\Services\AbstractService; +use Bitrix24\SDK\Services\MailService\Result\MailServiceResult; +use Bitrix24\SDK\Services\MailService\Result\MailServicesResult; +use Psr\Log\LoggerInterface; + +#[ApiServiceMetadata(new Scope(['mailservice']))] +class MailService extends AbstractService +{ + public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + /** + * Add a new mail service. + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-add.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'mailservice.add', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-add.html', + 'Creates a new mail service for the current Bitrix24' + )] + public function add( + string $name, + string $active = 'Y', + string $server = '', + int $port = 993, + string $encryption = 'Y', + string $link = '', + int $sort = 100 + ): AddedItemResult { + $params = [ + 'NAME' => $name, + 'ACTIVE' => $active, + 'SORT' => $sort, + ]; + if ($server !== '') { + $params['SERVER'] = $server; + } + + if ($port !== 993) { + $params['PORT'] = $port; + } + + if ($link !== '') { + $params['LINK'] = $link; + } + + $params['ENCRYPTION'] = $encryption; + + return new AddedItemResult( + $this->core->call('mailservice.add', $params) + ); + } + + /** + * Update an existing mail service. + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-update.html + * + * @param array{ + * NAME?: string, + * ACTIVE?: string, + * SERVER?: string, + * PORT?: int, + * ENCRYPTION?: string, + * LINK?: string, + * SORT?: int, + * } $fields + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'mailservice.update', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-update.html', + 'Updates an existing mail service parameters' + )] + public function update(int $id, array $fields): UpdatedItemResult + { + $params = $fields; + $params['ID'] = $id; + + return new UpdatedItemResult( + $this->core->call('mailservice.update', $params) + ); + } + + /** + * Get mail service by ID. + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-get.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'mailservice.get', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-get.html', + 'Returns mail service parameters by its identifier' + )] + public function get(int $id): MailServiceResult + { + return new MailServiceResult( + $this->core->call('mailservice.get', ['ID' => $id]) + ); + } + + /** + * Get list of active mail services. + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-list.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'mailservice.list', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-list.html', + 'Returns the list of active mail services' + )] + public function list(): MailServicesResult + { + return new MailServicesResult( + $this->core->call('mailservice.list') + ); + } + + /** + * Delete a mail service by ID. + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-delete.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'mailservice.delete', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-delete.html', + 'Deletes a mail service by its identifier' + )] + public function delete(int $id): DeletedItemResult + { + return new DeletedItemResult( + $this->core->call('mailservice.delete', ['ID' => $id]) + ); + } + + /** + * Get the localized field labels of a mail service. + * + * @link https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-fields.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'mailservice.fields', + 'https://apidocs.bitrix24.com/api-reference/mailservice/mailservice-fields.html', + 'Returns localized field labels of mail service' + )] + public function fields(): FieldsResult + { + return new FieldsResult($this->core->call('mailservice.fields')); + } + + /** + * Count active mail services. + * + * @throws BaseException + * @throws TransportException + */ + public function count(): int + { + return count($this->list()->getMailServices()); + } +} diff --git a/src/Services/ServiceBuilder.php b/src/Services/ServiceBuilder.php index 4c1026e5..f8d7184a 100644 --- a/src/Services/ServiceBuilder.php +++ b/src/Services/ServiceBuilder.php @@ -37,6 +37,7 @@ use Bitrix24\SDK\Services\Paysystem\PaysystemServiceBuilder; use Bitrix24\SDK\Services\SonetGroup\SonetGroupServiceBuilder; use Bitrix24\SDK\Services\Landing\LandingServiceBuilder; +use Bitrix24\SDK\Services\MailService\MailServiceServiceBuilder; use Psr\Log\LoggerInterface; class ServiceBuilder extends AbstractServiceBuilder @@ -349,4 +350,18 @@ public function getLandingScope(): LandingServiceBuilder return $this->serviceCache[__METHOD__]; } + + public function getMailServiceScope(): MailServiceServiceBuilder + { + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new MailServiceServiceBuilder( + $this->core, + $this->batch, + $this->bulkItemsReader, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } } diff --git a/tests/Integration/Services/MailService/Result/MailServiceItemResultAnnotationsTest.php b/tests/Integration/Services/MailService/Result/MailServiceItemResultAnnotationsTest.php new file mode 100644 index 00000000..f62c2662 --- /dev/null +++ b/tests/Integration/Services/MailService/Result/MailServiceItemResultAnnotationsTest.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\MailService\Result; + +use Bitrix24\SDK\Services\MailService\Result\MailServiceItemResult; +use Bitrix24\SDK\Services\MailService\Service\MailService; +use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(MailServiceItemResult::class)] +class MailServiceItemResultAnnotationsTest extends TestCase +{ + use CustomBitrix24Assertions; + + private MailService $mailService; + + private int $testMailServiceId = 0; + + #[\Override] + protected function setUp(): void + { + $this->mailService = Fabric::getServiceBuilder()->getMailServiceScope()->mailService(); + $this->testMailServiceId = $this->mailService->add( + 'SDK Annotations Test MailService', + 'Y', + 'imap.example.com', + 993, + 'Y', + 'https://mail.example.com' + )->getId(); + } + + #[\Override] + protected function tearDown(): void + { + if ($this->testMailServiceId > 0) { + $this->mailService->delete($this->testMailServiceId); + } + } + + #[Test] + #[TestDox('all system fields are annotated in MailServiceItemResult phpdoc')] + public function testAllSystemFieldsAnnotated(): void + { + $rawItem = $this->mailService->get($this->testMailServiceId) + ->getCoreResponse() + ->getResponseData() + ->getResult(); + + $this->assertBitrix24AllResultItemFieldsAnnotated( + array_keys($rawItem), + MailServiceItemResult::class + ); + } +} diff --git a/tests/Integration/Services/MailService/Service/BatchTest.php b/tests/Integration/Services/MailService/Service/BatchTest.php new file mode 100644 index 00000000..02f36d30 --- /dev/null +++ b/tests/Integration/Services/MailService/Service/BatchTest.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\MailService\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\MailService\Service\Batch; +use Bitrix24\SDK\Services\MailService\Service\MailService; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(Batch::class)] +class BatchTest extends TestCase +{ + private MailService $mailService; + + #[\Override] + protected function setUp(): void + { + $this->mailService = Fabric::getServiceBuilder()->getMailServiceScope()->mailService(); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('batch add creates multiple mail services')] + public function testBatchAdd(): void + { + $items = []; + for ($i = 1; $i <= 3; $i++) { + $items[] = [ + 'NAME' => 'SDK Batch Test MailService ' . $i, + 'ACTIVE' => 'Y', + 'SERVER' => 'imap.example' . $i . '.com', + 'PORT' => 993, + 'ENCRYPTION' => 'Y', + ]; + } + + $ids = []; + $cnt = 0; + foreach ($this->mailService->batch->add($items) as $result) { + $cnt++; + $ids[] = $result->getId(); + } + + self::assertSame(count($items), $cnt); + + // cleanup + foreach ($this->mailService->batch->delete($ids) as $deleteResult) { + // iterate to trigger execution + } + } + + /** + * @throws BaseException + */ + #[TestDox('batch delete removes multiple mail services')] + public function testBatchDelete(): void + { + $items = []; + for ($i = 1; $i <= 3; $i++) { + $items[] = [ + 'NAME' => 'SDK Batch Delete Test ' . $i, + 'ACTIVE' => 'Y', + 'ENCRYPTION' => 'N', + ]; + } + + $ids = []; + foreach ($this->mailService->batch->add($items) as $result) { + $ids[] = $result->getId(); + } + + $cnt = 0; + foreach ($this->mailService->batch->delete($ids) as $deleteResult) { + $cnt++; + self::assertTrue($deleteResult->isSuccess()); + } + + self::assertSame(count($items), $cnt); + } + + /** + * @throws BaseException + */ + #[TestDox('batch update modifies multiple mail services')] + public function testBatchUpdate(): void + { + $items = []; + for ($i = 1; $i <= 3; $i++) { + $items[] = [ + 'NAME' => 'SDK Batch Update Test ' . $i, + 'ACTIVE' => 'Y', + 'ENCRYPTION' => 'N', + ]; + } + + $ids = []; + foreach ($this->mailService->batch->add($items) as $result) { + $ids[] = $result->getId(); + } + + $updates = []; + foreach ($ids as $id) { + $updates[$id] = [ + 'NAME' => 'SDK Batch Updated ' . $id, + ]; + } + + $cnt = 0; + foreach ($this->mailService->batch->update($updates) as $updateResult) { + $cnt++; + self::assertTrue($updateResult->isSuccess()); + } + + self::assertSame(count($updates), $cnt); + + // cleanup + foreach ($this->mailService->batch->delete($ids) as $deleteResult) { + // iterate to trigger execution + } + } +} diff --git a/tests/Integration/Services/MailService/Service/MailServiceTest.php b/tests/Integration/Services/MailService/Service/MailServiceTest.php new file mode 100644 index 00000000..8d6a744d --- /dev/null +++ b/tests/Integration/Services/MailService/Service/MailServiceTest.php @@ -0,0 +1,194 @@ + + * + * For the full copyright and license information, please view the MIT-LICENSE.txt + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Bitrix24\SDK\Tests\Integration\Services\MailService\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\MailService\Service\MailService; +use Bitrix24\SDK\Tests\Integration\Fabric; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +#[CoversClass(MailService::class)] +class MailServiceTest extends TestCase +{ + private MailService $mailService; + + private int $testMailServiceId = 0; + + #[\Override] + protected function setUp(): void + { + $this->mailService = Fabric::getServiceBuilder()->getMailServiceScope()->mailService(); + } + + #[\Override] + protected function tearDown(): void + { + if ($this->testMailServiceId > 0) { + $this->mailService->delete($this->testMailServiceId); + $this->testMailServiceId = 0; + } + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('add creates a new mail service and returns its ID')] + public function testAdd(): void + { + $addedItemResult = $this->mailService->add( + 'SDK Test MailService', + 'Y', + 'imap.example.com', + 993, + 'Y', + 'https://mail.example.com' + ); + $this->testMailServiceId = $addedItemResult->getId(); + + self::assertGreaterThan(0, $this->testMailServiceId); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('update modifies an existing mail service')] + public function testUpdate(): void + { + $this->testMailServiceId = $this->mailService->add( + 'SDK Test MailService Update', + 'Y', + 'imap.example.com', + 993, + 'Y', + 'https://mail.example.com' + )->getId(); + + $updatedName = 'SDK Test MailService Updated'; + $updatedItemResult = $this->mailService->update($this->testMailServiceId, ['NAME' => $updatedName]); + + self::assertTrue($updatedItemResult->isSuccess()); + + $mailServiceItemResult = $this->mailService->get($this->testMailServiceId)->mailService(); + self::assertSame($updatedName, $mailServiceItemResult->NAME); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('get returns a mail service by its ID')] + public function testGet(): void + { + $this->testMailServiceId = $this->mailService->add( + 'SDK Test MailService Get', + 'Y', + 'imap.example.com', + 993, + 'Y', + 'https://mail.example.com' + )->getId(); + + $mailServiceItemResult = $this->mailService->get($this->testMailServiceId)->mailService(); + + self::assertSame($this->testMailServiceId, $mailServiceItemResult->ID); + self::assertSame('SDK Test MailService Get', $mailServiceItemResult->NAME); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('list returns active mail services')] + public function testList(): void + { + $this->testMailServiceId = $this->mailService->add( + 'SDK Test MailService List', + 'Y', + 'imap.example.com', + 993, + 'Y', + 'https://mail.example.com' + )->getId(); + + $items = $this->mailService->list()->getMailServices(); + + self::assertIsArray($items); + self::assertGreaterThanOrEqual(1, count($items)); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('delete removes a mail service')] + public function testDelete(): void + { + $id = $this->mailService->add( + 'SDK Test MailService Delete', + 'Y', + 'imap.example.com', + 993, + 'Y', + 'https://mail.example.com' + )->getId(); + + $deletedItemResult = $this->mailService->delete($id); + + self::assertTrue($deletedItemResult->isSuccess()); + // prevent double-delete in tearDown + $this->testMailServiceId = 0; + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('fields returns localized field labels')] + public function testFields(): void + { + $fields = $this->mailService->fields()->getFieldsDescription(); + + self::assertIsArray($fields); + self::assertArrayHasKey('ID', $fields); + self::assertArrayHasKey('NAME', $fields); + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('count returns number of active mail services')] + public function testCount(): void + { + $before = $this->mailService->count(); + + $this->testMailServiceId = $this->mailService->add( + 'SDK Test MailService Count', + 'Y', + 'imap.example.com', + 993, + 'Y', + 'https://mail.example.com' + )->getId(); + + $after = $this->mailService->count(); + + self::assertSame($before + 1, $after); + } +}