diff --git a/.tasks/589/plan.md b/.tasks/589/plan.md new file mode 100644 index 00000000..3614792a --- /dev/null +++ b/.tasks/589/plan.md @@ -0,0 +1,485 @@ +# Plan: Add support for catalog.userfield.document.* methods (issue #589) + +## Context + +Bitrix24 REST API exposes two methods for reading/writing custom (userfield) values attached to +warehouse accounting documents (`catalog.document.*`): + +- `catalog.userfield.document.list` — https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-list.html +- `catalog.userfield.document.update` — https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-update.html + +### Method details (fetched via Bitrix24 REST API MCP) + +**`catalog.userfield.document.list`** +- Params: `select` (array, **required** — must include `documentType`), `filter` (object, **required** — + must include `documentType`; keys may use `>=`/`>` prefixes), `order`, `start`. +- Response: `result.documents` (array of dynamic objects), `next` (offset for next page, present only + if more records exist), `total` (omitted when `start=-1`). +- Each item in `documents[]` always contains `documentId` (int) and `documentType` (string), plus zero + or more dynamic `fieldN` keys (N = userfield numeric ID, e.g. `field7097`) — the userfield set differs + per portal, so these keys cannot be statically enumerated. +- Errors include "documentType field is not specified in select/filter parameter". + +**`catalog.userfield.document.update`** +- Params: `documentId` (int, required), `fields` (object, required) containing `documentType` (string) + and one or more `fieldN` (mixed) values to set. +- Response: `result.document` — single object with `documentId`, `documentType`, and the updated dynamic + `fieldN` keys. +- Single-document only (no batch/list variant of update in the docs). + +### Generator usage — explicitly skipped + +Per the b24phpsdk-maintainer skill, `make oa-schema-build` was run successfully and +`docs/open-api/openapi.json` was rebuilt (220 paths, snapshot sourced from the portal's registered +local-app REST methods). `catalog.userfield.document.list` / `.update` are **not present** in that +snapshot (confirmed by running `php bin/console b24-dev:result-item-generator +catalog.userfield.document.list --stage=all`, which fails with "REST docs payload is required ... but +the documentation URL could not be resolved"). Therefore the `*ItemResult.php` generator, the +`*SelectBuilder.php` generator, and the `*ItemBuilder.php` generator cannot be used for this issue. +All SDK files are written manually, following the existing `Catalog\Document` / +`Catalog\DocumentElement` scope pattern (same parent scope, same author, same coding style). + +### Design decision — dynamic userfield keys (confirmed with user) + +`UserfieldDocumentItemResult` extends `AbstractAnnotatedItem` and annotates **only** the two fixed +system keys: `documentId` (int) and `documentType` (string). Dynamic `fieldN` keys remain accessible +through the inherited magic `__get()` (from `AbstractItem`) without annotation/type-casting — this is +consistent with how `AbstractAnnotatedItem::__get()` falls back to the raw value when no annotation +type is found for an offset. + +The mandatory annotation integration test (`UserfieldDocumentItemResultTest`) normalizes the raw API +response by keeping only the fixed system keys (`documentId`, `documentType`) before calling +`assertBitrix24AllResultItemFieldsAnnotated()`, per the "normalize the field keys" guidance in +`docs/testing.md`. A separate assertion in the same test confirms a dynamically-added userfield value +is readable via magic getter (not covered by the shared annotation assertion, since it's inherently +dynamic). + +### Batch support + +`update` takes a single `documentId` + `fields` object — same one-at-a-time shape as +`catalog.document.update`. A batch wrapper is added for consistency with the rest of the SDK +(`Catalog\Document\Service\Batch`, `Catalog\DocumentElement\Service\Batch`), using a custom +`Catalog\UserfieldDocument\Batch` extending the core `Batch` class because the id key is `documentId`, +not the base class's default `ID`. + +`list` does not need a batch wrapper (batch is for id-keyed add/update/delete operations, not for +paginated reads). `UserfieldDocument::list()` mirrors `Document::list()`'s signature shape +(`select`, `filter`) plus the two extra `list`-specific parameters this method supports (`order`, +`start`) for manual pagination. Unlike `DocumentsResult` (which has no `next`/`total` in its API +response), `UserfieldDocumentsResult` exposes `getNext(): ?int` and `getTotal(): ?int`, backed by the +existing `ResponseData::getPagination()` mechanism. + +--- + +## Files to Create + +### 1. `src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResult.php` + +```php +getCoreResponse()->getResponseData()->getResult()['document']); + } +} +``` + +### 3. `src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentsResult.php` + +```php +getCoreResponse()->getResponseData()->getResult(); + + return array_map( + static fn (array $item): UserfieldDocumentItemResult => new UserfieldDocumentItemResult($item), + $result['documents'] ?? [] + ); + } + + /** + * @throws BaseException + */ + public function getNext(): ?int + { + return $this->getCoreResponse()->getResponseData()->getPagination()->getNextItem(); + } + + /** + * @throws BaseException + */ + public function getTotal(): ?int + { + return $this->getCoreResponse()->getResponseData()->getPagination()->getTotal(); + } +} +``` + +Confirmed: `ResponseData::getPagination()` → `Pagination::getNextItem()` / `getTotal()` is the existing +SDK-wide mechanism (used internally by `Core\Batch`), reused here directly — no hand-rolled parsing. + +### 4. `src/Services/Catalog/UserfieldDocument/Batch.php` + +**Resolved during implementation:** overriding `determineKeyId()` alone is insufficient — +`Core\Batch::updateEntityItems()` hardcodes the command argument key to `'id'` (it does not consult +`determineKeyId()` at all; that hook is only used by other codepaths such as `deleteEntityItems()`). +Confirmed via a live batch-update integration test failure: `"could not find value for parameter +{documentid}"`. The fix is to override `updateEntityItems()` itself, building the command with +`'documentId'` instead of `'id'` (mirrors the base class's structure/exception handling, adapted for +the single supported case: `catalog.userfield.document.update`). + +```php +core->call( + 'catalog.userfield.document.list', + ['select' => $select, 'filter' => $filter, 'order' => $order, 'start' => $start] + ) + ); + } + + /** + * Updates userfield values of a warehouse accounting document. + * $fields must contain «documentType» plus the fieldN values to update. + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-update.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.userfield.document.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-update.html', + 'Updates userfield values of a warehouse accounting document' + )] + public function update(int $documentId, array $fields): UserfieldDocumentResult + { + return new UserfieldDocumentResult( + $this->core->call('catalog.userfield.document.update', ['documentId' => $documentId, 'fields' => $fields]) + ); + } +} +``` + +### 6. `src/Services/Catalog/UserfieldDocument/Service/Batch.php` + +```php + $documents keyed by document id, each value is the «fields» payload + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.userfield.document.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-update.html', + 'Batch update userfield values of warehouse accounting documents' + )] + public function update(array $documents): Generator + { + $items = []; + foreach ($documents as $id => $document) { + $items[$id] = ['fields' => $document]; + } + + foreach ($this->batch->updateEntityItems('catalog.userfield.document.update', $items) as $key => $item) { + yield $key => new UserfieldDocumentUpdatedBatchResult($item); + } + } +} +``` + +### 7. `src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentUpdatedBatchResult.php` + +Mirrors `Catalog\Document\Result\DocumentUpdatedBatchResult` — check that file's exact shape (it wraps +`UpdatedItemBatchResult` or similar core class) before writing an equivalent for userfield documents. + +### 8. `tests/Unit/Services/Catalog/UserfieldDocument/Service/UserfieldDocumentTest.php` + +Unit tests mirroring `tests/Unit/Services/Catalog/Document/Service/DocumentTest.php` pattern +(`mockCore()` + `makeService()` helpers): assert `list()` and `update()` build the correct REST +parameters and return the correct Result type. No HTTP calls (uses `createMock(CoreInterface::class)`). + +### 9. `tests/Integration/Services/Catalog/UserfieldDocument/Service/UserfieldDocumentTest.php` + +**Resolved during implementation:** app-mode credentials (`Factory::getServiceBuilder(true)` / +`Factory::getCore(true)`) work correctly against the test portal (token auto-refreshes). The correct +`entityId` for warehouse accounting document userfields is `CAT_STORE_DOCUMENT_` (e.g. +`CAT_STORE_DOCUMENT_A`), and `fieldName` must be prefixed `UF__`. Both were verified live via +`userfieldconfig.add` / `catalog.userfield.document.update` / `.list` round-trips before writing the +tests. This is implemented in the shared fixture +`tests/Builders/Services/Catalog/UserfieldDocument/CatalogDocumentUserfieldFixture.php` +(`getOrCreateFieldCode()`), used by all three integration test files in this scope — it discovers an +existing userfield for `CAT_STORE_DOCUMENT_A` via `userfieldconfig.list`, or creates one via +`userfieldconfig.add` if none exists yet (left in place for reuse across test runs, not deleted in +tearDown). + +Test plan: +- `setUp()`: `Factory::getServiceBuilder(true)->getCatalogScope()->userfieldDocument()`, plus + `document()` service to create a real document to attach userfield values to; `userfieldCode` is + resolved via `CatalogDocumentUserfieldFixture::getOrCreateFieldCode(Factory::getCore(true))`. +- Test `update()` sets the discovered `fieldN` value on a created document and asserts the returned + `UserfieldDocumentItemResult` exposes it via magic getter. +- Test `list()` with `select`/`filter` containing `documentType` returns the document with the + expected `fieldN` value. + +### 10. `tests/Integration/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResultTest.php` + +Same app-mode fixture as file 9 above (`CatalogDocumentUserfieldFixture::getOrCreateFieldCode()`). + +Per the mandatory annotation-test rule in `docs/testing.md`. Two test methods: +- `testAllFieldsAreAnnotated`: fetch a raw item from `list()`, **filter the raw keys down to + `['documentId', 'documentType']`** (normalization required — dynamic `fieldN` keys are portal-specific + and cannot be part of the static PHPDoc contract), then call + `assertBitrix24AllResultItemFieldsAnnotated()`. +- `testAllFieldsHasValidTypeCastingInMagicGetters`: call + `assertBitrix24ResultItemFieldsTypeCastMatchAnnotations()` on a real `UserfieldDocumentItemResult`. +- A third, non-template test method `testDynamicUserfieldValueIsAccessible` (not part of the mandatory + pair, but required to prove the design decision works): asserts that a dynamic `fieldN` set via + `update()` is readable as `$item->fieldN` even though it's unannotated. + +### 11. `tests/Integration/Services/Catalog/UserfieldDocument/Service/BatchTest.php` + +Batch update test mirroring `tests/Integration/Services/Catalog/Document/Service/BatchTest.php` +(create 2+ documents, batch-update their userfield values, assert results). + +--- + +## Files to Modify + +### 1. `src/Services/Catalog/CatalogServiceBuilder.php` + +Add, after `documentElement()` (~line 292): + +```php + public function userfieldDocument(): Catalog\UserfieldDocument\Service\UserfieldDocument + { + if (!isset($this->serviceCache[__METHOD__])) { + $this->serviceCache[__METHOD__] = new Catalog\UserfieldDocument\Service\UserfieldDocument( + new Catalog\UserfieldDocument\Service\Batch( + new Catalog\UserfieldDocument\Batch($this->core, $this->log), + $this->log + ), + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } +``` + +### 2. `phpunit.xml.dist` + +Confirmed convention from `Catalog\Document` (lines 575-580 of current file): one suite covering the +whole `Service/` directory (includes both the plain service test and `BatchTest.php`), plus one suite +for the annotations test. Add, after the `integration_tests_catalog_document_element_annotations` block +(~line 586): + +```xml + + ./tests/Integration/Services/Catalog/UserfieldDocument/Service/ + + + ./tests/Integration/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResultTest.php + +``` + +### 3. `Makefile` + +Add, mirroring the exact `test-integration-catalog-document` / `-annotations` target pair (~line 932): + +```makefile +.PHONY: test-integration-catalog-userfield-document +test-integration-catalog-userfield-document: + docker compose run --rm php-cli $(PHPUNIT) --testsuite integration_tests_catalog_userfield_document +.PHONY: test-integration-catalog-userfield-document-annotations +test-integration-catalog-userfield-document-annotations: + docker compose run --rm php-cli $(PHPUNIT) --testsuite integration_tests_catalog_userfield_document_annotations +``` + +### 4. `.php-cs-fixer.php`, `phpstan.neon.dist`, `rector.php` + +Confirmed — no change needed. All three already cover the whole `Catalog` scope wholesale: +- `.php-cs-fixer.php:15` → `->in(__DIR__ . '/src/Services/Catalog/')` +- `phpstan.neon.dist:10` → `tests/Integration/Services/Catalog` (and `src/` is covered elsewhere at the + top-level `src` scan) +- `rector.php:23-24` → `src/Services/Catalog` and `tests/Integration/Services/Catalog` + +`UserfieldDocument` is a subdirectory of `Catalog`, so it's picked up automatically. + +### 5. `CHANGELOG.md` + +Add under the latest `## X.Y.Z Unreleased` version, at the top of the relevant section: + +```markdown +- Added service `Services\Catalog\UserfieldDocument` with support methods, + see [catalog.userfield.document.* methods](https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/index.html): + - `list` gets a paginated list of userfield values for warehouse accounting documents, with batch calls support for update + - `update` updates userfield values of a warehouse accounting document, with batch calls support +``` + +(Exact wording/issue link finalized during implementation once the actual CHANGELOG top section is +read.) + +--- + +## Deptrac compliance + +`Services\Catalog\UserfieldDocument\*` only imports from `Core` (via `AbstractService`, +`AbstractAnnotatedItem`, `AbstractResult`, `Core\Batch`, exceptions) and `Services\AbstractService` / +`Services\AbstractServiceBuilder` — same dependency shape as the sibling `Document` / +`DocumentElement` scopes, which already pass deptrac. No new violations expected; no `skip_violations` +entry needed. + +--- + +## Verification + +```bash +make lint-cs-fixer +make lint-rector +make lint-phpstan +make lint-deptrac +make test-unit +make test-integration-catalog-userfield-document +``` diff --git a/CHANGELOG.md b/CHANGELOG.md index 704a44d8..df2a8c04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,16 +41,23 @@ - `delete` deletes a price rounding rule, with batch calls support - `get` gets information about a price rounding rule by its identifier - `getFields` returns the description of price rounding rule fields - -## 3.5.0 - -### Added - +- Added service `Services\Catalog\UserfieldDocument` with support methods, + see [catalog.userfield.document.* methods](https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/index.html) ([#589](https://github.com/bitrix24/b24phpsdk/issues/589)): + - `list` gets a paginated list of userfield values for warehouse accounting documents + - `update` updates userfield values of a warehouse accounting document, with batch calls support - Added service `Services\Catalog\StoreProduct` with support methods, see [catalog.storeproduct.* methods](https://apidocs.bitrix24.com/api-reference/catalog/store-product/index.html) ([#584](https://github.com/bitrix24/b24phpsdk/issues/584)): - `get` returns product stock information by record identifier - `list` returns a list of product stock records by filter - `getFields` returns the description of product stock fields +## 3.5.0 + +### Added + +- Added service `Services\Catalog\UserfieldDocument` with support methods, + see [catalog.userfield.document.* methods](https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/index.html) ([#589](https://github.com/bitrix24/b24phpsdk/issues/589)): + - `list` gets a paginated list of userfield values for warehouse accounting documents + - `update` updates userfield values of a warehouse accounting document, with batch calls support - Added service `Services\Catalog\Document` with support methods, see [catalog.document.* methods](https://apidocs.bitrix24.com/api-reference/catalog/document/index.html) ([#559](https://github.com/bitrix24/b24phpsdk/issues/559)): - `add` creates a new warehouse accounting document, with batch calls support diff --git a/Makefile b/Makefile index f63eafbc..543edcca 100644 --- a/Makefile +++ b/Makefile @@ -944,6 +944,12 @@ test-integration-catalog-document-element: test-integration-catalog-document-element-annotations: docker compose run --rm php-cli $(PHPUNIT) --testsuite integration_tests_catalog_document_element_annotations +.PHONY: test-integration-catalog-userfield-document +test-integration-catalog-userfield-document: + docker compose run --rm php-cli $(PHPUNIT) --testsuite integration_tests_catalog_userfield_document +.PHONY: test-integration-catalog-userfield-document-annotations +test-integration-catalog-userfield-document-annotations: + docker compose run --rm php-cli $(PHPUNIT) --testsuite integration_tests_catalog_userfield_document_annotations .PHONY: test-integration-catalog-store-product test-integration-catalog-store-product: docker compose run --rm php-cli $(PHPUNIT) --testsuite integration_tests_catalog_store_product diff --git a/docs/testing.md b/docs/testing.md index c50416e7..bf33e658 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -302,6 +302,8 @@ skip_violations: | `make test-integration-catalog-document-annotations` | Warehouse accounting document result annotations | | `make test-integration-catalog-document-element` | Warehouse accounting document line items | | `make test-integration-catalog-document-element-annotations` | Warehouse accounting document line item result annotations | +| `make test-integration-catalog-userfield-document` | Warehouse accounting document userfield values | +| `make test-integration-catalog-userfield-document-annotations` | Warehouse accounting document userfield result annotations | | `make test-integration-catalog-store-product` | Product stock by warehouse (`catalog.storeproduct.*`) | | `make test-integration-catalog-section` | Trade-catalog sections | | `make test-integration-catalog-section-annotations` | Trade-catalog section result annotations | diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a10bf28c..e701007a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -584,6 +584,11 @@ ./tests/Integration/Services/Catalog/DocumentElement/Result/DocumentElementItemResultTest.php + + ./tests/Integration/Services/Catalog/UserfieldDocument/Service/ + + + ./tests/Integration/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResultTest.php ./tests/Integration/Services/Catalog/StoreProduct/ diff --git a/src/Services/Booking/BookingServiceBuilder.php b/src/Services/Booking/BookingServiceBuilder.php index 75b50665..9013e61f 100644 --- a/src/Services/Booking/BookingServiceBuilder.php +++ b/src/Services/Booking/BookingServiceBuilder.php @@ -35,9 +35,7 @@ class BookingServiceBuilder extends AbstractServiceBuilder */ public function booking(): Booking { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Booking($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Booking($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -47,9 +45,7 @@ public function booking(): Booking */ public function bookingClient(): BookingClient { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new BookingClient($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new BookingClient($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -59,9 +55,7 @@ public function bookingClient(): BookingClient */ public function bookingExternalData(): BookingExternalData { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new BookingExternalData($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new BookingExternalData($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -71,9 +65,7 @@ public function bookingExternalData(): BookingExternalData */ public function resource(): Resource { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Resource($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Resource($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -83,9 +75,7 @@ public function resource(): Resource */ public function resourceSlots(): ResourceSlots { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ResourceSlots($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new ResourceSlots($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -95,9 +85,7 @@ public function resourceSlots(): ResourceSlots */ public function resourceType(): ResourceType { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ResourceType($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new ResourceType($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -107,9 +95,7 @@ public function resourceType(): ResourceType */ public function clientType(): ClientType { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ClientType($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new ClientType($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -119,9 +105,7 @@ public function clientType(): ClientType */ public function waitlist(): Waitlist { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Waitlist($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Waitlist($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -131,9 +115,7 @@ public function waitlist(): Waitlist */ public function waitlistClient(): WaitlistClient { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new WaitlistClient($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new WaitlistClient($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -143,9 +125,7 @@ public function waitlistClient(): WaitlistClient */ public function waitlistExternalData(): WaitlistExternalData { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new WaitlistExternalData($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new WaitlistExternalData($this->core, $this->log); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Calendar/CalendarServiceBuilder.php b/src/Services/Calendar/CalendarServiceBuilder.php index d87e6d62..16087f8d 100644 --- a/src/Services/Calendar/CalendarServiceBuilder.php +++ b/src/Services/Calendar/CalendarServiceBuilder.php @@ -30,12 +30,10 @@ class CalendarServiceBuilder extends AbstractServiceBuilder */ public function calendar(): Service\Calendar { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Service\Calendar( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Service\Calendar( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -65,12 +63,10 @@ public function event(): Event\Service\Event */ public function resource(): Resource\Service\Resource { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Resource\Service\Resource( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Resource\Service\Resource( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Catalog/CatalogServiceBuilder.php b/src/Services/Catalog/CatalogServiceBuilder.php index 995bb66b..d2cc79f0 100644 --- a/src/Services/Catalog/CatalogServiceBuilder.php +++ b/src/Services/Catalog/CatalogServiceBuilder.php @@ -23,12 +23,10 @@ class CatalogServiceBuilder extends AbstractServiceBuilder { public function catalog(): Catalog\Catalog\Service\Catalog { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\Catalog\Service\Catalog( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Catalog\Catalog\Service\Catalog( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -49,76 +47,64 @@ public function product(): Catalog\Product\Service\Product public function productService(): Catalog\Product\ProductService\Service\ProductService { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\Product\ProductService\Service\ProductService( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Catalog\Product\ProductService\Service\ProductService( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function productSku(): Catalog\Product\Sku\Service\Sku { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\Product\Sku\Service\Sku( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Catalog\Product\Sku\Service\Sku( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function productOffer(): Catalog\Product\Offer\Service\Offer { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\Product\Offer\Service\Offer( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Catalog\Product\Offer\Service\Offer( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function catalogEnum(): Catalog\Enum\Service\CatalogEnum { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\Enum\Service\CatalogEnum( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Catalog\Enum\Service\CatalogEnum( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function price(): Catalog\Price\Service\Price { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\Price\Service\Price( - new Catalog\Price\Service\Batch( - new Catalog\Price\Batch($this->core, $this->log), - $this->log - ), - $this->core, + $this->serviceCache[__METHOD__] ??= new Catalog\Price\Service\Price( + new Catalog\Price\Service\Batch( + new Catalog\Price\Batch($this->core, $this->log), $this->log - ); - } + ), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function extra(): Catalog\Extra\Service\Extra { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\Extra\Service\Extra( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Catalog\Extra\Service\Extra( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -139,28 +125,24 @@ public function productImage(): Catalog\ProductImage\Service\ProductImage public function measure(): Catalog\Measure\Service\Measure { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\Measure\Service\Measure( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Catalog\Measure\Service\Measure( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function priceType(): Catalog\PriceType\Service\PriceType { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\PriceType\Service\PriceType( - new Catalog\PriceType\Service\Batch( - new Catalog\PriceType\Batch($this->core, $this->log), - $this->log - ), - $this->core, + $this->serviceCache[__METHOD__] ??= new Catalog\PriceType\Service\PriceType( + new Catalog\PriceType\Service\Batch( + new Catalog\PriceType\Batch($this->core, $this->log), $this->log - ); - } + ), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -181,16 +163,14 @@ public function productPropertyEnum(): Catalog\ProductPropertyEnum\Service\Produ public function priceTypeLang(): Catalog\PriceTypeLang\Service\PriceTypeLang { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\PriceTypeLang\Service\PriceTypeLang( - new Catalog\PriceTypeLang\Service\Batch( - new Catalog\PriceTypeLang\Batch($this->core, $this->log), - $this->log - ), - $this->core, + $this->serviceCache[__METHOD__] ??= new Catalog\PriceTypeLang\Service\PriceTypeLang( + new Catalog\PriceTypeLang\Service\Batch( + new Catalog\PriceTypeLang\Batch($this->core, $this->log), $this->log - ); - } + ), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -233,60 +213,66 @@ public function productProperty(): Catalog\ProductProperty\Service\ProductProper public function priceTypeGroup(): Catalog\PriceTypeGroup\Service\PriceTypeGroup { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\PriceTypeGroup\Service\PriceTypeGroup( - new Catalog\PriceTypeGroup\Service\Batch( - new Catalog\PriceTypeGroup\Batch($this->core, $this->log), - $this->log - ), - $this->core, + $this->serviceCache[__METHOD__] ??= new Catalog\PriceTypeGroup\Service\PriceTypeGroup( + new Catalog\PriceTypeGroup\Service\Batch( + new Catalog\PriceTypeGroup\Batch($this->core, $this->log), $this->log - ); - } + ), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function productPropertySection(): Catalog\ProductPropertySection\Service\ProductPropertySection { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\ProductPropertySection\Service\ProductPropertySection( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Catalog\ProductPropertySection\Service\ProductPropertySection( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function document(): Catalog\Document\Service\Document { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\Document\Service\Document( - new Catalog\Document\Service\Batch( - new Catalog\Document\Batch($this->core, $this->log), - $this->log - ), - $this->core, + $this->serviceCache[__METHOD__] ??= new Catalog\Document\Service\Document( + new Catalog\Document\Service\Batch( + new Catalog\Document\Batch($this->core, $this->log), $this->log - ); - } + ), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function documentElement(): Catalog\DocumentElement\Service\DocumentElement { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Catalog\DocumentElement\Service\DocumentElement( - new Catalog\DocumentElement\Service\Batch( - new Catalog\DocumentElement\Batch($this->core, $this->log), - $this->log - ), - $this->core, + $this->serviceCache[__METHOD__] ??= new Catalog\DocumentElement\Service\DocumentElement( + new Catalog\DocumentElement\Service\Batch( + new Catalog\DocumentElement\Batch($this->core, $this->log), $this->log - ); - } + ), + $this->core, + $this->log + ); + + return $this->serviceCache[__METHOD__]; + } + + public function userfieldDocument(): Catalog\UserfieldDocument\Service\UserfieldDocument + { + $this->serviceCache[__METHOD__] ??= new Catalog\UserfieldDocument\Service\UserfieldDocument( + new Catalog\UserfieldDocument\Service\Batch( + new Catalog\UserfieldDocument\Batch($this->core, $this->log), + $this->log + ), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Catalog/UserfieldDocument/Batch.php b/src/Services/Catalog/UserfieldDocument/Batch.php new file mode 100644 index 00000000..e1754c4f --- /dev/null +++ b/src/Services/Catalog/UserfieldDocument/Batch.php @@ -0,0 +1,105 @@ + + * + * 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\Catalog\UserfieldDocument; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Response\DTO\ResponseData; +use Generator; + +/** + * Class Batch + * + * Overrides base Batch to handle parameter naming differences in catalog.userfield.document.* REST methods: + * - update uses 'documentId' instead of the base class's hardcoded 'id' command argument key + * + * @see https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-update.html + */ +class Batch extends \Bitrix24\SDK\Core\Batch +{ + #[\Override] + protected function determineKeyId(string $apiMethod, ?array $additionalParameters): string + { + return 'documentId'; + } + + /** + * Update entity items with batch call using 'documentId' instead of the base class's 'id' + * + * @param array $entityItems keyed by document id, each value must contain a 'fields' key + * + * @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 $documentId => $entityItem) { + if (!is_int($documentId)) { + throw new InvalidArgumentException( + sprintf( + 'invalid type «%s» of document id «%s», document id must be integer type', + gettype($documentId), + $documentId + ) + ); + } + + if (!array_key_exists('fields', $entityItem)) { + throw new InvalidArgumentException( + sprintf('array key «fields» not found in entity item with id %s', $documentId) + ); + } + + $this->registerCommand($apiMethod, ['documentId' => $documentId, 'fields' => $entityItem['fields']]); + } + + foreach ($this->getTraversable(true) as $cnt => $updatedItemResult) { + yield $cnt => $updatedItemResult; + } + } catch (InvalidArgumentException $exception) { + $errorMessage = sprintf('batch update document userfield items: %s', $exception->getMessage()); + $this->logger->error( + $errorMessage, + [ + 'trace' => $exception->getTrace(), + ] + ); + throw $exception; + } catch (\Throwable $exception) { + $errorMessage = sprintf('batch update document userfield 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/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResult.php b/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResult.php new file mode 100644 index 00000000..b4c3eaea --- /dev/null +++ b/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResult.php @@ -0,0 +1,27 @@ + + * + * 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\Catalog\UserfieldDocument\Result; + +use Bitrix24\SDK\Core\Result\AbstractAnnotatedItem; + +/** + * Dynamic userfield values (fieldN, where N is the portal-specific userfield ID) are also + * accessible via the inherited magic __get(), but cannot be statically annotated here. + * + * @property-read int $documentId + * @property-read string $documentType + */ +class UserfieldDocumentItemResult extends AbstractAnnotatedItem +{ +} diff --git a/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentResult.php b/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentResult.php new file mode 100644 index 00000000..0fd73123 --- /dev/null +++ b/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentResult.php @@ -0,0 +1,28 @@ + + * + * 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\Catalog\UserfieldDocument\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class UserfieldDocumentResult extends AbstractResult +{ + /** + * @throws BaseException + */ + public function document(): UserfieldDocumentItemResult + { + return new UserfieldDocumentItemResult($this->getCoreResponse()->getResponseData()->getResult()['document']); + } +} diff --git a/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentUpdatedBatchResult.php b/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentUpdatedBatchResult.php new file mode 100644 index 00000000..1d479e34 --- /dev/null +++ b/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentUpdatedBatchResult.php @@ -0,0 +1,33 @@ + + * + * 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\Catalog\UserfieldDocument\Result; + +use Bitrix24\SDK\Core\Response\DTO\ResponseData; + +class UserfieldDocumentUpdatedBatchResult +{ + public function __construct(private readonly ResponseData $responseData) + { + } + + public function getResponseData(): ResponseData + { + return $this->responseData; + } + + public function document(): UserfieldDocumentItemResult + { + return new UserfieldDocumentItemResult($this->responseData->getResult()['document']); + } +} diff --git a/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentsResult.php b/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentsResult.php new file mode 100644 index 00000000..85ef43b0 --- /dev/null +++ b/src/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentsResult.php @@ -0,0 +1,50 @@ + + * + * 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\Catalog\UserfieldDocument\Result; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\AbstractResult; + +class UserfieldDocumentsResult extends AbstractResult +{ + /** + * @return UserfieldDocumentItemResult[] + * @throws BaseException + */ + public function getDocuments(): array + { + $result = $this->getCoreResponse()->getResponseData()->getResult(); + + return array_map( + static fn (array $item): UserfieldDocumentItemResult => new UserfieldDocumentItemResult($item), + $result['documents'] ?? [] + ); + } + + /** + * @throws BaseException + */ + public function getNext(): ?int + { + return $this->getCoreResponse()->getResponseData()->getPagination()->getNextItem(); + } + + /** + * @throws BaseException + */ + public function getTotal(): ?int + { + return $this->getCoreResponse()->getResponseData()->getPagination()->getTotal(); + } +} diff --git a/src/Services/Catalog/UserfieldDocument/Service/Batch.php b/src/Services/Catalog/UserfieldDocument/Service/Batch.php new file mode 100644 index 00000000..2ee059af --- /dev/null +++ b/src/Services/Catalog/UserfieldDocument/Service/Batch.php @@ -0,0 +1,56 @@ + + * + * 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\Catalog\UserfieldDocument\Service; + +use Bitrix24\SDK\Attributes\ApiBatchMethodMetadata; +use Bitrix24\SDK\Attributes\ApiBatchServiceMetadata; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Services\Catalog\UserfieldDocument; +use Bitrix24\SDK\Services\Catalog\UserfieldDocument\Result\UserfieldDocumentUpdatedBatchResult; +use Generator; +use Psr\Log\LoggerInterface; + +#[ApiBatchServiceMetadata(new Scope(['catalog']))] +class Batch +{ + public function __construct(protected UserfieldDocument\Batch $batch, protected LoggerInterface $log) + { + } + + /** + * Batch update userfield values of warehouse accounting documents + * + * @param array $documents keyed by document id, each value is the «fields» payload + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'catalog.userfield.document.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-update.html', + 'Batch update userfield values of warehouse accounting documents' + )] + public function update(array $documents): Generator + { + $items = []; + foreach ($documents as $id => $document) { + $items[$id] = ['fields' => $document]; + } + + foreach ($this->batch->updateEntityItems('catalog.userfield.document.update', $items) as $key => $item) { + yield $key => new UserfieldDocumentUpdatedBatchResult($item); + } + } +} diff --git a/src/Services/Catalog/UserfieldDocument/Service/UserfieldDocument.php b/src/Services/Catalog/UserfieldDocument/Service/UserfieldDocument.php new file mode 100644 index 00000000..3911d669 --- /dev/null +++ b/src/Services/Catalog/UserfieldDocument/Service/UserfieldDocument.php @@ -0,0 +1,79 @@ + + * + * 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\Catalog\UserfieldDocument\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\Services\AbstractService; +use Bitrix24\SDK\Services\Catalog\UserfieldDocument\Result\UserfieldDocumentResult; +use Bitrix24\SDK\Services\Catalog\UserfieldDocument\Result\UserfieldDocumentsResult; +use Psr\Log\LoggerInterface; + +#[ApiServiceMetadata(new Scope(['catalog']))] +class UserfieldDocument extends AbstractService +{ + public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + /** + * Returns a paginated list of userfield values for warehouse accounting documents. + * The «documentType» key is required in both $select and $filter. + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-list.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.userfield.document.list', + 'https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-list.html', + 'Returns a paginated list of userfield values for warehouse accounting documents' + )] + public function list(array $select, array $filter, array $order = [], int $start = 0): UserfieldDocumentsResult + { + return new UserfieldDocumentsResult( + $this->core->call( + 'catalog.userfield.document.list', + ['select' => $select, 'filter' => $filter, 'order' => $order, 'start' => $start] + ) + ); + } + + /** + * Updates userfield values of a warehouse accounting document. + * $fields must contain «documentType» plus the fieldN values to update. + * + * @link https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-update.html + * + * @throws BaseException + * @throws TransportException + */ + #[ApiEndpointMetadata( + 'catalog.userfield.document.update', + 'https://apidocs.bitrix24.com/api-reference/catalog/userfield-document/catalog-userfield-document-update.html', + 'Updates userfield values of a warehouse accounting document' + )] + public function update(int $documentId, array $fields): UserfieldDocumentResult + { + return new UserfieldDocumentResult( + $this->core->call('catalog.userfield.document.update', ['documentId' => $documentId, 'fields' => $fields]) + ); + } +} diff --git a/src/Services/Disk/DiskServiceBuilder.php b/src/Services/Disk/DiskServiceBuilder.php index a0340cef..c1fff859 100644 --- a/src/Services/Disk/DiskServiceBuilder.php +++ b/src/Services/Disk/DiskServiceBuilder.php @@ -30,12 +30,10 @@ class DiskServiceBuilder extends AbstractServiceBuilder */ public function folder(): Folder\Service\Folder { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Folder\Service\Folder( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Folder\Service\Folder( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -45,12 +43,10 @@ public function folder(): Folder\Service\Folder */ public function file(): File\Service\File { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new File\Service\File( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new File\Service\File( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -60,12 +56,10 @@ public function file(): File\Service\File */ public function storage(): Storage\Service\Storage { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Storage\Service\Storage( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Storage\Service\Storage( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -75,12 +69,10 @@ public function storage(): Storage\Service\Storage */ public function disk(): Service\Disk { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Service\Disk( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Service\Disk( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/IM/IMServiceBuilder.php b/src/Services/IM/IMServiceBuilder.php index c5743c5a..472a9f9c 100644 --- a/src/Services/IM/IMServiceBuilder.php +++ b/src/Services/IM/IMServiceBuilder.php @@ -40,117 +40,91 @@ class IMServiceBuilder extends AbstractServiceBuilder { public function recent(): Recent { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Recent($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Recent($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function search(): Search { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Search($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Search($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function disk(): Disk { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Disk($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Disk($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function notify(): Notify { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Notify($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Notify($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function chat(): Chat { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Chat($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Chat($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function chatUser(): ChatUser { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ChatUser($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new ChatUser($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function message(): Message { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Message($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Message($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function dialog(): Dialog { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Dialog($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Dialog($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function revision(): Revision { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Revision($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Revision($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function counters(): Counters { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Counters($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Counters($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function department(): Department { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Department($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Department($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function userStatus(): UserStatus { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new UserStatus($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new UserStatus($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function user(): User { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new User($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new User($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -162,27 +136,21 @@ public function placementLocationCodes(): PlacementLocationCodes public function placements(): Placements { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Placements(new Placement($this->core, $this->log)); - } + $this->serviceCache[__METHOD__] ??= new Placements(new Placement($this->core, $this->log)); return $this->serviceCache[__METHOD__]; } public function eventV2(): EventV2 { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new EventV2($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new EventV2($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function fileV2(): FileV2 { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new FileV2($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new FileV2($this->core, $this->log); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/IMBot/IMBotServiceBuilder.php b/src/Services/IMBot/IMBotServiceBuilder.php index 76c64661..7b22d42d 100644 --- a/src/Services/IMBot/IMBotServiceBuilder.php +++ b/src/Services/IMBot/IMBotServiceBuilder.php @@ -46,9 +46,7 @@ class IMBotServiceBuilder extends AbstractServiceBuilder */ public function bot(): Bot { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Bot($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Bot($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -59,9 +57,7 @@ public function bot(): Bot */ public function chat(): Chat { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Chat($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Chat($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -71,9 +67,7 @@ public function chat(): Chat */ public function chatUser(): ChatUser { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ChatUser($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new ChatUser($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -83,9 +77,7 @@ public function chatUser(): ChatUser */ public function chatManager(): ChatManager { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ChatManager($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new ChatManager($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -98,13 +90,11 @@ public function chatManager(): ChatManager */ public function chatMessage(): ChatMessage { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ChatMessage( - new ChatMessageBatch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new ChatMessage( + new ChatMessageBatch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -114,9 +104,7 @@ public function chatMessage(): ChatMessage */ public function chatMessageReaction(): ChatMessageReaction { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ChatMessageReaction($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new ChatMessageReaction($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -126,9 +114,7 @@ public function chatMessageReaction(): ChatMessageReaction */ public function chatInputAction(): ChatInputAction { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ChatInputAction($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new ChatInputAction($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -138,9 +124,7 @@ public function chatInputAction(): ChatInputAction */ public function chatTextField(): ChatTextField { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ChatTextField($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new ChatTextField($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -151,9 +135,7 @@ public function chatTextField(): ChatTextField */ public function command(): Command { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Command($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Command($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -163,9 +145,7 @@ public function command(): Command */ public function event(): Event { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Event($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Event($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -175,9 +155,7 @@ public function event(): Event */ public function file(): File { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new File($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new File($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -187,9 +165,7 @@ public function file(): File */ public function revision(): Revision { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Revision($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Revision($this->core, $this->log); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/IMOpenLines/IMOpenLinesServiceBuilder.php b/src/Services/IMOpenLines/IMOpenLinesServiceBuilder.php index 5dac46e2..8d22869f 100644 --- a/src/Services/IMOpenLines/IMOpenLinesServiceBuilder.php +++ b/src/Services/IMOpenLines/IMOpenLinesServiceBuilder.php @@ -30,72 +30,56 @@ class IMOpenLinesServiceBuilder extends AbstractServiceBuilder { public function bot(): Bot { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Bot($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Bot($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function config(): Config { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Config($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Config($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function crmChat(): Chat { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Chat($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Chat($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function message(): Message { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Message($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Message($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function Network(): Network { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Network($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Network($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function connector(): Connector { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Connector($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Connector($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function operator(): Operator { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Operator($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Operator($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function session(): Session { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Session($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Session($this->core, $this->log); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Landing/LandingServiceBuilder.php b/src/Services/Landing/LandingServiceBuilder.php index beda5373..6e4a0d24 100644 --- a/src/Services/Landing/LandingServiceBuilder.php +++ b/src/Services/Landing/LandingServiceBuilder.php @@ -30,12 +30,10 @@ class LandingServiceBuilder extends AbstractServiceBuilder */ public function site(): Site\Service\Site { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Site\Service\Site( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Site\Service\Site( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -45,12 +43,10 @@ public function site(): Site\Service\Site */ public function page(): Page\Service\Page { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Page\Service\Page( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Page\Service\Page( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -60,12 +56,10 @@ public function page(): Page\Service\Page */ public function sysPage(): SysPage\Service\SysPage { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new SysPage\Service\SysPage( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new SysPage\Service\SysPage( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -75,12 +69,10 @@ public function sysPage(): SysPage\Service\SysPage */ public function template(): Template\Service\Template { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Template\Service\Template( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Template\Service\Template( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -90,12 +82,10 @@ public function template(): Template\Service\Template */ public function block(): Block\Service\Block { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Block\Service\Block( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Block\Service\Block( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -105,12 +95,10 @@ public function block(): Block\Service\Block */ public function repo(): Repo\Service\Repo { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Repo\Service\Repo( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Repo\Service\Repo( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -120,12 +108,10 @@ public function repo(): Repo\Service\Repo */ public function demos(): Demos\Service\Demos { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Demos\Service\Demos( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Demos\Service\Demos( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -135,12 +121,10 @@ public function demos(): Demos\Service\Demos */ public function role(): Role\Service\Role { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Role\Service\Role( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Role\Service\Role( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -150,12 +134,10 @@ public function role(): Role\Service\Role */ public function repoWidget(): RepoWidget\Service\RepoWidget { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new RepoWidget\Service\RepoWidget( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new RepoWidget\Service\RepoWidget( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Main/MainServiceBuilder.php b/src/Services/Main/MainServiceBuilder.php index 634eacea..414cfeda 100644 --- a/src/Services/Main/MainServiceBuilder.php +++ b/src/Services/Main/MainServiceBuilder.php @@ -30,66 +30,52 @@ class MainServiceBuilder extends AbstractServiceBuilder { public function main(): Main { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Main($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Main($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function documentation(): Documentation { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Documentation($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Documentation($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function event(): Event { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Event($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Event($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function offlineEvent(): OfflineEvent { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new OfflineEvent($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new OfflineEvent($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function eventLog(): EventLog { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new EventLog($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new EventLog($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function eventLogField(): EventLogField { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new EventLogField($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new EventLogField($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function eventManager(): EventManager { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new EventManager( - new Event($this->core, $this->log), - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new EventManager( + new Event($this->core, $this->log), + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Messageservice/MessageserviceServiceBuilder.php b/src/Services/Messageservice/MessageserviceServiceBuilder.php index 241aa512..1f0818aa 100644 --- a/src/Services/Messageservice/MessageserviceServiceBuilder.php +++ b/src/Services/Messageservice/MessageserviceServiceBuilder.php @@ -24,24 +24,20 @@ class MessageserviceServiceBuilder extends AbstractServiceBuilder { public function sender(): Sender { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Sender( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Sender( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function messageStatus(): MessageStatus { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new MessageStatus( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new MessageStatus( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Paysystem/PaysystemServiceBuilder.php b/src/Services/Paysystem/PaysystemServiceBuilder.php index 442f1ec1..fac4ef76 100644 --- a/src/Services/Paysystem/PaysystemServiceBuilder.php +++ b/src/Services/Paysystem/PaysystemServiceBuilder.php @@ -31,9 +31,7 @@ class PaysystemServiceBuilder extends AbstractServiceBuilder */ public function handler(): Handler { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Handler($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Handler($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -43,13 +41,11 @@ public function handler(): Handler */ public function paysystem(): Service\Paysystem { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Service\Paysystem( - new Service\Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Service\Paysystem( + new Service\Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -59,9 +55,7 @@ public function paysystem(): Service\Paysystem */ public function settings(): Settings\Service\Settings { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Settings\Service\Settings($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Settings\Service\Settings($this->core, $this->log); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Placement/PlacementServiceBuilder.php b/src/Services/Placement/PlacementServiceBuilder.php index b539bc59..6a632923 100644 --- a/src/Services/Placement/PlacementServiceBuilder.php +++ b/src/Services/Placement/PlacementServiceBuilder.php @@ -23,18 +23,14 @@ class PlacementServiceBuilder extends AbstractServiceBuilder { public function placement(): Placement { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Placement($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Placement($this->core, $this->log); return $this->serviceCache[__METHOD__]; } public function userfieldtype(): UserFieldType { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new UserFieldType($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new UserFieldType($this->core, $this->log); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Sale/SaleServiceBuilder.php b/src/Services/Sale/SaleServiceBuilder.php index a2d296bb..46649269 100644 --- a/src/Services/Sale/SaleServiceBuilder.php +++ b/src/Services/Sale/SaleServiceBuilder.php @@ -53,12 +53,10 @@ class SaleServiceBuilder extends AbstractServiceBuilder */ public function tradePlatform(): TradePlatform { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new TradePlatform( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new TradePlatform( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -68,24 +66,20 @@ public function tradePlatform(): TradePlatform */ public function property(): Property { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Property( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Property( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function propertyGroup(): PropertyGroup\Service\PropertyGroup { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new PropertyGroup\Service\PropertyGroup( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new PropertyGroup\Service\PropertyGroup( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -112,36 +106,30 @@ public function order(): Order\Service\Order public function status(): Status { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Status( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Status( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function personTypeStatus(): PersonTypeStatus { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new PersonTypeStatus( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new PersonTypeStatus( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function personType(): PersonType\Service\PersonType { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new PersonType\Service\PersonType( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new PersonType\Service\PersonType( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -151,12 +139,10 @@ public function personType(): PersonType\Service\PersonType */ public function payment(): Payment\Service\Payment { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Payment\Service\Payment( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Payment\Service\Payment( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -166,12 +152,10 @@ public function payment(): Payment\Service\Payment */ public function paymentItemBasket(): PaymentItemBasket\Service\PaymentItemBasket { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new PaymentItemBasket\Service\PaymentItemBasket( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new PaymentItemBasket\Service\PaymentItemBasket( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -181,36 +165,30 @@ public function paymentItemBasket(): PaymentItemBasket\Service\PaymentItemBasket */ public function paymentItemShipment(): PaymentItemShipment\Service\PaymentItemShipment { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new PaymentItemShipment\Service\PaymentItemShipment( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new PaymentItemShipment\Service\PaymentItemShipment( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function propertyVariant(): PropertyVariant { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new PropertyVariant( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new PropertyVariant( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function statusLang(): StatusLang { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new StatusLang( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new StatusLang( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -220,12 +198,10 @@ public function statusLang(): StatusLang */ public function shipment(): Shipment\Service\Shipment { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Shipment\Service\Shipment( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Shipment\Service\Shipment( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -235,12 +211,10 @@ public function shipment(): Shipment\Service\Shipment */ public function shipmentProperty(): ShipmentProperty\Service\ShipmentProperty { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ShipmentProperty\Service\ShipmentProperty( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new ShipmentProperty\Service\ShipmentProperty( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -270,12 +244,10 @@ public function basketItem(): BasketItem\Service\BasketItem */ public function shipmentPropertyValue(): ShipmentPropertyValue { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ShipmentPropertyValue( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new ShipmentPropertyValue( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -285,12 +257,10 @@ public function shipmentPropertyValue(): ShipmentPropertyValue */ public function shipmentItem(): ShipmentItem { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ShipmentItem( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new ShipmentItem( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -300,12 +270,10 @@ public function shipmentItem(): ShipmentItem */ public function basketProperty(): BasketProperty { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new BasketProperty( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new BasketProperty( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -315,12 +283,10 @@ public function basketProperty(): BasketProperty */ public function cashboxHandler(): CashboxHandler { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new CashboxHandler( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new CashboxHandler( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -330,12 +296,10 @@ public function cashboxHandler(): CashboxHandler */ public function deliveryHandler(): DeliveryHandler { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new DeliveryHandler( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new DeliveryHandler( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -345,12 +309,10 @@ public function deliveryHandler(): DeliveryHandler */ public function cashbox(): Cashbox { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Cashbox( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Cashbox( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -360,12 +322,10 @@ public function cashbox(): Cashbox */ public function delivery(): Delivery { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Delivery( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Delivery( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -375,12 +335,10 @@ public function delivery(): Delivery */ public function deliveryRequest(): DeliveryRequest { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new DeliveryRequest( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new DeliveryRequest( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -390,12 +348,10 @@ public function deliveryRequest(): DeliveryRequest */ public function deliveryExtraService(): DeliveryExtraService { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new DeliveryExtraService( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new DeliveryExtraService( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } @@ -405,12 +361,10 @@ public function deliveryExtraService(): DeliveryExtraService */ public function propertyRelation(): PropertyRelation\Service\PropertyRelation { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new PropertyRelation\Service\PropertyRelation( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new PropertyRelation\Service\PropertyRelation( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Sign/SignServiceBuilder.php b/src/Services/Sign/SignServiceBuilder.php index 556d73f1..9042e32f 100644 --- a/src/Services/Sign/SignServiceBuilder.php +++ b/src/Services/Sign/SignServiceBuilder.php @@ -29,9 +29,7 @@ class SignServiceBuilder extends AbstractServiceBuilder */ public function document(): Document { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Document($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new Document($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -41,9 +39,7 @@ public function document(): Document */ public function companyProvider(): CompanyProvider { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new CompanyProvider($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new CompanyProvider($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -53,9 +49,7 @@ public function companyProvider(): CompanyProvider */ public function personalTail(): PersonalTail { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new PersonalTail($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new PersonalTail($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -65,9 +59,7 @@ public function personalTail(): PersonalTail */ public function mySafeTail(): MySafeTail { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new MySafeTail($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new MySafeTail($this->core, $this->log); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/SonetGroup/SonetGroupServiceBuilder.php b/src/Services/SonetGroup/SonetGroupServiceBuilder.php index 5f91f1d6..37cf8856 100644 --- a/src/Services/SonetGroup/SonetGroupServiceBuilder.php +++ b/src/Services/SonetGroup/SonetGroupServiceBuilder.php @@ -30,12 +30,10 @@ class SonetGroupServiceBuilder extends AbstractServiceBuilder */ public function sonetGroup(): Service\SonetGroup { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Service\SonetGroup( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Service\SonetGroup( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Task/TaskServiceBuilder.php b/src/Services/Task/TaskServiceBuilder.php index e6d25207..f964e63d 100644 --- a/src/Services/Task/TaskServiceBuilder.php +++ b/src/Services/Task/TaskServiceBuilder.php @@ -40,181 +40,151 @@ public function task(): Service\Task public function taskAccess(): Service\TaskAccess { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Service\TaskAccess( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Service\TaskAccess( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function taskChat(): Service\TaskChat { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Service\TaskChat( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Service\TaskChat( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function taskChatMessageField(): ChatMessageField\Service\ChatMessageField { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new ChatMessageField\Service\ChatMessageField( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new ChatMessageField\Service\ChatMessageField( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function taskFileField(): FileField\Service\FileField { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new FileField\Service\FileField( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new FileField\Service\FileField( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function taskAccessField(): AccessField\Service\AccessField { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new AccessField\Service\AccessField( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new AccessField\Service\AccessField( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function taskField(): TaskField\Service\TaskField { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new TaskField\Service\TaskField( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new TaskField\Service\TaskField( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function taskFile(): Service\TaskFile { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Service\TaskFile( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Service\TaskFile( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function userfield(): Userfield\Service\Userfield { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Userfield\Service\Userfield( - new UserfieldConstraints(), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Userfield\Service\Userfield( + new UserfieldConstraints(), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function checklistitem(): Checklistitem\Service\Checklistitem { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Checklistitem\Service\Checklistitem( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Checklistitem\Service\Checklistitem( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function commentitem(): Commentitem\Service\Commentitem { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Commentitem\Service\Commentitem( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Commentitem\Service\Commentitem( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function result(): TaskResult\Service\Result { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new TaskResult\Service\Result( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new TaskResult\Service\Result( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function elapseditem(): Elapseditem\Service\Elapseditem { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Elapseditem\Service\Elapseditem( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Elapseditem\Service\Elapseditem( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function stage(): Stage\Service\Stage { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Stage\Service\Stage( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Stage\Service\Stage( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function planner(): Planner\Service\Planner { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Planner\Service\Planner( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Planner\Service\Planner( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function flow(): Flow\Service\Flow { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Flow\Service\Flow( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Flow\Service\Flow( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Telephony/TelephonyServiceBuilder.php b/src/Services/Telephony/TelephonyServiceBuilder.php index 99ea20b3..a0293615 100644 --- a/src/Services/Telephony/TelephonyServiceBuilder.php +++ b/src/Services/Telephony/TelephonyServiceBuilder.php @@ -25,58 +25,50 @@ class TelephonyServiceBuilder extends AbstractServiceBuilder { public function externalCall(): Telephony\ExternalCall\Service\ExternalCall { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\ExternalCall\Service\ExternalCall( - new Telephony\ExternalCall\Service\Batch($this->batch, $this->log), - new Base64Encoder( - new Filesystem(), - new \Symfony\Component\Mime\Encoder\Base64Encoder(), - $this->log, - ), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\ExternalCall\Service\ExternalCall( + new Telephony\ExternalCall\Service\Batch($this->batch, $this->log), + new Base64Encoder( + new Filesystem(), + new \Symfony\Component\Mime\Encoder\Base64Encoder(), + $this->log, + ), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function call(): Telephony\Call\Service\Call { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\Call\Service\Call( - new Telephony\Call\Service\Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\Call\Service\Call( + new Telephony\Call\Service\Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function externalLine(): Telephony\ExternalLine\Service\ExternalLine { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\ExternalLine\Service\ExternalLine( - new Telephony\ExternalLine\Service\Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\ExternalLine\Service\ExternalLine( + new Telephony\ExternalLine\Service\Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function getVoximplantServiceBuilder(): Telephony\Voximplant\VoximplantServiceBuilder { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\Voximplant\VoximplantServiceBuilder( - $this->core, - $this->batch, - $this->bulkItemsReader, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\Voximplant\VoximplantServiceBuilder( + $this->core, + $this->batch, + $this->bulkItemsReader, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Telephony/Voximplant/VoximplantServiceBuilder.php b/src/Services/Telephony/Voximplant/VoximplantServiceBuilder.php index b2efe9b9..3c00ab61 100644 --- a/src/Services/Telephony/Voximplant/VoximplantServiceBuilder.php +++ b/src/Services/Telephony/Voximplant/VoximplantServiceBuilder.php @@ -25,78 +25,66 @@ class VoximplantServiceBuilder extends AbstractServiceBuilder { public function sip(): Telephony\Voximplant\Sip\Service\Sip { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\Voximplant\Sip\Service\Sip( - new Telephony\Voximplant\Sip\Service\Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\Voximplant\Sip\Service\Sip( + new Telephony\Voximplant\Sip\Service\Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function user(): Telephony\Voximplant\User\Service\User { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\Voximplant\User\Service\User( - new Telephony\Voximplant\User\Service\Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\Voximplant\User\Service\User( + new Telephony\Voximplant\User\Service\Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function infoCall(): Telephony\Voximplant\InfoCall\Service\InfoCall { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\Voximplant\InfoCall\Service\InfoCall( - new Telephony\Voximplant\InfoCall\Service\Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\Voximplant\InfoCall\Service\InfoCall( + new Telephony\Voximplant\InfoCall\Service\Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function ttsVoices(): Telephony\Voximplant\TTS\Voices\Service\Voices { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\Voximplant\TTS\Voices\Service\Voices( - new Telephony\Voximplant\TTS\Voices\Service\Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\Voximplant\TTS\Voices\Service\Voices( + new Telephony\Voximplant\TTS\Voices\Service\Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function line(): Telephony\Voximplant\Line\Service\Line { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\Voximplant\Line\Service\Line( - new Telephony\Voximplant\Line\Service\Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\Voximplant\Line\Service\Line( + new Telephony\Voximplant\Line\Service\Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function url(): Telephony\Voximplant\Url\Service\Url { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Telephony\Voximplant\Url\Service\Url( - new Telephony\Voximplant\Url\Service\Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Telephony\Voximplant\Url\Service\Url( + new Telephony\Voximplant\Url\Service\Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/Timeman/TimemanServiceBuilder.php b/src/Services/Timeman/TimemanServiceBuilder.php index e3e0ae5a..b1d1e69e 100644 --- a/src/Services/Timeman/TimemanServiceBuilder.php +++ b/src/Services/Timeman/TimemanServiceBuilder.php @@ -25,36 +25,30 @@ class TimemanServiceBuilder extends AbstractServiceBuilder { public function timeman(): Timeman { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Timeman( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Timeman( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function record(): Record { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new Record( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new Record( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } public function recordField(): RecordField { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new RecordField( - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new RecordField( + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/User/UserServiceBuilder.php b/src/Services/User/UserServiceBuilder.php index 92f32b85..28b53052 100644 --- a/src/Services/User/UserServiceBuilder.php +++ b/src/Services/User/UserServiceBuilder.php @@ -24,13 +24,11 @@ class UserServiceBuilder extends AbstractServiceBuilder { public function user(): User { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new User( - new Batch($this->batch, $this->log), - $this->core, - $this->log - ); - } + $this->serviceCache[__METHOD__] ??= new User( + new Batch($this->batch, $this->log), + $this->core, + $this->log + ); return $this->serviceCache[__METHOD__]; } diff --git a/src/Services/UserConsent/UserConsentServiceBuilder.php b/src/Services/UserConsent/UserConsentServiceBuilder.php index 54627b70..715138be 100644 --- a/src/Services/UserConsent/UserConsentServiceBuilder.php +++ b/src/Services/UserConsent/UserConsentServiceBuilder.php @@ -26,9 +26,7 @@ class UserConsentServiceBuilder extends AbstractServiceBuilder */ public function UserConsentAgreement(): UserConsentAgreement { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new UserConsentAgreement($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new UserConsentAgreement($this->core, $this->log); return $this->serviceCache[__METHOD__]; } @@ -38,9 +36,7 @@ public function UserConsentAgreement(): UserConsentAgreement */ public function UserConsent(): UserConsent { - if (!isset($this->serviceCache[__METHOD__])) { - $this->serviceCache[__METHOD__] = new UserConsent($this->core, $this->log); - } + $this->serviceCache[__METHOD__] ??= new UserConsent($this->core, $this->log); return $this->serviceCache[__METHOD__]; } diff --git a/tests/Builders/Services/Catalog/UserfieldDocument/CatalogDocumentUserfieldFixture.php b/tests/Builders/Services/Catalog/UserfieldDocument/CatalogDocumentUserfieldFixture.php new file mode 100644 index 00000000..9f0a35c7 --- /dev/null +++ b/tests/Builders/Services/Catalog/UserfieldDocument/CatalogDocumentUserfieldFixture.php @@ -0,0 +1,61 @@ + + * + * 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\Builders\Services\Catalog\UserfieldDocument; + +use Bitrix24\SDK\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; + +/** + * Discovers an existing catalog-module userfield attached to warehouse accounting documents of type + * «A» (goods receipt), or creates one if none exists yet on the test portal. + * + * Warehouse accounting document userfields use `entityId` in the form + * `CAT_STORE_DOCUMENT_` (e.g. `CAT_STORE_DOCUMENT_A`), and `fieldName` must be prefixed + * with `UF__`. + */ +final class CatalogDocumentUserfieldFixture +{ + public const string DOCUMENT_TYPE = 'A'; + + public const string ENTITY_ID = 'CAT_STORE_DOCUMENT_' . self::DOCUMENT_TYPE; + + /** + * @throws BaseException + * @throws TransportException + */ + public static function getOrCreateFieldCode(CoreInterface $core): string + { + $existingFields = $core->call('userfieldconfig.list', [ + 'moduleId' => 'catalog', + 'filter' => ['entityId' => self::ENTITY_ID], + ])->getResponseData()->getResult()['fields'] ?? []; + + if ($existingFields !== []) { + return sprintf('field%s', $existingFields[0]['id']); + } + + $addedField = $core->call('userfieldconfig.add', [ + 'moduleId' => 'catalog', + 'field' => [ + 'entityId' => self::ENTITY_ID, + 'fieldName' => sprintf('UF_%s_TEST_%s', self::ENTITY_ID, time()), + 'userTypeId' => 'string', + 'editFormLabel' => ['en' => 'b24-php-sdk integration test field'], + ], + ])->getResponseData()->getResult()['field']; + + return sprintf('field%s', $addedField['id']); + } +} diff --git a/tests/Integration/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResultTest.php b/tests/Integration/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResultTest.php new file mode 100644 index 00000000..b6d43125 --- /dev/null +++ b/tests/Integration/Services/Catalog/UserfieldDocument/Result/UserfieldDocumentItemResultTest.php @@ -0,0 +1,109 @@ + + * + * 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\Catalog\UserfieldDocument\Result; + +use Bitrix24\SDK\Services\Catalog\Document\Service\Document; +use Bitrix24\SDK\Services\Catalog\UserfieldDocument\Result\UserfieldDocumentItemResult; +use Bitrix24\SDK\Services\Catalog\UserfieldDocument\Service\UserfieldDocument; +use Bitrix24\SDK\Tests\Builders\Services\Catalog\UserfieldDocument\CatalogDocumentUserfieldFixture; +use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions; +use Bitrix24\SDK\Tests\Integration\Factory; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +/** + * Requires application (OAuth) credentials — see tests/ApplicationBridge/. + */ +#[CoversClass(UserfieldDocumentItemResult::class)] +class UserfieldDocumentItemResultTest extends TestCase +{ + use CustomBitrix24Assertions; + + private UserfieldDocument $userfieldDocumentService; + + private Document $documentService; + + private string $userfieldCode; + + private int $documentId; + + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Factory::getServiceBuilder(true); + $this->userfieldDocumentService = $serviceBuilder->getCatalogScope()->userfieldDocument(); + $this->documentService = $serviceBuilder->getCatalogScope()->document(); + $this->userfieldCode = CatalogDocumentUserfieldFixture::getOrCreateFieldCode(Factory::getCore(true)); + + $this->documentId = $this->documentService->add([ + 'docType' => 'A', + 'currency' => 'USD', + 'responsibleId' => 1, + 'title' => sprintf('test userfield document annotations %s', time()), + ])->document()->id; + + $this->userfieldDocumentService->update($this->documentId, [ + 'documentType' => 'A', + $this->userfieldCode => sprintf('annotation test value %s', time()), + ]); + } + + #[\Override] + protected function tearDown(): void + { + $this->documentService->delete($this->documentId); + } + + #[Test] + #[TestDox('all fixed system fields in UserfieldDocumentItemResult are annotated in phpdoc and match with raw api response')] + public function testAllFieldsAreAnnotated(): void + { + $rawItem = $this->userfieldDocumentService->list( + ['documentType', 'documentId', $this->userfieldCode], + ['documentType' => 'A', 'documentId' => $this->documentId] + )->getCoreResponse()->getResponseData()->getResult()['documents'][0]; + + // Dynamic userfield keys (fieldN) are portal-specific and intentionally not part of the + // static PHPDoc contract — only the fixed system keys are checked here. + $fixedSystemFields = array_intersect(array_keys($rawItem), ['documentId', 'documentType']); + + $this->assertBitrix24AllResultItemFieldsAnnotated($fixedSystemFields, UserfieldDocumentItemResult::class); + } + + #[Test] + #[TestDox('all fields in UserfieldDocumentItemResult have valid type casting in magic getters')] + public function testAllFieldsHasValidTypeCastingInMagicGetters(): void + { + $itemResult = $this->userfieldDocumentService->list( + ['documentType', 'documentId', $this->userfieldCode], + ['documentType' => 'A', 'documentId' => $this->documentId] + )->getDocuments()[0]; + + $this->assertBitrix24ResultItemFieldsTypeCastMatchAnnotations($itemResult, UserfieldDocumentItemResult::class); + } + + #[Test] + #[TestDox('dynamic userfield value is accessible via magic getter even though it is unannotated')] + public function testDynamicUserfieldValueIsAccessible(): void + { + $itemResult = $this->userfieldDocumentService->list( + ['documentType', 'documentId', $this->userfieldCode], + ['documentType' => 'A', 'documentId' => $this->documentId] + )->getDocuments()[0]; + + $this->assertNotEmpty($itemResult->{$this->userfieldCode}); + } +} diff --git a/tests/Integration/Services/Catalog/UserfieldDocument/Service/BatchTest.php b/tests/Integration/Services/Catalog/UserfieldDocument/Service/BatchTest.php new file mode 100644 index 00000000..7f1f66cd --- /dev/null +++ b/tests/Integration/Services/Catalog/UserfieldDocument/Service/BatchTest.php @@ -0,0 +1,100 @@ + + * + * 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\Catalog\UserfieldDocument\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\Document\Service\Document; +use Bitrix24\SDK\Services\Catalog\UserfieldDocument\Service\Batch; +use Bitrix24\SDK\Services\Catalog\UserfieldDocument\Service\UserfieldDocument; +use Bitrix24\SDK\Tests\Builders\Services\Catalog\UserfieldDocument\CatalogDocumentUserfieldFixture; +use Bitrix24\SDK\Tests\Integration\Factory; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +/** + * Requires application (OAuth) credentials — see tests/ApplicationBridge/. + */ +#[CoversClass(Batch::class)] +class BatchTest extends TestCase +{ + private UserfieldDocument $userfieldDocumentService; + + private Document $documentService; + + private string $userfieldCode; + + /** + * @var int[] + */ + private array $createdDocumentIds = []; + + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Factory::getServiceBuilder(true); + $this->userfieldDocumentService = $serviceBuilder->getCatalogScope()->userfieldDocument(); + $this->documentService = $serviceBuilder->getCatalogScope()->document(); + $this->userfieldCode = CatalogDocumentUserfieldFixture::getOrCreateFieldCode(Factory::getCore(true)); + } + + #[\Override] + protected function tearDown(): void + { + foreach ($this->createdDocumentIds as $documentId) { + try { + $this->documentService->delete($documentId); + } catch (\Throwable) { + // already removed, ignore + } + } + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test Batch::update')] + public function testUpdate(): void + { + $documentIds = []; + for ($i = 0; $i < 2; ++$i) { + $documentIds[] = $this->documentService->add([ + 'docType' => 'A', + 'currency' => 'USD', + 'responsibleId' => 1, + 'title' => sprintf('batch userfield document %s-%s', time(), $i), + ])->document()->id; + } + + $this->createdDocumentIds = array_merge($this->createdDocumentIds, $documentIds); + + $updatePayload = []; + foreach ($documentIds as $documentId) { + $updatePayload[$documentId] = [ + 'documentType' => 'A', + $this->userfieldCode => sprintf('batch value %s', $documentId), + ]; + } + + $updatedCount = 0; + foreach ($this->userfieldDocumentService->batch->update($updatePayload) as $updatedItemResult) { + $this->assertNotEmpty($updatedItemResult->document()->{$this->userfieldCode}); + ++$updatedCount; + } + + $this->assertSame(2, $updatedCount); + } +} diff --git a/tests/Integration/Services/Catalog/UserfieldDocument/Service/UserfieldDocumentTest.php b/tests/Integration/Services/Catalog/UserfieldDocument/Service/UserfieldDocumentTest.php new file mode 100644 index 00000000..f4a92b23 --- /dev/null +++ b/tests/Integration/Services/Catalog/UserfieldDocument/Service/UserfieldDocumentTest.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\Tests\Integration\Services\Catalog\UserfieldDocument\Service; + +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\TransportException; +use Bitrix24\SDK\Services\Catalog\Document\Service\Document; +use Bitrix24\SDK\Services\Catalog\UserfieldDocument\Service\UserfieldDocument; +use Bitrix24\SDK\Tests\Builders\Services\Catalog\UserfieldDocument\CatalogDocumentUserfieldFixture; +use Bitrix24\SDK\Tests\Integration\Factory; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\TestCase; + +/** + * Requires application (OAuth) credentials — see tests/ApplicationBridge/ — because discovering / + * creating a catalog-module userfield to exercise fieldN read/write needs userfieldconfig.*, which + * a plain incoming webhook is not permitted to call. + */ +#[CoversClass(UserfieldDocument::class)] +class UserfieldDocumentTest extends TestCase +{ + private UserfieldDocument $userfieldDocumentService; + + private Document $documentService; + + private string $userfieldCode; + + /** + * @var int[] + */ + private array $createdDocumentIds = []; + + #[\Override] + protected function setUp(): void + { + $serviceBuilder = Factory::getServiceBuilder(true); + $this->userfieldDocumentService = $serviceBuilder->getCatalogScope()->userfieldDocument(); + $this->documentService = $serviceBuilder->getCatalogScope()->document(); + $this->userfieldCode = CatalogDocumentUserfieldFixture::getOrCreateFieldCode(Factory::getCore(true)); + } + + #[\Override] + protected function tearDown(): void + { + foreach ($this->createdDocumentIds as $documentId) { + try { + $this->documentService->delete($documentId); + } catch (\Throwable) { + // already removed, ignore + } + } + } + + /** + * @throws BaseException + * @throws TransportException + */ + #[TestDox('test UserfieldDocument::update, UserfieldDocument::list')] + public function testUpdateAndList(): void + { + $documentId = $this->createDocument(); + $fieldValue = sprintf('test userfield value %s', time()); + + $updateResult = $this->userfieldDocumentService->update($documentId, [ + 'documentType' => 'A', + $this->userfieldCode => $fieldValue, + ]); + $this->assertSame($documentId, $updateResult->document()->documentId); + $this->assertSame($fieldValue, $updateResult->document()->{$this->userfieldCode}); + + $listResult = $this->userfieldDocumentService->list( + ['documentType', 'documentId', $this->userfieldCode], + ['documentType' => 'A', 'documentId' => $documentId] + ); + $documents = $listResult->getDocuments(); + $this->assertCount(1, $documents); + $this->assertSame($fieldValue, $documents[0]->{$this->userfieldCode}); + } + + /** + * @throws BaseException + * @throws TransportException + */ + private function createDocument(): int + { + $documentId = $this->documentService->add([ + 'docType' => 'A', + 'currency' => 'USD', + 'responsibleId' => 1, + 'title' => sprintf('test userfield document %s', time()), + ])->document()->id; + $this->createdDocumentIds[] = $documentId; + + return $documentId; + } +} diff --git a/tests/Unit/Services/Catalog/UserfieldDocument/Service/UserfieldDocumentTest.php b/tests/Unit/Services/Catalog/UserfieldDocument/Service/UserfieldDocumentTest.php new file mode 100644 index 00000000..c6f680c9 --- /dev/null +++ b/tests/Unit/Services/Catalog/UserfieldDocument/Service/UserfieldDocumentTest.php @@ -0,0 +1,73 @@ +mockCore('catalog.userfield.document.list', [ + 'select' => ['documentType', 'documentId', 'field7097'], + 'filter' => ['documentType' => 'A', 'documentId' => 81], + 'order' => ['documentId' => 'ASC'], + 'start' => 0, + ]); + + self::assertInstanceOf( + UserfieldDocumentsResult::class, + $this->makeService($core)->list( + ['documentType', 'documentId', 'field7097'], + ['documentType' => 'A', 'documentId' => 81], + ['documentId' => 'ASC'] + ) + ); + } + + public function testUpdateBuildsParameters(): void + { + $core = $this->mockCore('catalog.userfield.document.update', [ + 'documentId' => 81, + 'fields' => ['documentType' => 'A', 'field7097' => 'Test field value'], + ]); + + self::assertInstanceOf( + UserfieldDocumentResult::class, + $this->makeService($core)->update(81, ['documentType' => 'A', 'field7097' => 'Test field value']) + ); + } + + private function makeService(CoreInterface $core): UserfieldDocument + { + return new UserfieldDocument( + new Batch(new UserfieldDocumentBatch($core, new NullLogger()), new NullLogger()), + $core, + new NullLogger() + ); + } + + private function mockCore(string $method, array $parameters): CoreInterface + { + $response = $this->createStub(Response::class); + $core = $this->createMock(CoreInterface::class); + $core->expects($this->once()) + ->method('call') + ->with($method, $parameters) + ->willReturn($response); + + return $core; + } +}