diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..2a1f3629 --- /dev/null +++ b/.env.example @@ -0,0 +1,37 @@ +# DocuWare REST API (maps to Postman environment "DocuWare") +# +# Postman Laravel / config +# ---------------- -------------------------------------------- +# ServerUrl DOCUWARE_URL (scheme + host, no trailing path) +# Platform DOCUWARE_PLATFORM_PATH (default: DocuWare/Platform) +# Username DOCUWARE_USERNAME +# Password DOCUWARE_PASSWORD +# OrgId DOCUWARE_TESTS_ORG_ID (optional; or DOCUWARE_TESTS_ORGANIZATION_ID) +# FileCabinetId DOCUWARE_TESTS_FILE_CABINET_ID +# SearchDialogId DOCUWARE_TESTS_SEARCH_DIALOG_ID (optional; falls back to DOCUWARE_TESTS_DIALOG_ID in your app) +# StoreDialogId DOCUWARE_TESTS_STORE_DIALOG_ID +# DocumentId DOCUWARE_TESTS_DOCUMENT_ID +# ClientID / ClientSecret β€” OAuth client; package uses DOCUWARE_CLIENT_ID + password grant by default + +DOCUWARE_URL= +DOCUWARE_PLATFORM_PATH=DocuWare/Platform +DOCUWARE_USERNAME= +DOCUWARE_PASSWORD= +DOCUWARE_PASSPHRASE= +DOCUWARE_CLIENT_ID=docuware.platform.net.client +DOCUWARE_SCOPE=docuware.platform +DOCUWARE_TIMEOUT=60 +DOCUWARE_CACHE_DRIVER=file +DOCUWARE_CACHE_LIFETIME_IN_SECONDS=60 + +# PHPUnit / local live tests (see docs/postman-parity.md) +DOCUWARE_TESTS_FILE_CABINET_ID= +DOCUWARE_TESTS_DIALOG_ID= +DOCUWARE_TESTS_BASKET_ID= +DOCUWARE_TESTS_ORG_ID= +DOCUWARE_TESTS_SEARCH_DIALOG_ID= +DOCUWARE_TESTS_STORE_DIALOG_ID= +DOCUWARE_TESTS_DOCUMENT_ID= +DOCUWARE_TESTS_ORGANIZATION_ID= +DOCUWARE_TESTS_GROUP_ID= +DOCUWARE_TESTS_ROLE_ID= diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index bc5e177e..c8596fba 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -29,8 +29,8 @@ We're sorry to hear you have a problem. Can you help us solve it by providing th attributes: label: PHP Version description: What version of PHP are you running? Please be as specific as possible - placeholder: "8.4.0" - value: "8.4.0" + placeholder: "8.5.0" + value: "8.5.0" validations: required: true - type: input @@ -38,8 +38,8 @@ We're sorry to hear you have a problem. Can you help us solve it by providing th attributes: label: Laravel Version description: What version of Laravel are you running? Please be as specific as possible - placeholder: "12.0.0" - value: "12.0.0" + placeholder: "13.0.0" + value: "13.0.0" validations: required: true - type: dropdown diff --git a/.github/workflows/composer-audit.yml b/.github/workflows/composer-audit.yml index ed5c5478..72698cfa 100644 --- a/.github/workflows/composer-audit.yml +++ b/.github/workflows/composer-audit.yml @@ -28,7 +28,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@2.37.0 with: - php-version: '8.4' + php-version: '8.5' coverage: none - name: Resolve dependencies and audit diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 5bfa1ad9..b8a14171 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -9,11 +9,13 @@ jobs: dependabot: runs-on: ubuntu-latest if: ${{ github.actor == 'dependabot[bot]' }} + env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v2.5.0 + uses: dependabot/fetch-metadata@v3.0.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/fix-php-code-style-issues.yml b/.github/workflows/fix-php-code-style-issues.yml index 41e61934..14165467 100644 --- a/.github/workflows/fix-php-code-style-issues.yml +++ b/.github/workflows/fix-php-code-style-issues.yml @@ -13,8 +13,17 @@ jobs: - name: Checkout code uses: actions/checkout@v6.0.2 - - name: Fix PHP code style issues - uses: aglipanci/laravel-pint-action@2.6 + - name: Setup PHP + uses: shivammathur/setup-php@2.37.0 + with: + php-version: '8.5' + coverage: none + + - name: Install composer dependencies + uses: ramsey/composer-install@4.0.0 + + - name: Run Laravel Pint + run: vendor/bin/pint - name: Commit changes uses: stefanzweifel/git-auto-commit-action@v7.1.0 diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 18023123..5bbb64c8 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -32,7 +32,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@2.37.0 with: - php-version: '8.4' + php-version: '8.5' coverage: none - name: Install composer dependencies diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 69be47a6..0eb9ffb3 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -14,22 +14,22 @@ jobs: max-parallel: 1 matrix: os: [ ubuntu-latest ] - php: [ 8.2, 8.3, 8.4 ] - laravel: [ 12.* ] + php: [ 8.3, 8.4, 8.5 ] + laravel: [ 13.* ] stability: [ prefer-lowest, prefer-stable ] name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo - coverage: none + coverage: pcov - name: Setup problem matchers run: | @@ -41,10 +41,10 @@ jobs: composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update composer update --${{ matrix.stability }} --prefer-dist --no-interaction - - name: Execute tests + - name: Copy PHPUnit configuration run: cp phpunit.xml.dist phpunit.xml - - name: Execute tests + - name: Run Pest tests run: vendor/bin/pest env: DOCUWARE_URL: ${{ secrets.DOCUWARE_URL }} @@ -54,7 +54,7 @@ jobs: - name: Store Log Artifacts if: failure() - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: Store report artifacts path: ./vendor/orchestra/testbench-core/laravel/storage/logs diff --git a/README.md b/README.md index 69ed4391..0b512b27 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ See the documentation if you need further functionality. ⚠️ * [πŸ’₯ Exceptions explained](#-exceptions-explained) * [✨ Events](#-events) * [πŸ”§ Configuration file](#-configuration-file) + * [Postman collection parity & Saloon fixtures](#postman-collection-parity--saloon-fixtures) * [🚧 Testing](#-testing) * [πŸ“ Changelog](#-changelog) * [✏️ Contributing](#-contributing) @@ -198,20 +199,20 @@ then optimize the processes that power the core of your business. | FileCabinets/Search | Get a Specific Document From a File Cabinet | βœ… | | | FileCabinets/Search | Search for Documents in a Single File Cabinet | βœ… | | | FileCabinets/Search | Search for Documents in Multiple File Cabinets | βœ… | | -| FileCabinets/CheckInCheckOut | Check-out & Download a Document | πŸ•£ | | -| FileCabinets/CheckInCheckOut | Check-in a Document from the File System | πŸ•£ | | -| FileCabinets/CheckInCheckOut | Undo Check-out | πŸ•£ | | +| FileCabinets/CheckInCheckOut | Check-out & Download a Document | βœ… | `CheckoutDocumentToFileSystem` | +| FileCabinets/CheckInCheckOut | Check-in a Document from the File System | βœ… | `CheckInDocumentFromFileSystem` | +| FileCabinets/CheckInCheckOut | Undo Check-out | βœ… | `UndoDocumentCheckout` | | FileCabinets/SelectLists | Get Select Lists & Get Filtered Select Lists | βœ… | | | FileCabinets/Upload | Create Data Record | βœ… | | | FileCabinets/Upload | Append File(s) to a Data Record | βœ… | | | FileCabinets/Upload | Upload a Single File for a Data Record | ❌ | - | | FileCabinets/Upload | Create a Data Record & Upload File | ❌ | - | -| FileCabinets/Upload | Create Data Record & Upload File Using Store Dialog | ❌ | - | +| FileCabinets/Upload | Create Data Record & Upload File Using Store Dialog | βœ… | `CreateDataRecord` + `storeDialogId` | | FileCabinets/Upload | Append a Single PDF to a Document | βœ… | - | | FileCabinets/Upload | Replace a PDF Document Section | βœ… | | -| FileCabinets/BatchIndexFieldsUpdate | Batch Update Index Fields By Id | ❌ | - | -| FileCabinets/BatchIndexFieldsUpdate | Batch Update Index Fields By Search | ❌ | - | -| FileCabinets/BatchIndexFieldsUpdate | Batch Append/Update Keyword Fields By Id | ❌ | - | +| FileCabinets/BatchIndexFieldsUpdate | Batch Update Index Fields By Id | βœ… | `BatchDocumentsUpdateFields` | +| FileCabinets/BatchIndexFieldsUpdate | Batch Update Index Fields By Search | βœ… | `BatchDocumentsUpdateFields` | +| FileCabinets/BatchIndexFieldsUpdate | Batch Append/Update Keyword Fields By Id | βœ… | `BatchDocumentsUpdateFields` | | Documents/UpdateIndexValues | Update Index Values | βœ… | | | Documents/UpdateIndexValues | Update Table Field Values | ❌ | - ? | | Documents/ModifyDocuments | Transfer Document | βœ… | | @@ -220,15 +221,15 @@ then optimize the processes that power the core of your business. | Documents/ClipUnclip&StapleUnstaple | Unclip | βœ… | | | Documents/ClipUnclip&StapleUnstaple | Staple | βœ… | | | Documents/ClipUnclip&StapleUnstaple | Unstaple | βœ… | | -| Documents/AnnotationsStamps | AddStampWithPosition | πŸ•£ | | -| Documents/AnnotationsStamps | AddStampWithBestPosition | πŸ•£ | | +| Documents/AnnotationsStamps | AddStampWithPosition | βœ… | `AddDocumentAnnotations` | +| Documents/AnnotationsStamps | AddStampWithBestPosition | βœ… | `AddDocumentAnnotations` | | Documents/AnnotationsStamps | AddTextAnnotation | πŸ•£ | | | Documents/AnnotationsStamps | AddRectEntryAnnotation | πŸ•£ | | | Documents/AnnotationsStamps | AddLineEntryAnnotation | πŸ•£ | | | Documents/AnnotationsStamps | AddPolyLineEntryAnnotation | ❌ | - | | Documents/AnnotationsStamps | DeleteAnnotation | ❌ | - | | Documents/AnnotationsStamps | UpdateTextAnnotation | πŸ•£ | | -| Documents/AnnotationsStamps | Get Stamps | ❌ | - | +| Documents/AnnotationsStamps | Get Stamps | βœ… | `GetStamps` | | Documents/DocumentsTrashBin | Get Documents | βœ… | | | Documents/DocumentsTrashBin | Delete Documents | βœ… | | | Documents/DocumentsTrashBin | Restore Documents | βœ… | | @@ -1744,6 +1745,17 @@ return [ 'timeout' => env('DOCUWARE_TIMEOUT', 15), + /* + |-------------------------------------------------------------------------- + | Platform path + |-------------------------------------------------------------------------- + | + | Matches Postman {{Platform}} (default DocuWare/Platform). + | + */ + + 'platform_path' => env('DOCUWARE_PLATFORM_PATH', 'DocuWare/Platform'), + /* |-------------------------------------------------------------------------- | DocuWare Credentials @@ -1816,10 +1828,29 @@ return [ 'file_cabinet_id' => env('DOCUWARE_TESTS_FILE_CABINET_ID'), 'dialog_id' => env('DOCUWARE_TESTS_DIALOG_ID'), 'basket_id' => env('DOCUWARE_TESTS_BASKET_ID'), + 'org_id' => env('DOCUWARE_TESTS_ORG_ID', env('DOCUWARE_TESTS_ORGANIZATION_ID')), + 'search_dialog_id' => env('DOCUWARE_TESTS_SEARCH_DIALOG_ID'), + 'store_dialog_id' => env('DOCUWARE_TESTS_STORE_DIALOG_ID'), + 'document_id' => env('DOCUWARE_TESTS_DOCUMENT_ID'), ], ]; ``` +## Postman collection parity & Saloon fixtures + +The official DocuWare Postman collection uses `{{ServerUrl}}` and `{{Platform}}` (default `DocuWare/Platform`). This package maps them to Laravel env vars β€” see [`.env.example`](.env.example) for a **Postman variable β†’ `DOCUWARE_*`** table. + +- **Parity matrix** (endpoints vs request classes): [`docs/postman-parity.md`](docs/postman-parity.md). +- **Platform path**: `DOCUWARE_PLATFORM_PATH` (used by `DocuWareConnector`, `GetResponsibleIdentityService`, and encrypted Web Client URLs in `DocuWareUrl`). +- **CI-friendly tests**: Default `composer test` runs **unit**, **DTO**, and **Saloon fixture** tests (`tests/Feature/SaloonFixtures`). HTTP responses are replayed from JSON files under [`tests/Fixtures/saloon/`](tests/Fixtures/saloon) using [Saloon fixtures](https://docs.saloon.dev/digging-deeper/testing) (`MockClient` + `Fixture`). Bodies use Saloon’s recorded format: `statusCode`, `headers`, `data` (raw response body), `context`. +- **Recording fixtures** (optional): Edit [`tests/Manual/RecordGetOrganizationFixtureTest.php`](tests/Manual/RecordGetOrganizationFixtureTest.php), remove the `->skip(...)`, set real `DOCUWARE_*` credentials, then run: + ```bash + composer test:manual + ``` + (`composer test:manual` runs only `tests/Manual`.) + Review the generated JSON for secrets, commit if safe, then restore the skip. +- **Live tenant tests** (destructive cleanup, real API): `composer test:live` runs the `integration` PHPUnit testsuite (`tests/Integration`). Requires valid DocuWare credentials and test cabinet IDs in `phpunit.xml` or the environment. + ## 🚧 Testing Copy your own phpunit.xml-file. @@ -1832,6 +1863,7 @@ Modify environment variables in the phpunit.xml-file: ```xml + @@ -1844,14 +1876,24 @@ Modify environment variables in the phpunit.xml-file: + + + + ``` -Run the tests: +Default test run (no live DocuWare required): ```bash composer test ``` +Against a real system (integration suite): + +```bash +composer test:live +``` + ## πŸ“ Changelog Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. diff --git a/composer.json b/composer.json index 409fc869..428151ce 100644 --- a/composer.json +++ b/composer.json @@ -21,24 +21,27 @@ } ], "require": { - "php": "8.2.*|8.3.*|8.4.*", - "guzzlehttp/guzzle": "^7.8", - "illuminate/contracts": "^12.0", - "nesbot/carbon": "^3.8", + "php": "8.3.*|8.4.*|8.5.*", + "guzzlehttp/guzzle": "^7.9.2", + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0", + "nesbot/carbon": "^3.8.4", "saloonphp/cache-plugin": "^3.1", - "saloonphp/laravel-plugin": "^3.0|^4.0", - "saloonphp/saloon": "^3.0|^4.0", - "spatie/laravel-package-tools": "^1.19" + "saloonphp/laravel-plugin": "^4.0", + "saloonphp/saloon": "^4.0", + "spatie/laravel-package-tools": "^1.19.0" }, "require-dev": { - "laravel/pint": "^1.21", - "larastan/larastan": "^v3.1", - "orchestra/testbench": "^10.0", - "pestphp/pest": "^3.7", - "phpstan/extension-installer": "^1.4", - "phpstan/phpstan-deprecation-rules": "^2.0", - "phpstan/phpstan-phpunit": "^2.0", - "spatie/laravel-ray": "^1.39" + "laravel/pint": "^1.21.1", + "larastan/larastan": "^3.9.3", + "nunomaduro/collision": "^8.9", + "orchestra/testbench": "^11.0", + "pestphp/pest": "^4.4", + "phpdocumentor/reflection-docblock": "^5.6.1", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan-deprecation-rules": "^2.0.1", + "phpstan/phpstan-phpunit": "^2.0.4", + "spatie/laravel-ray": "^1.40.0" }, "autoload": { "psr-4": { @@ -53,16 +56,18 @@ "scripts": { "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", "analyse": "vendor/bin/phpstan analyse", - "test": "vendor/bin/pest", - "test-coverage": "vendor/bin/pest --coverage", + "test": "vendor/bin/pest --no-coverage --testsuite=default", + "test:live": "vendor/bin/pest --no-coverage --testsuite=integration", + "test:manual": "vendor/bin/pest --no-coverage tests/Manual", + "test-coverage": "vendor/bin/pest --coverage --testsuite=default", "format": "vendor/bin/pint" }, "config": { "sort-packages": true, "allow-plugins": { - "composer/package-versions-deprecated": true, - "phpstan/extension-installer": true, - "pestphp/pest-plugin": true + "composer/package-versions-deprecated": false, + "pestphp/pest-plugin": true, + "phpstan/extension-installer": true } }, "extra": { diff --git a/config/laravel-docuware.php b/config/laravel-docuware.php index d8cc11ef..d6934a07 100644 --- a/config/laravel-docuware.php +++ b/config/laravel-docuware.php @@ -23,6 +23,18 @@ 'timeout' => env('DOCUWARE_TIMEOUT', 15), + /* + |-------------------------------------------------------------------------- + | Platform path + |-------------------------------------------------------------------------- + | + | Postman variable {{Platform}} is usually "DocuWare/Platform". Base URL is + | rtrim(DOCUWARE_URL,'/').'/'.platform_path + | + */ + + 'platform_path' => env('DOCUWARE_PLATFORM_PATH', 'DocuWare/Platform'), + /* |-------------------------------------------------------------------------- | DocuWare Credentials @@ -95,5 +107,9 @@ 'file_cabinet_id' => env('DOCUWARE_TESTS_FILE_CABINET_ID'), 'dialog_id' => env('DOCUWARE_TESTS_DIALOG_ID'), 'basket_id' => env('DOCUWARE_TESTS_BASKET_ID'), + 'org_id' => env('DOCUWARE_TESTS_ORG_ID', env('DOCUWARE_TESTS_ORGANIZATION_ID')), + 'search_dialog_id' => env('DOCUWARE_TESTS_SEARCH_DIALOG_ID'), + 'store_dialog_id' => env('DOCUWARE_TESTS_STORE_DIALOG_ID'), + 'document_id' => env('DOCUWARE_TESTS_DOCUMENT_ID'), ], ]; diff --git a/docs/postman-parity.md b/docs/postman-parity.md new file mode 100644 index 00000000..b22fc4b8 --- /dev/null +++ b/docs/postman-parity.md @@ -0,0 +1,95 @@ +# DocuWare Postman collection vs this package + +Reference: official **DocuWare** Postman collection (e.g. `DocuWare.postman_collection.json`, Sept 2024). +Base URL pattern: `{ServerUrl}/{Platform}/…` with `Platform` default `DocuWare/Platform` β€” matches `DOCUWARE_URL` + `DOCUWARE_PLATFORM_PATH` in this package. + +Legend: **Parity** = covered with equivalent Saloon request; **Partial** = same endpoint, naming/options differ; **Missing** = not implemented yet. + +## Authentication + +| Postman | Package | +|--------|---------| +| 1. Get Responsible Identity Service | `GetResponsibleIdentityService` β€” Parity | +| 2. Get Identity Service Configuration | `GetIdentityServiceConfiguration` β€” Parity | +| 3.a–3.d OAuth token requests | `RequestTokenWithCredentials`, `RequestTokenWithCredentialsTrustedUser` β€” Partial (Postman has DocuWare token / Windows variants) | + +## General β€” Organization + +| Postman | Package | +|--------|---------| +| Get Login Token | `GetLoginToken` β€” Parity | +| Get Organization | `GetOrganization` β€” Parity | +| Get all File Cabinets and Document Trays | `GetAllFileCabinetsAndDocumentTrays` β€” Parity (`OrgId` via constructor) | + +## General β€” User management + +| Postman | Package | +|--------|---------| +| Get Users, Get User by ID, Users of Role/Group | `GetUsers`, `GetUserById`, … β€” Parity | +| Create / Update User | `CreateUser`, `UpdateUser` β€” Parity | +| Groups / Roles CRUD | `GetGroups`, `AddUserToAGroup`, … β€” Parity | + +## File cabinets β€” General / Dialogs / Search / Select lists + +| Postman | Package | +|--------|---------| +| Get File Cabinet Information | `GetFileCabinetInformation` β€” Parity | +| Get Total Number of Documents | `GetTotalNumberOfDocuments` β€” Parity | +| Get All / Specific / Typed Dialogs | `GetAllDialogs`, `GetASpecificDialog`, `GetDialogsOfASpecificType` β€” Parity | +| Get Documents / Specific Document | `GetDocumentsFromAFileCabinet`, `GetASpecificDocumentFromAFileCabinet` β€” Parity | +| DialogExpression search (single / multi cabinet) | `GetSearchRequest` / builder β€” Partial (align query/body with Postman examples) | +| Get / Filtered Select Lists | `GetSelectLists`, `GetFilteredSelectLists` β€” Parity | + +## File cabinets β€” Check in / Check out + +| Postman | Package | +|--------|---------| +| Check-out & Download (CheckoutToFileSystem) | `CheckoutDocumentToFileSystem` β€” Parity | +| Check-in from file system (multipart) | `CheckInDocumentFromFileSystem` β€” Parity | +| Undo Check-out (ProcessDocumentAction) | `UndoDocumentCheckout` β€” Parity | + +## File cabinets β€” Upload + +| Postman | Package | +|--------|---------| +| Create Data Record | `CreateDataRecord` β€” Parity | +| Create with `StoreDialogId` query | `CreateDataRecord` β€” Partial (use `storeDialogId` constructor arg) | +| Append files / Replace PDF / Append single PDF | `AppendFilesToADataRecord`, `ReplaceAPDFDocumentSection`, `AppendASinglePDFToADocument` β€” Parity | +| Other Postman-named upload variants | Same endpoints as above β€” Partial (naming only) | + +## File cabinets β€” Batch index + +| Postman | Package | +|--------|---------| +| Batch Update By Id / By Search / Keywords | `BatchDocumentsUpdateFields` β€” Parity (pass full JSON `Source` + `Data` as array) | + +## Documents + +| Postman | Package | +|--------|---------| +| Update Index Values / Table fields | `UpdateIndexValues` β€” Parity | +| Transfer / Delete | `TransferDocument`, `DeleteDocument` β€” Parity | +| Clip / Unclip / Staple / Unstaple | `Clip`, `Unclip`, `Staple`, `Unstaple` β€” Parity | +| Trash bin | `GetDocuments`, `DeleteDocuments`, `RestoreDocuments` (trash) β€” Parity | +| Application properties | `GetApplicationProperties`, … β€” Parity | +| Sections / Textshot | `GetAllSectionsFromADocument`, … β€” Parity | +| Download / Thumbnail | `DownloadDocument`, `DownloadSection`, `DownloadThumbnail` β€” Parity | +| Get Stamps | `GetStamps` β€” Parity | +| Add stamp (Annotation endpoint) | `AddDocumentAnnotations` β€” Parity (body as `array`) | +| Get / Add / Update / Delete annotations (full set) | **Partial** β€” stamp-oriented coverage via `AddDocumentAnnotations`; other annotation types may still be Missing | + +## Workflow + +| Postman | Package | +|--------|---------| +| Workflow history / steps | `GetDocumentWorkflowHistory`, `GetDocumentWorkflowHistorySteps` β€” Parity | + +## Fields + +| Postman | Package | +|--------|---------| +| Fields on cabinet | `GetFieldsRequest` β€” Parity | + +--- + +When Postman updates, diff new `raw` URLs under `FileCabinets`, `Documents`, and `Organization` against `src/Requests/**/resolveEndpoint()`. diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 0cc2d040..3438d94e 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,7 +2,7 @@ includes: - phpstan-baseline.neon parameters: - level: 5 + level: 6 paths: - src - config diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 5d65eeb6..addd3cf5 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,12 +1,18 @@ - - tests + + tests/Unit + tests/Core + tests/Feature + tests/Manual + + + tests/Integration @@ -22,6 +28,7 @@ + diff --git a/src/Connectors/DocuWareConnector.php b/src/Connectors/DocuWareConnector.php index b36fa324..3796eee8 100644 --- a/src/Connectors/DocuWareConnector.php +++ b/src/Connectors/DocuWareConnector.php @@ -17,6 +17,7 @@ use Psr\SimpleCache\InvalidArgumentException; use Saloon\Http\Auth\TokenAuthenticator; use Saloon\Http\Connector; +use Saloon\Http\Response; class DocuWareConnector extends Connector { @@ -26,7 +27,10 @@ public function __construct( public function resolveBaseUrl(): string { - return $this->configuration->url.'/DocuWare/Platform'; + $base = rtrim($this->configuration->url, '/'); + $platform = trim(config('laravel-docuware.platform_path', 'DocuWare/Platform'), '/'); + + return $base.'/'.$platform; } public function defaultHeaders(): array @@ -48,9 +52,13 @@ protected function defaultAuth(): TokenAuthenticator return new TokenAuthenticator($this->getOrCreateNewOAuthToken()); } + protected function oauthTokenCacheTtlSeconds(RequestTokenDto $token): int + { + return max(1, $token->expiresIn - 60); + } + /** * @throws InvalidArgumentException - * @throws \Exception */ protected function getOrCreateNewOAuthToken(): string { @@ -58,7 +66,6 @@ protected function getOrCreateNewOAuthToken(): string $cacheKey = 'docuware.oauth.'.$this->configuration->identifier; - // Check if the token exists in cache and return it if found if ($cache->has($cacheKey)) { $token = Crypt::decrypt($cache->get($cacheKey)); DocuWareOAuthLog::dispatch($this->configuration->url, $this->configuration->username, 'Token retrieved from cache'); @@ -66,24 +73,19 @@ protected function getOrCreateNewOAuthToken(): string return $token->accessToken; } - // Handle token retrieval for ConfigWithCredentials if ($this->configuration instanceof ConfigWithCredentials) { $token = $this->getNewOAuthTokenWithCredentials(); DocuWareOAuthLog::dispatch($this->configuration->url, $this->configuration->username, 'Token retrieved from API'); - $cache->put($cacheKey, Crypt::encrypt($token), $token->expiresIn - 60); + $cache->put($cacheKey, Crypt::encrypt($token), $this->oauthTokenCacheTtlSeconds($token)); return $token->accessToken; } - // Handle token retrieval for ConfigWithCredentialsTrustedUser - // @phpstan-ignore-next-line - if ($this->configuration instanceof ConfigWithCredentialsTrustedUser) { - $token = $this->getNewOAuthTokenWithCredentialsTrustedUser(); - DocuWareOAuthLog::dispatch($this->configuration->url, $this->configuration->username, 'Token retrieved from API'); - $cache->put($cacheKey, Crypt::encrypt($token), $token->expiresIn - 60); + $token = $this->getNewOAuthTokenWithCredentialsTrustedUser(); + DocuWareOAuthLog::dispatch($this->configuration->url, $this->configuration->username, 'Token retrieved from API'); + $cache->put($cacheKey, Crypt::encrypt($token), $this->oauthTokenCacheTtlSeconds($token)); - return $token->accessToken; - } + return $token->accessToken; } protected function getAuthenticationTokenEndpoint(): IdentityServiceConfiguration @@ -111,18 +113,7 @@ protected function getNewOAuthTokenWithCredentials(): RequestTokenDto password: $this->configuration->password, ))->send(); - throw_if( - $requestTokenResponse->failed(), - trim(preg_replace('/\s\s+/', ' ', Arr::get( - array: $requestTokenResponse->json(), - key: 'error_description', - default: $requestTokenResponse->body() - ))) - ); - - throw_if($requestTokenResponse->dto() == null, 'Token response is null'); - - return $requestTokenResponse->dto(); + return $this->ensureRequestTokenSuccess($requestTokenResponse); } /** @@ -140,6 +131,15 @@ protected function getNewOAuthTokenWithCredentialsTrustedUser(): RequestTokenDto impersonateName: $this->configuration->impersonatedUsername, ))->send(); + return $this->ensureRequestTokenSuccess($requestTokenResponse); + } + + /** + * @throws \Throwable + * @throws \JsonException + */ + protected function ensureRequestTokenSuccess(Response $requestTokenResponse): RequestTokenDto + { throw_if( $requestTokenResponse->failed(), trim(preg_replace('/\s\s+/', ' ', Arr::get( diff --git a/src/DTO/Authentication/OAuth/IdentityServiceConfiguration.php b/src/DTO/Authentication/OAuth/IdentityServiceConfiguration.php index 800c0824..8bd3b5de 100644 --- a/src/DTO/Authentication/OAuth/IdentityServiceConfiguration.php +++ b/src/DTO/Authentication/OAuth/IdentityServiceConfiguration.php @@ -6,6 +6,9 @@ final class IdentityServiceConfiguration { + /** + * @param array $data + */ public static function make(array $data): self { return new self( @@ -26,26 +29,41 @@ public static function make(array $data): self frontchannelLogoutSessionSupported: Arr::get($data, 'frontchannel_logout_session_supported'), backchannelLogoutSupported: Arr::get($data, 'backchannel_logout_supported'), backchannelLogoutSessionSupported: Arr::get($data, 'backchannel_logout_session_supported'), - scopesSupported: Arr::get($data, 'scopes_supported', []), - claimsSupported: Arr::get($data, 'claims_supported', []), - grantTypesSupported: Arr::get($data, 'grant_types_supported', []), - responseTypesSupported: Arr::get($data, 'response_types_supported', []), - responseModesSupported: Arr::get($data, 'response_modes_supported', []), - tokenEndpointAuthMethodsSupported: Arr::get($data, 'token_endpoint_auth_methods_supported', []), - idTokenSigningAlgValuesSupported: Arr::get($data, 'id_token_signing_alg_values_supported', []), - subjectTypesSupported: Arr::get($data, 'subject_types_supported', []), - codeChallengeMethodsSupported: Arr::get($data, 'code_challenge_methods_supported', []), + scopesSupported: self::stringList(Arr::get($data, 'scopes_supported', [])), + claimsSupported: self::stringList(Arr::get($data, 'claims_supported', [])), + grantTypesSupported: self::stringList(Arr::get($data, 'grant_types_supported', [])), + responseTypesSupported: self::stringList(Arr::get($data, 'response_types_supported', [])), + responseModesSupported: self::stringList(Arr::get($data, 'response_modes_supported', [])), + tokenEndpointAuthMethodsSupported: self::stringList(Arr::get($data, 'token_endpoint_auth_methods_supported', [])), + idTokenSigningAlgValuesSupported: self::stringList(Arr::get($data, 'id_token_signing_alg_values_supported', [])), + subjectTypesSupported: self::stringList(Arr::get($data, 'subject_types_supported', [])), + codeChallengeMethodsSupported: self::stringList(Arr::get($data, 'code_challenge_methods_supported', [])), requestParameterSupported: Arr::get($data, 'request_parameter_supported'), - requestObjectSigningAlgValuesSupported: Arr::get($data, 'request_object_signing_alg_values_supported', []), - promptValuesSupported: Arr::get($data, 'prompt_values_supported', []), + requestObjectSigningAlgValuesSupported: self::stringList(Arr::get($data, 'request_object_signing_alg_values_supported', [])), + promptValuesSupported: self::stringList(Arr::get($data, 'prompt_values_supported', [])), authorizationResponseIssParameterSupported: Arr::get($data, 'authorization_response_iss_parameter_supported'), - backchannelTokenDeliveryModesSupported: Arr::get($data, 'backchannel_token_delivery_modes_supported', []), + backchannelTokenDeliveryModesSupported: self::stringList(Arr::get($data, 'backchannel_token_delivery_modes_supported', [])), backchannelUserCodeParameterSupported: Arr::get($data, 'backchannel_user_code_parameter_supported'), - dpopSigningAlgValuesSupported: Arr::get($data, 'dpop_signing_alg_values_supported', []), + dpopSigningAlgValuesSupported: self::stringList(Arr::get($data, 'dpop_signing_alg_values_supported', [])), windowsAuthEndpoint: Arr::get($data, 'windows_auth_endpoint'), ); } + /** + * @param list $scopesSupported + * @param list $claimsSupported + * @param list $grantTypesSupported + * @param list $responseTypesSupported + * @param list $responseModesSupported + * @param list $tokenEndpointAuthMethodsSupported + * @param list $idTokenSigningAlgValuesSupported + * @param list $subjectTypesSupported + * @param list $codeChallengeMethodsSupported + * @param list $requestObjectSigningAlgValuesSupported + * @param list $promptValuesSupported + * @param list $backchannelTokenDeliveryModesSupported + * @param list $dpopSigningAlgValuesSupported + */ public function __construct( public ?string $issuer, public ?string $jwksUri, @@ -82,4 +100,25 @@ public function __construct( public array $dpopSigningAlgValuesSupported, public ?string $windowsAuthEndpoint, ) {} + + /** + * @return list + */ + private static function stringList(mixed $value): array + { + if (! is_array($value)) { + return []; + } + + $out = []; + foreach (array_values($value) as $item) { + if (is_string($item)) { + $out[] = $item; + } elseif (is_scalar($item)) { + $out[] = (string) $item; + } + } + + return $out; + } } diff --git a/src/DTO/Authentication/OAuth/RequestToken.php b/src/DTO/Authentication/OAuth/RequestToken.php index 1c8d84cc..0760760e 100644 --- a/src/DTO/Authentication/OAuth/RequestToken.php +++ b/src/DTO/Authentication/OAuth/RequestToken.php @@ -7,6 +7,9 @@ final class RequestToken { + /** + * @param array $data + */ public static function make(array $data): self { return new self( diff --git a/src/DTO/Authentication/OAuth/ResponsibleIdentityService.php b/src/DTO/Authentication/OAuth/ResponsibleIdentityService.php index 8099d024..68942fe2 100644 --- a/src/DTO/Authentication/OAuth/ResponsibleIdentityService.php +++ b/src/DTO/Authentication/OAuth/ResponsibleIdentityService.php @@ -6,6 +6,9 @@ final class ResponsibleIdentityService { + /** + * @param array $data + */ public static function make(array $data): self { return new self( diff --git a/src/DTO/Documents/Document.php b/src/DTO/Documents/Document.php index adfc596e..9f505614 100644 --- a/src/DTO/Documents/Document.php +++ b/src/DTO/Documents/Document.php @@ -5,6 +5,7 @@ use Carbon\Carbon; use CodebarAg\DocuWare\DTO\Section; use CodebarAg\DocuWare\DTO\SuggestionField; +use CodebarAg\DocuWare\Support\JsonArrays; use CodebarAg\DocuWare\Support\ParseValue; use Illuminate\Support\Arr; use Illuminate\Support\Collection; @@ -12,18 +13,21 @@ final class Document { + /** + * @param array $data + */ public static function fromJson(array $data): self { $fields = Arr::has($data, 'Fields') - ? self::convertFields(collect(Arr::get($data, 'Fields'))) + ? self::convertFields(collect(JsonArrays::listOfRecords(Arr::get($data, 'Fields')))) : null; $sections = Arr::has($data, 'Sections') - ? self::convertSections(collect(Arr::get($data, 'Sections'))) + ? self::convertSections(collect(JsonArrays::listOfRecords(Arr::get($data, 'Sections')))) : null; $suggestions = Arr::has($data, 'Suggestions') - ? self::convertSuggestions(collect(Arr::get($data, 'Suggestions'))) + ? self::convertSuggestions(collect(JsonArrays::listOfRecords(Arr::get($data, 'Suggestions')))) : null; return new self( @@ -31,7 +35,7 @@ public static function fromJson(array $data): self file_size: Arr::get($data, 'FileSize'), total_pages: Arr::get($data, 'TotalPages'), title: Arr::get($data, 'Title'), - extension: (Arr::get($fields, 'DWEXTENSION'))->value ?? null, + extension: self::extensionFromFields($fields), content_type: Arr::get($data, 'ContentType'), file_cabinet_id: Arr::get($data, 'FileCabinetId'), intellixTrust: Arr::get($data, 'IntellixTrust'), @@ -43,6 +47,29 @@ public static function fromJson(array $data): self ); } + /** + * @param Collection|null $fields + */ + protected static function extensionFromFields(?Collection $fields): ?string + { + if ($fields === null) { + return null; + } + + $field = $fields->get('DWEXTENSION'); + if (! $field instanceof DocumentField) { + return null; + } + + $value = $field->value; + + return is_string($value) ? $value : null; + } + + /** + * @param Collection> $fields + * @return Collection + */ protected static function convertFields(Collection $fields): Collection { return $fields->mapWithKeys(function (array $field) { @@ -50,6 +77,10 @@ protected static function convertFields(Collection $fields): Collection }); } + /** + * @param Collection> $suggestions + * @return Collection + */ protected static function convertSuggestions(Collection $suggestions): Collection { return $suggestions->mapWithKeys(function (array $suggestion) { @@ -57,6 +88,10 @@ protected static function convertSuggestions(Collection $suggestions): Collectio }); } + /** + * @param Collection> $sections + * @return Collection + */ protected static function convertSections(Collection $sections): Collection { return $sections->mapWithKeys(function (array $section) { @@ -64,6 +99,11 @@ protected static function convertSections(Collection $sections): Collection }); } + /** + * @param Collection|null $fields + * @param Collection|null $sections + * @param Collection|null $suggestions + */ public function __construct( public int $id, public int $file_size, @@ -118,6 +158,11 @@ public function fileName(): string return "{$name}{$this->extension}"; } + /** + * @param Collection|null $fields + * @param Collection|null $sections + * @param Collection|null $suggestions + */ public static function fake( ?int $id = null, ?int $file_size = null, diff --git a/src/DTO/Documents/DocumentField.php b/src/DTO/Documents/DocumentField.php index d7fe0c13..d38c6b60 100644 --- a/src/DTO/Documents/DocumentField.php +++ b/src/DTO/Documents/DocumentField.php @@ -9,6 +9,9 @@ final class DocumentField { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( @@ -21,6 +24,9 @@ public static function fromJson(array $data): self ); } + /** + * @param null|int|float|Carbon|string|Collection $value + */ public function __construct( public bool $systemField, public string $name, diff --git a/src/DTO/Documents/DocumentIndex/IndexDateDTO.php b/src/DTO/Documents/DocumentIndex/IndexDateDTO.php index c794c05f..78f68544 100644 --- a/src/DTO/Documents/DocumentIndex/IndexDateDTO.php +++ b/src/DTO/Documents/DocumentIndex/IndexDateDTO.php @@ -16,7 +16,7 @@ public static function make(string $name, null|Carbon|\Carbon\Carbon $value): se return new self($name, $value); } - public static function makeWithFallback($name, object $value): mixed + public static function makeWithFallback(string $name, object $value): ?self { return match (true) { $value instanceof Carbon => self::make($name, $value), @@ -24,6 +24,9 @@ public static function makeWithFallback($name, object $value): mixed }; } + /** + * @return array + */ public function values(): array { return [ diff --git a/src/DTO/Documents/DocumentIndex/IndexDateTimeDTO.php b/src/DTO/Documents/DocumentIndex/IndexDateTimeDTO.php index 3bc6d581..92067153 100644 --- a/src/DTO/Documents/DocumentIndex/IndexDateTimeDTO.php +++ b/src/DTO/Documents/DocumentIndex/IndexDateTimeDTO.php @@ -16,7 +16,7 @@ public static function make(string $name, null|Carbon|\Carbon\Carbon $value): se return new self($name, $value); } - public static function makeWithFallback($name, object $value): mixed + public static function makeWithFallback(string $name, object $value): ?self { return match (true) { $value instanceof Carbon => self::make($name, $value), @@ -24,6 +24,9 @@ public static function makeWithFallback($name, object $value): mixed }; } + /** + * @return array + */ public function values(): array { return [ diff --git a/src/DTO/Documents/DocumentIndex/IndexDecimalDTO.php b/src/DTO/Documents/DocumentIndex/IndexDecimalDTO.php index e1de1531..72876b66 100644 --- a/src/DTO/Documents/DocumentIndex/IndexDecimalDTO.php +++ b/src/DTO/Documents/DocumentIndex/IndexDecimalDTO.php @@ -14,6 +14,9 @@ public static function make(string $name, null|int|float $value): self return new self($name, $value); } + /** + * @return array + */ public function values(): array { return [ diff --git a/src/DTO/Documents/DocumentIndex/IndexDetectDTO.php b/src/DTO/Documents/DocumentIndex/IndexDetectDTO.php index 861bfc91..102f02c4 100644 --- a/src/DTO/Documents/DocumentIndex/IndexDetectDTO.php +++ b/src/DTO/Documents/DocumentIndex/IndexDetectDTO.php @@ -11,7 +11,7 @@ public function __construct( public mixed $value, ) {} - public static function make(string $name, mixed $value) + public static function make(string $name, mixed $value): IndexTextDTO|IndexNumericDTO|IndexDecimalDTO|IndexDateTimeDTO|null { return match (true) { is_string($value) => IndexTextDTO::make($name, $value), diff --git a/src/DTO/Documents/DocumentIndex/IndexKeywordDTO.php b/src/DTO/Documents/DocumentIndex/IndexKeywordDTO.php index 7b4f960e..62fffa4d 100644 --- a/src/DTO/Documents/DocumentIndex/IndexKeywordDTO.php +++ b/src/DTO/Documents/DocumentIndex/IndexKeywordDTO.php @@ -14,6 +14,9 @@ public static function make(string $name, ?string $value): self return new self($name, $value); } + /** + * @return array + */ public function values(): array { return [ diff --git a/src/DTO/Documents/DocumentIndex/IndexMemoDTO.php b/src/DTO/Documents/DocumentIndex/IndexMemoDTO.php index db8765a1..d59085dd 100644 --- a/src/DTO/Documents/DocumentIndex/IndexMemoDTO.php +++ b/src/DTO/Documents/DocumentIndex/IndexMemoDTO.php @@ -14,6 +14,9 @@ public static function make(string $name, ?string $value): self return new self($name, $value); } + /** + * @return array + */ public function values(): array { return [ diff --git a/src/DTO/Documents/DocumentIndex/IndexNumericDTO.php b/src/DTO/Documents/DocumentIndex/IndexNumericDTO.php index abd2b876..e0365f88 100644 --- a/src/DTO/Documents/DocumentIndex/IndexNumericDTO.php +++ b/src/DTO/Documents/DocumentIndex/IndexNumericDTO.php @@ -16,6 +16,9 @@ public static function make(string $name, ?int $value): self return new self($name, $value); } + /** + * @return array + */ public function values(): array { return [ diff --git a/src/DTO/Documents/DocumentIndex/IndexTableDTO.php b/src/DTO/Documents/DocumentIndex/IndexTableDTO.php index a6b9c321..b37272dd 100644 --- a/src/DTO/Documents/DocumentIndex/IndexTableDTO.php +++ b/src/DTO/Documents/DocumentIndex/IndexTableDTO.php @@ -6,16 +6,25 @@ class IndexTableDTO { + /** + * @param array|Collection|null $rows + */ public function __construct( public string $name, public null|Collection|array $rows, ) {} + /** + * @param array|Collection $rows + */ public static function make(string $name, Collection|array $rows): self { return new self($name, $rows); } + /** + * @return array + */ public function values(): array { return [ @@ -28,16 +37,34 @@ public function values(): array ]; } + /** + * @return list> + */ protected function rowsCollection(): array { - return collect($this->rows ?? [])->map(function ($row) { - return self::makeRowContent(collect($row)); - }) + $rows = $this->rows ?? []; + + $collection = $rows instanceof Collection + ? $rows + : collect($rows); + + return $collection + ->map(function (mixed $row): array { + $rowCollection = $row instanceof Collection + ? $row + : collect(is_array($row) ? $row : []); + + return self::makeRowContent($rowCollection); + }) ->filter() ->values() ->toArray(); } + /** + * @param Collection $indexes + * @return array>> + */ public static function makeRowContent(Collection $indexes): array { return [ diff --git a/src/DTO/Documents/DocumentIndex/IndexTextDTO.php b/src/DTO/Documents/DocumentIndex/IndexTextDTO.php index 8917b1ab..a144fba8 100644 --- a/src/DTO/Documents/DocumentIndex/IndexTextDTO.php +++ b/src/DTO/Documents/DocumentIndex/IndexTextDTO.php @@ -14,6 +14,9 @@ public static function make(string $name, ?string $value): self return new self($name, $value); } + /** + * @return array + */ public function values(): array { return [ diff --git a/src/DTO/Documents/DocumentIndex/PrepareDTO.php b/src/DTO/Documents/DocumentIndex/PrepareDTO.php index 356d4390..cfd245f1 100644 --- a/src/DTO/Documents/DocumentIndex/PrepareDTO.php +++ b/src/DTO/Documents/DocumentIndex/PrepareDTO.php @@ -6,6 +6,10 @@ class PrepareDTO { + /** + * @param Collection $indexes + * @return array + */ public static function makeFields(Collection $indexes): array { return [ @@ -16,6 +20,10 @@ public static function makeFields(Collection $indexes): array ]; } + /** + * @param Collection $indexes + * @return array + */ public static function makeField(Collection $indexes, bool $forceUpdate = false): array { return [ diff --git a/src/DTO/Documents/DocumentPaginator.php b/src/DTO/Documents/DocumentPaginator.php index 422e7862..2319f126 100644 --- a/src/DTO/Documents/DocumentPaginator.php +++ b/src/DTO/Documents/DocumentPaginator.php @@ -8,10 +8,13 @@ use Illuminate\Support\Collection; /** - * @property Collection|Document[] $documents + * @property Collection $documents */ class DocumentPaginator { + /** + * @param Collection $documents + */ public function __construct( public int $total, public int $per_page, @@ -43,6 +46,9 @@ public function failed(): bool return ! $this->successful(); } + /** + * @param array $data + */ public static function fromJson( array $data, int $page, @@ -56,7 +62,17 @@ public static function fromJson( $to = $page === $lastPage ? $total : $page * $perPage; - $documents = collect(Arr::get($data, 'Items'))->map(function (array $document) { + $itemsRaw = Arr::get($data, 'Items', []); + $itemList = []; + if (is_array($itemsRaw)) { + foreach (array_values($itemsRaw) as $item) { + if (is_array($item)) { + $itemList[] = $item; + } + } + } + + $documents = collect($itemList)->map(function (array $document) { return Document::fromJson($document); }); @@ -80,11 +96,14 @@ public static function fromFailed(Exception $e): self last_page: 0, from: 0, to: 0, - documents: collect(), + documents: new Collection, error: ErrorBag::make($e), ); } + /** + * @param Collection|null $documents + */ public static function fake( ?int $total = null, ?int $per_page = null, diff --git a/src/DTO/Documents/DocumentThumbnail.php b/src/DTO/Documents/DocumentThumbnail.php index 0a32d52c..1510a07b 100644 --- a/src/DTO/Documents/DocumentThumbnail.php +++ b/src/DTO/Documents/DocumentThumbnail.php @@ -6,6 +6,9 @@ final class DocumentThumbnail { + /** + * @param array $data + */ public static function fromData(array $data): self { $mime = Arr::get($data, 'mime'); diff --git a/src/DTO/Documents/DocumentsTrashBin/DeleteDocuments.php b/src/DTO/Documents/DocumentsTrashBin/DeleteDocuments.php index 9eebdc0e..1496c151 100644 --- a/src/DTO/Documents/DocumentsTrashBin/DeleteDocuments.php +++ b/src/DTO/Documents/DocumentsTrashBin/DeleteDocuments.php @@ -2,13 +2,18 @@ namespace CodebarAg\DocuWare\DTO\Documents\DocumentsTrashBin; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Arr; final class DeleteDocuments { + /** + * @param array $data + */ public static function fromData(array $data): self { - $failedItems = Arr::get($data, 'FailedItems'); + $failedRaw = Arr::get($data, 'FailedItems', []); + $failedItems = JsonArrays::listOfRecords(is_array($failedRaw) ? $failedRaw : []); $successCount = Arr::get($data, 'SuccessCount'); return new self( @@ -17,6 +22,9 @@ public static function fromData(array $data): self ); } + /** + * @param list> $failedItems + */ public function __construct( public array $failedItems = [], public int $successCount = 0, diff --git a/src/DTO/Documents/DocumentsTrashBin/RestoreDocuments.php b/src/DTO/Documents/DocumentsTrashBin/RestoreDocuments.php index d87bf877..3d15951c 100644 --- a/src/DTO/Documents/DocumentsTrashBin/RestoreDocuments.php +++ b/src/DTO/Documents/DocumentsTrashBin/RestoreDocuments.php @@ -2,13 +2,18 @@ namespace CodebarAg\DocuWare\DTO\Documents\DocumentsTrashBin; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Arr; final class RestoreDocuments { + /** + * @param array $data + */ public static function fromData(array $data): self { - $failedItems = Arr::get($data, 'FailedItems'); + $failedRaw = Arr::get($data, 'FailedItems', []); + $failedItems = JsonArrays::listOfRecords(is_array($failedRaw) ? $failedRaw : []); $successCount = Arr::get($data, 'SuccessCount'); return new self( @@ -17,6 +22,9 @@ public static function fromData(array $data): self ); } + /** + * @param list> $failedItems + */ public function __construct( public array $failedItems = [], public int $successCount = 0, diff --git a/src/DTO/Documents/Field.php b/src/DTO/Documents/Field.php index 0c8fc4e9..706f25b2 100644 --- a/src/DTO/Documents/Field.php +++ b/src/DTO/Documents/Field.php @@ -6,6 +6,9 @@ final class Field { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( diff --git a/src/DTO/Documents/TableRow.php b/src/DTO/Documents/TableRow.php index 9612b62b..079238b8 100644 --- a/src/DTO/Documents/TableRow.php +++ b/src/DTO/Documents/TableRow.php @@ -2,19 +2,27 @@ namespace CodebarAg\DocuWare\DTO\Documents; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; class TableRow { + /** + * @param array $data + */ public static function fromJson(array $data): self { - $fields = self::convertFields(collect($data)); + $fields = self::convertFields(collect(JsonArrays::listOfRecords($data))); return new self( fields: $fields, ); } + /** + * @param Collection> $fields + * @return Collection + */ protected static function convertFields(Collection $fields): Collection { return $fields->mapWithKeys(function (array $field) { @@ -22,10 +30,16 @@ protected static function convertFields(Collection $fields): Collection }); } + /** + * @param Collection $fields + */ public function __construct( public Collection $fields, ) {} + /** + * @param Collection|null $fields + */ public static function fake( ?Collection $fields = null, ): self { diff --git a/src/DTO/Documents/TrashDocumentPaginator.php b/src/DTO/Documents/TrashDocumentPaginator.php index c67dcd41..60399295 100644 --- a/src/DTO/Documents/TrashDocumentPaginator.php +++ b/src/DTO/Documents/TrashDocumentPaginator.php @@ -3,15 +3,21 @@ namespace CodebarAg\DocuWare\DTO\Documents; use CodebarAg\DocuWare\DTO\ErrorBag; +use CodebarAg\DocuWare\Support\JsonArrays; use Exception; use Illuminate\Support\Arr; use Illuminate\Support\Collection; /** - * @property Collection|Document[] $documents + * @property Collection> $documents */ class TrashDocumentPaginator { + /** + * @param Collection> $headers + * @param Collection> $documents + * @param Collection> $mappedDocuments + */ public function __construct( public int $total, public int $per_page, @@ -45,6 +51,9 @@ public function failed(): bool return ! $this->successful(); } + /** + * @param array $data + */ public static function fromJson( array $data, int $page, @@ -58,18 +67,25 @@ public static function fromJson( $to = $page === $lastPage ? $total : $page * $perPage; - $headers = collect(Arr::get($data, 'Headers')); - $documents = collect(Arr::get($data, 'Rows')); - - $mappedDocuments = $documents->map(function (array $document) use ($headers) { - $document = collect($document); - - return $document->mapWithKeys(function ($value, $key) use ($headers) { - $header = collect($headers->get($key)); - - return $header->has('FieldName') ? [$header->get('FieldName') => $value] : []; - })->filter(); - }); + $headersRaw = Arr::get($data, 'Headers', []); + $headerMap = []; + if (is_array($headersRaw)) { + foreach ($headersRaw as $key => $value) { + if (is_array($value)) { + $headerMap[(string) $key] = JsonArrays::associativeRow($value); + } + } + } + $headers = collect($headerMap); + + $rowsRaw = Arr::get($data, 'Rows', []); + $documents = collect(JsonArrays::listOfRecords(is_array($rowsRaw) ? $rowsRaw : [])); + + $mappedList = []; + foreach ($documents as $document) { + $mappedList[] = self::mapDocumentRowToFields($document, $headers); + } + $mappedDocuments = collect($mappedList); return new self( total: $total, @@ -84,6 +100,27 @@ public static function fromJson( ); } + /** + * @param array $document + * @param Collection> $headers + * @return Collection + */ + protected static function mapDocumentRowToFields(array $document, Collection $headers): Collection + { + $row = collect(JsonArrays::associativeRow($document)); + + return $row->mapWithKeys(function (mixed $value, int|string $key) use ($headers): array { + $headerRaw = $headers->get((string) $key); + $header = collect(is_array($headerRaw) ? JsonArrays::associativeRow($headerRaw) : []); + + $fieldName = $header->get('FieldName'); + + return $header->has('FieldName') && (is_string($fieldName) || is_int($fieldName)) + ? [(string) $fieldName => $value] + : []; + })->filter(); + } + public static function fromFailed(Exception $e): self { return new self( @@ -100,6 +137,11 @@ public static function fromFailed(Exception $e): self ); } + /** + * @param Collection>|null $headers + * @param Collection>|null $documents + * @param Collection>|null $mappedDocuments + */ public static function fake( ?int $total = null, ?int $per_page = null, @@ -118,9 +160,9 @@ public static function fake( last_page: $last_page ?? random_int(10, 20), from: $from ?? 1, to: $to ?? 10, - headers: $headers, - documents: $documents, - mappedDocuments: $mappedDocuments, + headers: $headers ?? collect(), + documents: $documents ?? collect(), + mappedDocuments: $mappedDocuments ?? collect(), ); } } diff --git a/src/DTO/FileCabinets/CheckoutToFileSystemResult.php b/src/DTO/FileCabinets/CheckoutToFileSystemResult.php new file mode 100644 index 00000000..7e8976b6 --- /dev/null +++ b/src/DTO/FileCabinets/CheckoutToFileSystemResult.php @@ -0,0 +1,29 @@ +> $links + */ + public function __construct( + public array $links, + ) {} + + public static function fromResponse(Response $response): self + { + event(new DocuWareResponseLog($response)); + + EnsureValidResponse::from($response); + + $raw = $response->throw()->json('Links'); + + return new self(JsonArrays::listOfRecords($raw)); + } +} diff --git a/src/DTO/FileCabinets/Dialog.php b/src/DTO/FileCabinets/Dialog.php index 9e4c3c6a..32a88556 100644 --- a/src/DTO/FileCabinets/Dialog.php +++ b/src/DTO/FileCabinets/Dialog.php @@ -2,23 +2,36 @@ namespace CodebarAg\DocuWare\DTO\FileCabinets; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Arr; use Illuminate\Support\Str; final class Dialog { + /** + * @param array $data + */ public static function fromJson(array $data): self { + $fieldsRaw = Arr::get($data, 'Fields'); + $fields = null; + if (is_array($fieldsRaw)) { + $fields = JsonArrays::listOfRecords($fieldsRaw); + } + return new self( id: Arr::get($data, 'Id'), type: Arr::get($data, 'Type'), label: Arr::get($data, 'DisplayName'), isDefault: Arr::get($data, 'IsDefault'), fileCabinetId: Arr::get($data, 'FileCabinetId'), - fields: Arr::get($data, 'Fields'), + fields: $fields, ); } + /** + * @param list>|null $fields + */ public function __construct( public string $id, public string $type, diff --git a/src/DTO/FileCabinets/General/FileCabinetInformation.php b/src/DTO/FileCabinets/General/FileCabinetInformation.php index 242d2b23..c0d8ed12 100644 --- a/src/DTO/FileCabinets/General/FileCabinetInformation.php +++ b/src/DTO/FileCabinets/General/FileCabinetInformation.php @@ -7,6 +7,9 @@ final class FileCabinetInformation { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( diff --git a/src/DTO/General/Organization/FileCabinet.php b/src/DTO/General/Organization/FileCabinet.php index 0e6b9736..4b7b504d 100644 --- a/src/DTO/General/Organization/FileCabinet.php +++ b/src/DTO/General/Organization/FileCabinet.php @@ -7,6 +7,9 @@ final class FileCabinet { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( diff --git a/src/DTO/General/Organization/Organization.php b/src/DTO/General/Organization/Organization.php index 26643bc9..13ed220d 100644 --- a/src/DTO/General/Organization/Organization.php +++ b/src/DTO/General/Organization/Organization.php @@ -7,6 +7,9 @@ final class Organization { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( @@ -18,6 +21,10 @@ public static function fromJson(array $data): self ); } + /** + * @param array $additionalInfo + * @param array $configurationRights + */ public function __construct( public string $id, public string $name, @@ -26,6 +33,10 @@ public function __construct( public array $configurationRights = [], ) {} + /** + * @param array $additionalInfo + * @param array $configurationRights + */ public static function fake( ?string $id = null, ?string $name = null, diff --git a/src/DTO/General/Organization/OrganizationIndex.php b/src/DTO/General/Organization/OrganizationIndex.php index 71a58dbb..2b745994 100644 --- a/src/DTO/General/Organization/OrganizationIndex.php +++ b/src/DTO/General/Organization/OrganizationIndex.php @@ -7,6 +7,9 @@ final class OrganizationIndex { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( diff --git a/src/DTO/General/UserManagement/CreateUpdateUser/User.php b/src/DTO/General/UserManagement/CreateUpdateUser/User.php index dd0e1add..4a6840bc 100644 --- a/src/DTO/General/UserManagement/CreateUpdateUser/User.php +++ b/src/DTO/General/UserManagement/CreateUpdateUser/User.php @@ -6,6 +6,9 @@ final class User { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( diff --git a/src/DTO/General/UserManagement/GetModifyGroups/Group.php b/src/DTO/General/UserManagement/GetModifyGroups/Group.php index f37e0927..0df7768d 100644 --- a/src/DTO/General/UserManagement/GetModifyGroups/Group.php +++ b/src/DTO/General/UserManagement/GetModifyGroups/Group.php @@ -6,6 +6,9 @@ final class Group { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( diff --git a/src/DTO/General/UserManagement/GetModifyRoles/Role.php b/src/DTO/General/UserManagement/GetModifyRoles/Role.php index 6eac160f..5ef7a3b2 100644 --- a/src/DTO/General/UserManagement/GetModifyRoles/Role.php +++ b/src/DTO/General/UserManagement/GetModifyRoles/Role.php @@ -6,6 +6,9 @@ final class Role { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( diff --git a/src/DTO/General/UserManagement/GetUsers/OutOfOffice.php b/src/DTO/General/UserManagement/GetUsers/OutOfOffice.php index 8aeb77a4..7f159cbd 100644 --- a/src/DTO/General/UserManagement/GetUsers/OutOfOffice.php +++ b/src/DTO/General/UserManagement/GetUsers/OutOfOffice.php @@ -8,6 +8,9 @@ final class OutOfOffice { + /** + * @param array $data + */ public static function fromJson(array $data): self { $startDateTime = Arr::get($data, 'StartDateTime'); diff --git a/src/DTO/General/UserManagement/GetUsers/RegionalSettings.php b/src/DTO/General/UserManagement/GetUsers/RegionalSettings.php index c926ee80..904ac32b 100644 --- a/src/DTO/General/UserManagement/GetUsers/RegionalSettings.php +++ b/src/DTO/General/UserManagement/GetUsers/RegionalSettings.php @@ -6,6 +6,9 @@ final class RegionalSettings { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( diff --git a/src/DTO/General/UserManagement/GetUsers/User.php b/src/DTO/General/UserManagement/GetUsers/User.php index f2d3e65a..c4dec673 100644 --- a/src/DTO/General/UserManagement/GetUsers/User.php +++ b/src/DTO/General/UserManagement/GetUsers/User.php @@ -7,6 +7,9 @@ final class User { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( diff --git a/src/DTO/Section.php b/src/DTO/Section.php index 49c554b2..0c2b7de9 100644 --- a/src/DTO/Section.php +++ b/src/DTO/Section.php @@ -8,6 +8,9 @@ final class Section { + /** + * @param array $data + */ public static function fromJson(array $data): self { if ($contentModifiedDateTime = Arr::get($data, 'ContentModified')) { diff --git a/src/DTO/SuggestionField.php b/src/DTO/SuggestionField.php index 6e0a11ee..a9510c5c 100644 --- a/src/DTO/SuggestionField.php +++ b/src/DTO/SuggestionField.php @@ -6,6 +6,9 @@ final class SuggestionField { + /** + * @param array $data + */ public static function fromJson(array $data): self { return new self( @@ -16,6 +19,9 @@ public static function fromJson(array $data): self ); } + /** + * @param array $value + */ public function __construct( public array $value, public ?string $name, @@ -23,6 +29,9 @@ public function __construct( public ?string $confidence, ) {} + /** + * @param array $value + */ public static function fake( array $value = [], ?string $name = null, diff --git a/src/DTO/Textshot.php b/src/DTO/Textshot.php index 91a2f386..1949a203 100644 --- a/src/DTO/Textshot.php +++ b/src/DTO/Textshot.php @@ -2,14 +2,18 @@ namespace CodebarAg\DocuWare\DTO; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Arr; use Illuminate\Support\Collection; final class Textshot { + /** + * @param array $data + */ public static function fromJson(array $data): self { - $pages = collect(Arr::get($data, 'Pages', [])); + $pages = collect(JsonArrays::listOfRecords(Arr::get($data, 'Pages', []))); return new self( page_count: $pages->count(), @@ -17,6 +21,9 @@ public static function fromJson(array $data): self ); } + /** + * @param Collection $pages + */ public function __construct( public int $page_count, public Collection $pages, diff --git a/src/DTO/TextshotPage.php b/src/DTO/TextshotPage.php index 543f3d64..bf697d7f 100644 --- a/src/DTO/TextshotPage.php +++ b/src/DTO/TextshotPage.php @@ -2,23 +2,31 @@ namespace CodebarAg\DocuWare\DTO; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Arr; use Illuminate\Support\Collection; final class TextshotPage { + /** + * @param Collection> $collection + * @return Collection + */ public static function fromCollection(Collection $collection): Collection { return $collection->map(fn (array $data) => self::fromJson($data)); } + /** + * @param array $data + */ public static function fromJson(array $data): self { $rawItems = Arr::get($data, 'Items', []); return new self( language: Arr::get($data, 'Lang'), - content: self::content($rawItems) + content: self::content(JsonArrays::listOfRecords(is_array($rawItems) ? $rawItems : [])) ); } @@ -27,19 +35,22 @@ public function __construct( public string $content, ) {} + /** + * @param list> $rawItems + */ protected static function content(array $rawItems): string { return collect($rawItems) - ->filter(function ($item) { + ->filter(function (mixed $item) { return Arr::get($item, '$type') === 'TextZone'; }) ->pluck('Ln') ->flatten(2) - ->filter(function ($item) { + ->filter(function (mixed $item) { return is_array($item); }) ->flatten(1) - ->map(function ($item) { + ->map(function (mixed $item) { $type = Arr::get($item, '$type'); diff --git a/src/DTO/Workflow/HistoryStep.php b/src/DTO/Workflow/HistoryStep.php index 20a832ad..d3a3dc4a 100644 --- a/src/DTO/Workflow/HistoryStep.php +++ b/src/DTO/Workflow/HistoryStep.php @@ -2,6 +2,7 @@ namespace CodebarAg\DocuWare\DTO\Workflow; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Arr; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; @@ -9,6 +10,9 @@ final class HistoryStep { + /** + * @param array $data + */ public static function fromJson(array $data): self { if ($stepDateTime = Arr::get($data, 'StepDate')) { @@ -16,8 +20,17 @@ public static function fromJson(array $data): self $stepDateTime = Carbon::createFromTimestamp($stepDateTime); } + $itemRaw = Arr::get($data, 'Info.Item'); + $rows = []; + if (is_array($itemRaw)) { + $rows = array_is_list($itemRaw) + ? JsonArrays::listOfRecords($itemRaw) + : [JsonArrays::associativeRow($itemRaw)]; + } + $infoItem = collect($rows); + return new self( - infoItem: collect(Arr::get($data, 'Info.Item')), + infoItem: $infoItem, stepNumber: Arr::get($data, 'StepNumber'), stepDate: $stepDateTime, activityName: Arr::get($data, 'ActivityName'), @@ -26,6 +39,9 @@ public static function fromJson(array $data): self ); } + /** + * @param Collection> $infoItem + */ public function __construct( public Collection $infoItem, public int $stepNumber, diff --git a/src/DTO/Workflow/InstanceHistory.php b/src/DTO/Workflow/InstanceHistory.php index 3ae14e0f..69fe1331 100644 --- a/src/DTO/Workflow/InstanceHistory.php +++ b/src/DTO/Workflow/InstanceHistory.php @@ -2,6 +2,7 @@ namespace CodebarAg\DocuWare\DTO\Workflow; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Arr; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; @@ -9,6 +10,9 @@ final class InstanceHistory { + /** + * @param array $data + */ public static function fromJson(array $data): self { if ($startDateTime = Arr::get($data, 'StartedAt')) { @@ -16,8 +20,11 @@ public static function fromJson(array $data): self $startDateTime = Carbon::createFromTimestamp($startDateTime); } - if ($historySteps = Arr::get($data, 'HistorySteps')) { - $historySteps = collect($historySteps)->map(fn (array $historyStep) => HistoryStep::fromJson($historyStep)); + $historySteps = null; + $stepsRaw = Arr::get($data, 'HistorySteps'); + if (is_array($stepsRaw)) { + $historySteps = collect(JsonArrays::listOfRecords($stepsRaw)) + ->map(fn (array $historyStep) => HistoryStep::fromJson($historyStep)); } return new self( @@ -32,6 +39,9 @@ public static function fromJson(array $data): self ); } + /** + * @param Collection|null $historySteps + */ public function __construct( public string $id, public string $workflowId, diff --git a/src/DocuWareSearchRequestBuilder.php b/src/DocuWareSearchRequestBuilder.php index 0e70ee76..6ea14a34 100644 --- a/src/DocuWareSearchRequestBuilder.php +++ b/src/DocuWareSearchRequestBuilder.php @@ -6,6 +6,7 @@ use CodebarAg\DocuWare\Exceptions\UnableToSearch; use CodebarAg\DocuWare\Requests\Documents\DocumentsTrashBin\GetDocuments; use CodebarAg\DocuWare\Requests\Search\GetSearchRequest; +use Illuminate\Support\Collection; use Illuminate\Support\Str; use Saloon\Exceptions\InvalidResponseClassException; use Saloon\Exceptions\PendingRequestException; @@ -16,6 +17,7 @@ class DocuWareSearchRequestBuilder protected ?string $dialogId = null; + /** @var list */ protected array $additionalFileCabinetIds = []; protected int $page = 1; @@ -28,8 +30,10 @@ class DocuWareSearchRequestBuilder protected string $orderDirection = 'asc'; + /** @var array> */ protected array $filters = []; + /** @var array> */ protected array $usedDateOperators = []; protected bool $trashBin = false; @@ -48,6 +52,9 @@ public function fileCabinet(string $fileCabinetId): self return $this; } + /** + * @param list $fileCabinetIds + */ public function fileCabinets(array $fileCabinetIds): self { $this->fileCabinetId = $fileCabinetIds[0] ?? null; @@ -93,14 +100,13 @@ public function fulltext(?string $searchTerm): self return $this; } - public function filterDate(string $name, string $operator, ?Carbon $date): self + public function filterDate(string $name, string $operator, Carbon $date): self { $date = $this->exactDateTime($date, $operator); $this->makeSureFilterDateRangeIsCorrect($name, $operator); $this->filters[$name][] = $date; - $this->filters[$name] = array_values($this->filters[$name]); return $this; } @@ -140,11 +146,17 @@ public function filterIn(string $name, mixed $values): self return $this->filter($name, $values); } - $values = collect($values)->map(function ($value) { + $list = match (true) { + is_array($values) => array_values($values), + $values instanceof Collection => $values->values()->all(), + default => [], + }; + + $prepared = collect($list)->map(function (mixed $value) { return self::prepareValueForFilter($value); })->toArray(); - $this->filters[$name][] = implode(' OR ', $values); + $this->filters[$name][] = implode(' OR ', $prepared); return $this; } @@ -250,7 +262,7 @@ private function restructureMonoDateFilterRange(): void } } - private function makeSureFilterDateRangeIsCorrect($name, $operator): void + private function makeSureFilterDateRangeIsCorrect(string $name, string $operator): void { if (isset($this->usedDateOperators[$name])) { if ($operatorFilterIndex = array_search($operator, $this->usedDateOperators[$name])) { @@ -270,7 +282,7 @@ private function makeSureFilterDateRangeIsCorrect($name, $operator): void } } - private function exactDateTime($date, $operator): Carbon + private function exactDateTime(Carbon $date, string $operator): Carbon { return match ($operator) { '<', '>=' => $date->startOfDay(), diff --git a/src/DocuWareUrl.php b/src/DocuWareUrl.php index be682d9a..cedda30a 100644 --- a/src/DocuWareUrl.php +++ b/src/DocuWareUrl.php @@ -96,9 +96,12 @@ public function make(): string iv: $iv, ); + $platform = trim(config('laravel-docuware.platform_path', 'DocuWare/Platform'), '/'); + return sprintf( - '%s/DocuWare/Platform/WebClient/Integration?ep=%s', - $this->url, + '%s/%s/WebClient/Integration?ep=%s', + rtrim($this->url, '/'), + $platform, URL::format($encrypted), ); } diff --git a/src/Facades/DocuWare.php b/src/Facades/DocuWare.php index cc08cb89..edf46ef1 100644 --- a/src/Facades/DocuWare.php +++ b/src/Facades/DocuWare.php @@ -21,19 +21,19 @@ * @method static string login() * @method static void logout() * @method static Organization getOrganization(string $organizationId) - * @method static Collection|OrganizationIndex[] getOrganizations() - * @method static Collection|FileCabinetInformation[] getFileCabinets() - * @method static Collection|Field[] getFields(string $fileCabinetId) - * @method static Collection|Dialog[] getDialogs(string $fileCabinetId) - * @method static array getSelectList(string $fileCabinetId, string $dialogId, string $fieldName) + * @method static Collection getOrganizations() + * @method static Collection getFileCabinets() + * @method static Collection getFields(string $fileCabinetId) + * @method static Collection getDialogs(string $fileCabinetId) + * @method static array getSelectList(string $fileCabinetId, string $dialogId, string $fieldName) * @method static Document getDocument(string $fileCabinetId, int $documentId) * @method static string getDocumentPreview(string $fileCabinetId, int $documentId) * @method static string downloadDocument(string $fileCabinetId, int $documentId) - * @method static string downloadDocuments(string $fileCabinetId, array $documentIds) - * @method DocumentThumbnail downloadDocumentThumbnail(string $fileCabinetId, int $documentId, int $section, int $page = 0) + * @method static string downloadDocuments(string $fileCabinetId, list $documentIds) + * @method static DocumentThumbnail downloadDocumentThumbnail(string $fileCabinetId, int $documentId, int $section, int $page = 0) * @method static null|int|float|Carbon|string updateDocumentValue(string $fileCabinetId, int $documentId, string $fieldName, string $newValue, bool $forceUpdate = false) - * @method static null|int|float|Carbon|string updateDocumentValues(string $fileCabinetId, int $documentId, array $values, bool $forceUpdate = false) - * @method static Document uploadDocument(string $fileCabinetId, string $fileContent, string $fileName, ?Collection $indexes = null) + * @method static null|int|float|Carbon|string updateDocumentValues(string $fileCabinetId, int $documentId, array $values, bool $forceUpdate = false) + * @method static Document uploadDocument(string $fileCabinetId, string $fileContent, string $fileName, ?Collection $indexes = null) * @method static int documentCount(string $fileCabinetId, string $dialogId) * @method static void deleteDocument(string $fileCabinetId, int $documentId) * @method static DocuWareSearchRequestBuilder search() diff --git a/src/Requests/Authentication/OAuth/GetResponsibleIdentityService.php b/src/Requests/Authentication/OAuth/GetResponsibleIdentityService.php index e82fcb0a..1c94682b 100644 --- a/src/Requests/Authentication/OAuth/GetResponsibleIdentityService.php +++ b/src/Requests/Authentication/OAuth/GetResponsibleIdentityService.php @@ -25,7 +25,8 @@ public function __construct( public function resolveEndpoint(): string { $url = $this->url ?? config('laravel-docuware.credentials.url'); - $base = $url.'/DocuWare/Platform'; + $platform = trim(config('laravel-docuware.platform_path', 'DocuWare/Platform'), '/'); + $base = rtrim($url, '/').'/'.$platform; return $base.'/Home/IdentityServiceInfo'; } diff --git a/src/Requests/Authentication/OAuth/RequestTokenWithCredentials.php b/src/Requests/Authentication/OAuth/RequestTokenWithCredentials.php index 01bd572d..6b5827a3 100644 --- a/src/Requests/Authentication/OAuth/RequestTokenWithCredentials.php +++ b/src/Requests/Authentication/OAuth/RequestTokenWithCredentials.php @@ -36,6 +36,9 @@ public function defaultHeaders(): array ]; } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Authentication/OAuth/RequestTokenWithCredentialsTrustedUser.php b/src/Requests/Authentication/OAuth/RequestTokenWithCredentialsTrustedUser.php index ef4d65f6..8a11d50e 100644 --- a/src/Requests/Authentication/OAuth/RequestTokenWithCredentialsTrustedUser.php +++ b/src/Requests/Authentication/OAuth/RequestTokenWithCredentialsTrustedUser.php @@ -37,6 +37,9 @@ public function defaultHeaders(): array ]; } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Documents/ApplicationProperties/AddApplicationProperties.php b/src/Requests/Documents/ApplicationProperties/AddApplicationProperties.php index 40fd9b7b..dfb7db96 100644 --- a/src/Requests/Documents/ApplicationProperties/AddApplicationProperties.php +++ b/src/Requests/Documents/ApplicationProperties/AddApplicationProperties.php @@ -20,6 +20,9 @@ class AddApplicationProperties extends Request implements Cacheable, HasBody protected Method $method = Method::POST; + /** + * @param list> $properties + */ public function __construct( protected readonly string $fileCabinetId, protected readonly string $documentId, @@ -31,7 +34,10 @@ public function resolveEndpoint(): string return '/FileCabinets/'.$this->fileCabinetId.'/Documents/'.$this->documentId.'/DocumentApplicationProperties'; } - public function defaultBody() + /** + * @return array + */ + public function defaultBody(): array { return [ 'DocumentApplicationProperty' => $this->properties, diff --git a/src/Requests/Documents/ApplicationProperties/DeleteApplicationProperties.php b/src/Requests/Documents/ApplicationProperties/DeleteApplicationProperties.php index 67d1c4f6..5747159b 100644 --- a/src/Requests/Documents/ApplicationProperties/DeleteApplicationProperties.php +++ b/src/Requests/Documents/ApplicationProperties/DeleteApplicationProperties.php @@ -20,6 +20,9 @@ class DeleteApplicationProperties extends Request implements Cacheable, HasBody protected Method $method = Method::POST; + /** + * @param list $propertyNames + */ public function __construct( protected readonly string $fileCabinetId, protected readonly string $documentId, @@ -31,9 +34,12 @@ public function resolveEndpoint(): string return '/FileCabinets/'.$this->fileCabinetId.'/Documents/'.$this->documentId.'/DocumentApplicationProperties'; } - public function defaultBody() + /** + * @return array + */ + public function defaultBody(): array { - $props = collect($this->propertyNames)->map(function ($name) { + $props = collect($this->propertyNames)->map(function (string $name) { return [ 'Name' => $name, 'Value' => null, diff --git a/src/Requests/Documents/ApplicationProperties/UpdateApplicationProperties.php b/src/Requests/Documents/ApplicationProperties/UpdateApplicationProperties.php index 44ac8039..63259b18 100644 --- a/src/Requests/Documents/ApplicationProperties/UpdateApplicationProperties.php +++ b/src/Requests/Documents/ApplicationProperties/UpdateApplicationProperties.php @@ -20,6 +20,9 @@ class UpdateApplicationProperties extends Request implements Cacheable, HasBody protected Method $method = Method::POST; + /** + * @param list> $properties + */ public function __construct( protected readonly string $fileCabinetId, protected readonly string $documentId, @@ -31,7 +34,10 @@ public function resolveEndpoint(): string return '/FileCabinets/'.$this->fileCabinetId.'/Documents/'.$this->documentId.'/DocumentApplicationProperties'; } - public function defaultBody() + /** + * @return array + */ + public function defaultBody(): array { return [ 'DocumentApplicationProperty' => $this->properties, diff --git a/src/Requests/Documents/ClipUnclipStapleUnstaple/Clip.php b/src/Requests/Documents/ClipUnclipStapleUnstaple/Clip.php index 52cd9f52..ac8d6777 100644 --- a/src/Requests/Documents/ClipUnclipStapleUnstaple/Clip.php +++ b/src/Requests/Documents/ClipUnclipStapleUnstaple/Clip.php @@ -16,6 +16,9 @@ class Clip extends Request implements HasBody protected Method $method = Method::POST; + /** + * @param list> $documents + */ public function __construct( protected readonly string $documentTrayId, protected readonly array $documents, @@ -27,6 +30,9 @@ public function resolveEndpoint(): string return '/FileCabinets/'.$this->documentTrayId.'/Operations/ContentMerge'; } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Documents/ClipUnclipStapleUnstaple/Staple.php b/src/Requests/Documents/ClipUnclipStapleUnstaple/Staple.php index f3f86651..8522833f 100644 --- a/src/Requests/Documents/ClipUnclipStapleUnstaple/Staple.php +++ b/src/Requests/Documents/ClipUnclipStapleUnstaple/Staple.php @@ -16,6 +16,9 @@ class Staple extends Request implements HasBody protected Method $method = Method::POST; + /** + * @param list> $documents + */ public function __construct( protected readonly string $documentTrayId, protected readonly array $documents, @@ -27,6 +30,9 @@ public function resolveEndpoint(): string return '/FileCabinets/'.$this->documentTrayId.'/Operations/ContentMerge'; } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Documents/ClipUnclipStapleUnstaple/Unclip.php b/src/Requests/Documents/ClipUnclipStapleUnstaple/Unclip.php index 352df770..6f392000 100644 --- a/src/Requests/Documents/ClipUnclipStapleUnstaple/Unclip.php +++ b/src/Requests/Documents/ClipUnclipStapleUnstaple/Unclip.php @@ -33,6 +33,9 @@ public function defaultQuery(): array ]; } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Documents/ClipUnclipStapleUnstaple/Unstaple.php b/src/Requests/Documents/ClipUnclipStapleUnstaple/Unstaple.php index 7d4f861c..98b166ee 100644 --- a/src/Requests/Documents/ClipUnclipStapleUnstaple/Unstaple.php +++ b/src/Requests/Documents/ClipUnclipStapleUnstaple/Unstaple.php @@ -33,6 +33,9 @@ public function defaultQuery(): array ]; } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Documents/DocumentsTrashBin/DeleteDocuments.php b/src/Requests/Documents/DocumentsTrashBin/DeleteDocuments.php index e935c1e3..b2e62689 100644 --- a/src/Requests/Documents/DocumentsTrashBin/DeleteDocuments.php +++ b/src/Requests/Documents/DocumentsTrashBin/DeleteDocuments.php @@ -17,6 +17,9 @@ class DeleteDocuments extends Request implements HasBody protected Method $method = Method::POST; + /** + * @param array|Collection $ids + */ public function __construct( protected readonly array|Collection $ids = [], ) {} @@ -26,6 +29,9 @@ public function resolveEndpoint(): string return '/TrashBin/BatchDelete'; } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Documents/DocumentsTrashBin/GetDocuments.php b/src/Requests/Documents/DocumentsTrashBin/GetDocuments.php index 71466142..61f32198 100644 --- a/src/Requests/Documents/DocumentsTrashBin/GetDocuments.php +++ b/src/Requests/Documents/DocumentsTrashBin/GetDocuments.php @@ -21,6 +21,9 @@ class GetDocuments extends Request implements Cacheable, HasBody protected Method $method = Method::POST; + /** + * @param array $condition + */ public function __construct( protected readonly int $page = 1, protected readonly int $perPage = 50, @@ -46,6 +49,9 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Documents/DocumentsTrashBin/RestoreDocuments.php b/src/Requests/Documents/DocumentsTrashBin/RestoreDocuments.php index 33b29adc..2415a6ca 100644 --- a/src/Requests/Documents/DocumentsTrashBin/RestoreDocuments.php +++ b/src/Requests/Documents/DocumentsTrashBin/RestoreDocuments.php @@ -17,6 +17,9 @@ class RestoreDocuments extends Request implements HasBody protected Method $method = Method::POST; + /** + * @param array|Collection $ids + */ public function __construct( protected readonly array|Collection $ids = [], ) {} @@ -26,6 +29,9 @@ public function resolveEndpoint(): string return '/TrashBin/BatchRestore'; } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Documents/ModifyDocuments/TransferDocument.php b/src/Requests/Documents/ModifyDocuments/TransferDocument.php index b80a2a96..f6d7b7c4 100644 --- a/src/Requests/Documents/ModifyDocuments/TransferDocument.php +++ b/src/Requests/Documents/ModifyDocuments/TransferDocument.php @@ -2,9 +2,17 @@ namespace CodebarAg\DocuWare\Requests\Documents\ModifyDocuments; -use Arr; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexDateDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexDateTimeDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexDecimalDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexKeywordDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexMemoDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexNumericDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexTableDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexTextDTO; use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\PrepareDTO; use CodebarAg\DocuWare\Responses\Documents\ModifyDocuments\TransferDocumentResponse; +use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Saloon\Contracts\Body\HasBody; use Saloon\Enums\Method; @@ -18,6 +26,9 @@ class TransferDocument extends Request implements HasBody protected Method $method = Method::POST; + /** + * @param Collection|null $fields + */ public function __construct( protected readonly string $fileCabinetId, protected readonly string $destinationFileCabinetId, @@ -49,6 +60,9 @@ protected function defaultHeaders(): array ]; } + /** + * @return array + */ protected function defaultBody(): array { $body = [ diff --git a/src/Requests/Documents/Sections/GetAllSectionsFromADocument.php b/src/Requests/Documents/Sections/GetAllSectionsFromADocument.php index eb106e3b..b8a9e22b 100644 --- a/src/Requests/Documents/Sections/GetAllSectionsFromADocument.php +++ b/src/Requests/Documents/Sections/GetAllSectionsFromADocument.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\Documents\Sections; +use CodebarAg\DocuWare\DTO\Section; use CodebarAg\DocuWare\Responses\Documents\Sections\GetAllSectionsFromADocumentResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -46,7 +46,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Collection|Enumerable + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetAllSectionsFromADocumentResponse::fromResponse($response); } diff --git a/src/Requests/Documents/Stamps/AddDocumentAnnotations.php b/src/Requests/Documents/Stamps/AddDocumentAnnotations.php new file mode 100644 index 00000000..10fa2e45 --- /dev/null +++ b/src/Requests/Documents/Stamps/AddDocumentAnnotations.php @@ -0,0 +1,58 @@ + $payload e.g. ["Annotations" => [...]] + */ + public function __construct( + protected readonly string $fileCabinetId, + protected readonly int|string $documentId, + protected readonly array $payload, + ) {} + + public function resolveEndpoint(): string + { + return '/FileCabinets/'.$this->fileCabinetId.'/Documents/'.$this->documentId.'/Annotation'; + } + + /** + * @return array + */ + protected function defaultBody(): array + { + return $this->payload; + } + + /** + * @return array + */ + public function createDtoFromResponse(Response $response): array + { + event(new DocuWareResponseLog($response)); + + EnsureValidResponse::from($response); + + /** @var array $json */ + $json = $response->throw()->json(); + + return $json; + } +} diff --git a/src/Requests/Documents/Stamps/GetStamps.php b/src/Requests/Documents/Stamps/GetStamps.php new file mode 100644 index 00000000..a9203390 --- /dev/null +++ b/src/Requests/Documents/Stamps/GetStamps.php @@ -0,0 +1,39 @@ +fileCabinetId.'/Stamps'; + } + + /** + * @return Collection> + */ + public function createDtoFromResponse(Response $response): Collection + { + event(new DocuWareResponseLog($response)); + + EnsureValidResponse::from($response); + + $raw = $response->throw()->json('Stamp'); + + return collect(JsonArrays::listOfRecords($raw)); + } +} diff --git a/src/Requests/Documents/UpdateIndexValues/UpdateIndexValues.php b/src/Requests/Documents/UpdateIndexValues/UpdateIndexValues.php index add916dc..512188c9 100644 --- a/src/Requests/Documents/UpdateIndexValues/UpdateIndexValues.php +++ b/src/Requests/Documents/UpdateIndexValues/UpdateIndexValues.php @@ -2,6 +2,14 @@ namespace CodebarAg\DocuWare\Requests\Documents\UpdateIndexValues; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexDateDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexDateTimeDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexDecimalDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexKeywordDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexMemoDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexNumericDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexTableDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexTextDTO; use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\PrepareDTO; use CodebarAg\DocuWare\Responses\Documents\UpdateIndexValues\UpdateIndexValuesResponse; use Illuminate\Support\Collection; @@ -17,6 +25,9 @@ class UpdateIndexValues extends Request implements HasBody protected Method $method = Method::PUT; + /** + * @param Collection|null $indexes + */ public function __construct( protected readonly string $fileCabinetId, protected readonly string $documentId, @@ -29,6 +40,9 @@ public function resolveEndpoint(): string return '/FileCabinets/'.$this->fileCabinetId.'/Documents/'.$this->documentId.'/Fields'; } + /** + * @return array + */ public function defaultBody(): array { $body = []; @@ -43,6 +57,9 @@ public function defaultBody(): array } + /** + * @return Collection + */ public function createDtoFromResponse(Response $response): Collection { return UpdateIndexValuesResponse::fromResponse($response); diff --git a/src/Requests/Fields/GetFieldsRequest.php b/src/Requests/Fields/GetFieldsRequest.php index 614b9e10..7fc42b73 100644 --- a/src/Requests/Fields/GetFieldsRequest.php +++ b/src/Requests/Fields/GetFieldsRequest.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\Fields; +use CodebarAg\DocuWare\DTO\Documents\Field; use CodebarAg\DocuWare\Responses\Fields\GetFieldsResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -38,7 +38,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Collection|Enumerable + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetFieldsResponse::fromResponse($response); } diff --git a/src/Requests/FileCabinets/Batch/BatchDocumentsUpdateFields.php b/src/Requests/FileCabinets/Batch/BatchDocumentsUpdateFields.php new file mode 100644 index 00000000..1b8d8179 --- /dev/null +++ b/src/Requests/FileCabinets/Batch/BatchDocumentsUpdateFields.php @@ -0,0 +1,61 @@ + + */ +final class BatchDocumentsUpdateFields extends Request implements HasBody +{ + use HasJsonBody; + + protected Method $method = Method::POST; + + /** + * @param array $payload + */ + public function __construct( + protected readonly string $fileCabinetId, + protected readonly array $payload, + ) {} + + public function resolveEndpoint(): string + { + return '/FileCabinets/'.$this->fileCabinetId.'/Operations/BatchDocumentsUpdateFields'; + } + + /** + * @return array + */ + protected function defaultBody(): array + { + return $this->payload; + } + + /** + * @return array + */ + public function createDtoFromResponse(Response $response): array + { + event(new DocuWareResponseLog($response)); + + EnsureValidResponse::from($response); + + /** @var array $json */ + $json = $response->throw()->json(); + + return $json; + } +} diff --git a/src/Requests/FileCabinets/CheckInCheckOut/CheckInDocumentFromFileSystem.php b/src/Requests/FileCabinets/CheckInCheckOut/CheckInDocumentFromFileSystem.php new file mode 100644 index 00000000..20812c40 --- /dev/null +++ b/src/Requests/FileCabinets/CheckInCheckOut/CheckInDocumentFromFileSystem.php @@ -0,0 +1,54 @@ +fileCabinetId.'/Documents/'.$this->documentId.'/CheckInFromFileSystem'; + } + + /** + * @return list + */ + protected function defaultBody(): array + { + return [ + new MultipartValue(name: 'CheckIn', value: $this->checkInJson, filename: 'CheckIn.json'), + new MultipartValue(name: 'File[]', value: $this->fileContent, filename: $this->fileName), + ]; + } + + public function createDtoFromResponse(Response $response): Document + { + return GetASpecificDocumentFromAFileCabinetResponse::fromResponse($response); + } +} diff --git a/src/Requests/FileCabinets/CheckInCheckOut/CheckoutDocumentToFileSystem.php b/src/Requests/FileCabinets/CheckInCheckOut/CheckoutDocumentToFileSystem.php new file mode 100644 index 00000000..8e72bb75 --- /dev/null +++ b/src/Requests/FileCabinets/CheckInCheckOut/CheckoutDocumentToFileSystem.php @@ -0,0 +1,28 @@ +fileCabinetId.'/Documents/'.$this->documentId.'/CheckoutToFileSystem'; + } + + public function createDtoFromResponse(Response $response): CheckoutToFileSystemResult + { + return CheckoutToFileSystemResult::fromResponse($response); + } +} diff --git a/src/Requests/FileCabinets/CheckInCheckOut/UndoDocumentCheckout.php b/src/Requests/FileCabinets/CheckInCheckOut/UndoDocumentCheckout.php new file mode 100644 index 00000000..5feeb36b --- /dev/null +++ b/src/Requests/FileCabinets/CheckInCheckOut/UndoDocumentCheckout.php @@ -0,0 +1,43 @@ +fileCabinetId.'/Operations/ProcessDocumentAction?DocId='.$this->documentId; + } + + /** + * @return array + */ + protected function defaultBody(): array + { + return [ + 'DocumentAction' => 'UndoCheckOut', + ]; + } + + public function createDtoFromResponse(Response $response): Document + { + return GetASpecificDocumentFromAFileCabinetResponse::fromResponse($response); + } +} diff --git a/src/Requests/FileCabinets/Search/GetDocumentsFromAFileCabinet.php b/src/Requests/FileCabinets/Search/GetDocumentsFromAFileCabinet.php index 537611df..b7cd0eba 100644 --- a/src/Requests/FileCabinets/Search/GetDocumentsFromAFileCabinet.php +++ b/src/Requests/FileCabinets/Search/GetDocumentsFromAFileCabinet.php @@ -18,6 +18,9 @@ class GetDocumentsFromAFileCabinet extends Request implements Cacheable protected Method $method = Method::GET; + /** + * @param list $fields + */ public function __construct( protected readonly string $fileCabinetId, protected readonly array $fields = [], diff --git a/src/Requests/FileCabinets/Upload/AppendASinglePDFToADocument.php b/src/Requests/FileCabinets/Upload/AppendASinglePDFToADocument.php index eca8114d..54ab68f2 100644 --- a/src/Requests/FileCabinets/Upload/AppendASinglePDFToADocument.php +++ b/src/Requests/FileCabinets/Upload/AppendASinglePDFToADocument.php @@ -37,6 +37,9 @@ protected function defaultQuery(): array ]; } + /** + * @return list + */ protected function defaultBody(): array { return [ diff --git a/src/Requests/FileCabinets/Upload/AppendFilesToADataRecord.php b/src/Requests/FileCabinets/Upload/AppendFilesToADataRecord.php index 6fb25a87..6f098824 100644 --- a/src/Requests/FileCabinets/Upload/AppendFilesToADataRecord.php +++ b/src/Requests/FileCabinets/Upload/AppendFilesToADataRecord.php @@ -6,6 +6,7 @@ use CodebarAg\DocuWare\Responses\FileCabinets\Upload\CreateDataRecordResponse; use Illuminate\Support\Collection; use Saloon\Contracts\Body\HasBody; +use Saloon\Data\MultipartValue; use Saloon\Enums\Method; use Saloon\Http\Request; use Saloon\Http\Response; @@ -17,6 +18,9 @@ class AppendFilesToADataRecord extends Request implements HasBody protected Method $method = Method::POST; + /** + * @param Collection $files + */ public function __construct( protected readonly string $fileCabinetId, protected readonly string $dataRecordId, @@ -28,6 +32,9 @@ public function resolveEndpoint(): string return '/FileCabinets/'.$this->fileCabinetId.'/Documents/'.$this->dataRecordId; } + /** + * @return list + */ protected function defaultBody(): array { return $this->files->toArray(); diff --git a/src/Requests/FileCabinets/Upload/CreateDataRecord.php b/src/Requests/FileCabinets/Upload/CreateDataRecord.php index fb44e8a6..994964ba 100644 --- a/src/Requests/FileCabinets/Upload/CreateDataRecord.php +++ b/src/Requests/FileCabinets/Upload/CreateDataRecord.php @@ -3,6 +3,14 @@ namespace CodebarAg\DocuWare\Requests\FileCabinets\Upload; use CodebarAg\DocuWare\DTO\Documents\Document; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexDateDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexDateTimeDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexDecimalDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexKeywordDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexMemoDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexNumericDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexTableDTO; +use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\IndexTextDTO; use CodebarAg\DocuWare\DTO\Documents\DocumentIndex\PrepareDTO; use CodebarAg\DocuWare\Responses\FileCabinets\Upload\CreateDataRecordResponse; use Illuminate\Support\Collection; @@ -19,18 +27,31 @@ class CreateDataRecord extends Request implements HasBody protected Method $method = Method::POST; + /** + * @param Collection|null $indexes + */ public function __construct( protected readonly string $fileCabinetId, protected readonly ?string $fileContent, protected readonly ?string $fileName, protected readonly ?Collection $indexes = null, + protected readonly ?string $storeDialogId = null, ) {} public function resolveEndpoint(): string { - return '/FileCabinets/'.$this->fileCabinetId.'/Documents'; + $path = '/FileCabinets/'.$this->fileCabinetId.'/Documents'; + + if ($this->storeDialogId !== null && $this->storeDialogId !== '') { + $path .= '?StoreDialogId='.rawurlencode($this->storeDialogId); + } + + return $path; } + /** + * @return list + */ protected function defaultBody(): array { $body = []; diff --git a/src/Requests/FileCabinets/Upload/ReplaceAPDFDocumentSection.php b/src/Requests/FileCabinets/Upload/ReplaceAPDFDocumentSection.php index dd64e7a2..4de2ca90 100644 --- a/src/Requests/FileCabinets/Upload/ReplaceAPDFDocumentSection.php +++ b/src/Requests/FileCabinets/Upload/ReplaceAPDFDocumentSection.php @@ -37,6 +37,9 @@ protected function defaultQuery(): array ]; } + /** + * @return list + */ protected function defaultBody(): array { return [ diff --git a/src/Requests/General/Organization/GetAllFileCabinetsAndDocumentTrays.php b/src/Requests/General/Organization/GetAllFileCabinetsAndDocumentTrays.php index 06a31e48..cdffe3fb 100644 --- a/src/Requests/General/Organization/GetAllFileCabinetsAndDocumentTrays.php +++ b/src/Requests/General/Organization/GetAllFileCabinetsAndDocumentTrays.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\General\Organization; +use CodebarAg\DocuWare\DTO\General\Organization\FileCabinet; use CodebarAg\DocuWare\Responses\General\Organization\GetAllFileCabinetsAndDocumentTraysResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -48,7 +48,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Collection|Enumerable + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetAllFileCabinetsAndDocumentTraysResponse::fromResponse($response); } diff --git a/src/Requests/General/Organization/GetLoginToken.php b/src/Requests/General/Organization/GetLoginToken.php index 12f65fb6..7385b3e1 100644 --- a/src/Requests/General/Organization/GetLoginToken.php +++ b/src/Requests/General/Organization/GetLoginToken.php @@ -20,6 +20,9 @@ class GetLoginToken extends Request implements Cacheable, HasBody protected Method $method = Method::POST; + /** + * @param list $targetProducts + */ public function __construct( public array $targetProducts = ['PlatformService'], public string $usage = 'Multi', @@ -31,6 +34,9 @@ public function resolveEndpoint(): string return '/Organization/LoginToken'; } + /** + * @return array + */ protected function defaultBody(): array { return [ diff --git a/src/Requests/General/Organization/GetOrganization.php b/src/Requests/General/Organization/GetOrganization.php index 1518ebb8..d65176f7 100644 --- a/src/Requests/General/Organization/GetOrganization.php +++ b/src/Requests/General/Organization/GetOrganization.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\General\Organization; +use CodebarAg\DocuWare\DTO\General\Organization\Organization; use CodebarAg\DocuWare\Responses\General\Organization\GetOrganizationResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -34,7 +34,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Collection|Enumerable + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetOrganizationResponse::fromResponse($response); } diff --git a/src/Requests/General/UserManagement/CreateUpdateUsers/CreateUser.php b/src/Requests/General/UserManagement/CreateUpdateUsers/CreateUser.php index ec6cb16c..8fe8cb7f 100644 --- a/src/Requests/General/UserManagement/CreateUpdateUsers/CreateUser.php +++ b/src/Requests/General/UserManagement/CreateUpdateUsers/CreateUser.php @@ -38,6 +38,9 @@ public function defaultHeaders(): array ]; } + /** + * @return array + */ protected function defaultBody(): array { return [ diff --git a/src/Requests/General/UserManagement/CreateUpdateUsers/UpdateUser.php b/src/Requests/General/UserManagement/CreateUpdateUsers/UpdateUser.php index 2d06e910..75097d76 100644 --- a/src/Requests/General/UserManagement/CreateUpdateUsers/UpdateUser.php +++ b/src/Requests/General/UserManagement/CreateUpdateUsers/UpdateUser.php @@ -37,6 +37,9 @@ public function defaultHeaders(): array ]; } + /** + * @return array + */ protected function defaultBody(): array { return [ diff --git a/src/Requests/General/UserManagement/GetModifyGroups/AddUserToAGroup.php b/src/Requests/General/UserManagement/GetModifyGroups/AddUserToAGroup.php index 00db60de..b4de5f42 100644 --- a/src/Requests/General/UserManagement/GetModifyGroups/AddUserToAGroup.php +++ b/src/Requests/General/UserManagement/GetModifyGroups/AddUserToAGroup.php @@ -16,6 +16,9 @@ class AddUserToAGroup extends Request implements HasBody protected Method $method = Method::PUT; + /** + * @param list $ids + */ public function __construct( public string $userId, public array $ids @@ -33,6 +36,9 @@ protected function defaultQuery(): array ]; } + /** + * @return array + */ protected function defaultBody(): array { return [ diff --git a/src/Requests/General/UserManagement/GetModifyGroups/GetAllGroupsForASpecificUser.php b/src/Requests/General/UserManagement/GetModifyGroups/GetAllGroupsForASpecificUser.php index 7d3812b7..c9ea7969 100644 --- a/src/Requests/General/UserManagement/GetModifyGroups/GetAllGroupsForASpecificUser.php +++ b/src/Requests/General/UserManagement/GetModifyGroups/GetAllGroupsForASpecificUser.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\General\UserManagement\GetModifyGroups; +use CodebarAg\DocuWare\DTO\General\UserManagement\GetModifyGroups\Group; use CodebarAg\DocuWare\Responses\General\UserManagement\GetModifyGroups\GetGroupsResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -49,7 +49,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetGroupsResponse::fromResponse($response); } diff --git a/src/Requests/General/UserManagement/GetModifyGroups/GetGroups.php b/src/Requests/General/UserManagement/GetModifyGroups/GetGroups.php index bfcb872f..c2eee8a7 100644 --- a/src/Requests/General/UserManagement/GetModifyGroups/GetGroups.php +++ b/src/Requests/General/UserManagement/GetModifyGroups/GetGroups.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\General\UserManagement\GetModifyGroups; +use CodebarAg\DocuWare\DTO\General\UserManagement\GetModifyGroups\Group; use CodebarAg\DocuWare\Responses\General\UserManagement\GetModifyGroups\GetGroupsResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -47,7 +47,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetGroupsResponse::fromResponse($response); } diff --git a/src/Requests/General/UserManagement/GetModifyGroups/RemoveUserFromAGroup.php b/src/Requests/General/UserManagement/GetModifyGroups/RemoveUserFromAGroup.php index a1a04cf6..b24b8cc9 100644 --- a/src/Requests/General/UserManagement/GetModifyGroups/RemoveUserFromAGroup.php +++ b/src/Requests/General/UserManagement/GetModifyGroups/RemoveUserFromAGroup.php @@ -16,6 +16,9 @@ class RemoveUserFromAGroup extends Request implements HasBody protected Method $method = Method::PUT; + /** + * @param list $ids + */ public function __construct( public string $userId, public array $ids @@ -33,6 +36,9 @@ protected function defaultQuery(): array ]; } + /** + * @return array + */ protected function defaultBody(): array { return [ diff --git a/src/Requests/General/UserManagement/GetModifyRoles/AddUserToARole.php b/src/Requests/General/UserManagement/GetModifyRoles/AddUserToARole.php index f61095b2..7f7b09cf 100644 --- a/src/Requests/General/UserManagement/GetModifyRoles/AddUserToARole.php +++ b/src/Requests/General/UserManagement/GetModifyRoles/AddUserToARole.php @@ -16,6 +16,9 @@ class AddUserToARole extends Request implements HasBody protected Method $method = Method::PUT; + /** + * @param list $ids + */ public function __construct( public string $userId, public array $ids @@ -33,6 +36,9 @@ protected function defaultQuery(): array ]; } + /** + * @return array + */ protected function defaultBody(): array { return [ diff --git a/src/Requests/General/UserManagement/GetModifyRoles/GetAllRolesForASpecificUser.php b/src/Requests/General/UserManagement/GetModifyRoles/GetAllRolesForASpecificUser.php index 5d2b70ba..64cc7c0e 100644 --- a/src/Requests/General/UserManagement/GetModifyRoles/GetAllRolesForASpecificUser.php +++ b/src/Requests/General/UserManagement/GetModifyRoles/GetAllRolesForASpecificUser.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\General\UserManagement\GetModifyRoles; +use CodebarAg\DocuWare\DTO\General\UserManagement\GetModifyRoles\Role; use CodebarAg\DocuWare\Responses\General\UserManagement\GetModifyRoles\GetRolesResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -51,7 +51,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetRolesResponse::fromResponse($response); } diff --git a/src/Requests/General/UserManagement/GetModifyRoles/GetRoles.php b/src/Requests/General/UserManagement/GetModifyRoles/GetRoles.php index 961b2518..374978bc 100644 --- a/src/Requests/General/UserManagement/GetModifyRoles/GetRoles.php +++ b/src/Requests/General/UserManagement/GetModifyRoles/GetRoles.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\General\UserManagement\GetModifyRoles; +use CodebarAg\DocuWare\DTO\General\UserManagement\GetModifyRoles\Role; use CodebarAg\DocuWare\Responses\General\UserManagement\GetModifyRoles\GetRolesResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -49,7 +49,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetRolesResponse::fromResponse($response); } diff --git a/src/Requests/General/UserManagement/GetModifyRoles/RemoveUserFromARole.php b/src/Requests/General/UserManagement/GetModifyRoles/RemoveUserFromARole.php index abc7cf73..34d1f8bf 100644 --- a/src/Requests/General/UserManagement/GetModifyRoles/RemoveUserFromARole.php +++ b/src/Requests/General/UserManagement/GetModifyRoles/RemoveUserFromARole.php @@ -16,6 +16,9 @@ class RemoveUserFromARole extends Request implements HasBody protected Method $method = Method::PUT; + /** + * @param list $ids + */ public function __construct( public string $userId, public array $ids @@ -33,6 +36,9 @@ protected function defaultQuery(): array ]; } + /** + * @return array + */ protected function defaultBody(): array { return [ diff --git a/src/Requests/General/UserManagement/GetUsers/GetUsers.php b/src/Requests/General/UserManagement/GetUsers/GetUsers.php index 5645dc09..bd396e3b 100644 --- a/src/Requests/General/UserManagement/GetUsers/GetUsers.php +++ b/src/Requests/General/UserManagement/GetUsers/GetUsers.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\General\UserManagement\GetUsers; +use CodebarAg\DocuWare\DTO\General\UserManagement\GetUsers\User; use CodebarAg\DocuWare\Responses\General\UserManagement\GetUsers\GetUsersResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -47,7 +47,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetUsersResponse::fromResponse($response); } diff --git a/src/Requests/General/UserManagement/GetUsers/GetUsersOfAGroup.php b/src/Requests/General/UserManagement/GetUsers/GetUsersOfAGroup.php index 753ae7b5..81de9dd8 100644 --- a/src/Requests/General/UserManagement/GetUsers/GetUsersOfAGroup.php +++ b/src/Requests/General/UserManagement/GetUsers/GetUsersOfAGroup.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\General\UserManagement\GetUsers; +use CodebarAg\DocuWare\DTO\General\UserManagement\GetUsers\User; use CodebarAg\DocuWare\Responses\General\UserManagement\GetUsers\GetUsersResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -45,7 +45,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetUsersResponse::fromResponse($response); } diff --git a/src/Requests/General/UserManagement/GetUsers/GetUsersOfARole.php b/src/Requests/General/UserManagement/GetUsers/GetUsersOfARole.php index 217cfd2a..f08e44b6 100644 --- a/src/Requests/General/UserManagement/GetUsers/GetUsersOfARole.php +++ b/src/Requests/General/UserManagement/GetUsers/GetUsersOfARole.php @@ -2,9 +2,9 @@ namespace CodebarAg\DocuWare\Requests\General\UserManagement\GetUsers; +use CodebarAg\DocuWare\DTO\General\UserManagement\GetUsers\User; use CodebarAg\DocuWare\Responses\General\UserManagement\GetUsers\GetUsersResponse; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Illuminate\Support\Facades\Cache; use Saloon\CachePlugin\Contracts\Cacheable; use Saloon\CachePlugin\Drivers\LaravelCacheDriver; @@ -47,7 +47,10 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } - public function createDtoFromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public function createDtoFromResponse(Response $response): Collection { return GetUsersResponse::fromResponse($response); } diff --git a/src/Requests/Search/GetSearchRequest.php b/src/Requests/Search/GetSearchRequest.php index 2438c00f..1106a677 100644 --- a/src/Requests/Search/GetSearchRequest.php +++ b/src/Requests/Search/GetSearchRequest.php @@ -21,6 +21,10 @@ class GetSearchRequest extends Request implements Cacheable, HasBody protected Method $method = Method::POST; + /** + * @param list $additionalFileCabinetIds + * @param array $condition + */ public function __construct( protected readonly ?string $fileCabinetId, protected readonly ?string $dialogId = null, @@ -59,6 +63,9 @@ public function defaultQuery(): array return $defultQuery; } + /** + * @return array + */ public function defaultBody(): array { return [ diff --git a/src/Requests/Workflow/GetDocumentWorkflowHistory.php b/src/Requests/Workflow/GetDocumentWorkflowHistory.php index e3fd08e7..2a8ef955 100644 --- a/src/Requests/Workflow/GetDocumentWorkflowHistory.php +++ b/src/Requests/Workflow/GetDocumentWorkflowHistory.php @@ -2,6 +2,7 @@ namespace CodebarAg\DocuWare\Requests\Workflow; +use CodebarAg\DocuWare\DTO\Workflow\InstanceHistory; use CodebarAg\DocuWare\Responses\Workflow\GetDocumentWorkflowHistoryResponse; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Cache; @@ -38,6 +39,9 @@ public function cacheExpiryInSeconds(): int return config('laravel-docuware.configurations.cache.lifetime_in_seconds', 3600); } + /** + * @return Collection + */ public function createDtoFromResponse(Response $response): Collection { return GetDocumentWorkflowHistoryResponse::fromResponse($response); diff --git a/src/Responses/Documents/ApplicationProperties/GetApplicationPropertiesResponse.php b/src/Responses/Documents/ApplicationProperties/GetApplicationPropertiesResponse.php index 35d9184c..7e992c69 100644 --- a/src/Responses/Documents/ApplicationProperties/GetApplicationPropertiesResponse.php +++ b/src/Responses/Documents/ApplicationProperties/GetApplicationPropertiesResponse.php @@ -4,16 +4,21 @@ use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; +use Illuminate\Support\Collection; use Saloon\Http\Response; final class GetApplicationPropertiesResponse { - public static function fromResponse(Response $response): mixed + /** + * @return Collection> + */ + public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); EnsureValidResponse::from($response); - return collect($response->throw()->json('DocumentApplicationProperty')); + return collect(JsonArrays::listOfRecords($response->throw()->json('DocumentApplicationProperty'))); } } diff --git a/src/Responses/Documents/Sections/GetAllSectionsFromADocumentResponse.php b/src/Responses/Documents/Sections/GetAllSectionsFromADocumentResponse.php index 8388ffb5..8a9ff1f3 100644 --- a/src/Responses/Documents/Sections/GetAllSectionsFromADocumentResponse.php +++ b/src/Responses/Documents/Sections/GetAllSectionsFromADocumentResponse.php @@ -5,18 +5,22 @@ use CodebarAg\DocuWare\DTO\Section; use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Saloon\Http\Response; final class GetAllSectionsFromADocumentResponse { - public static function fromResponse(Response $response): Collection|Enumerable + /** + * @return Collection + */ + public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); EnsureValidResponse::from($response); - return collect($response->throw()->json('Section'))->map(fn ($section) => Section::fromJson($section)); + return collect(JsonArrays::listOfRecords($response->throw()->json('Section'))) + ->map(fn (array $section) => Section::fromJson($section)); } } diff --git a/src/Responses/Documents/UpdateIndexValues/UpdateIndexValuesResponse.php b/src/Responses/Documents/UpdateIndexValues/UpdateIndexValuesResponse.php index 912e998c..2bcce424 100644 --- a/src/Responses/Documents/UpdateIndexValues/UpdateIndexValuesResponse.php +++ b/src/Responses/Documents/UpdateIndexValues/UpdateIndexValuesResponse.php @@ -4,12 +4,16 @@ use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use CodebarAg\DocuWare\Support\ParseValue; use Illuminate\Support\Collection; use Saloon\Http\Response; final class UpdateIndexValuesResponse { + /** + * @return Collection + */ public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); @@ -18,7 +22,7 @@ public static function fromResponse(Response $response): Collection $fields = $response->throw()->json('Field'); - return collect($fields)->mapWithKeys(function (array $field) { + return collect(JsonArrays::listOfRecords($fields))->mapWithKeys(function (array $field) { return [ $field['FieldName'] => ParseValue::field($field), ]; diff --git a/src/Responses/Fields/GetFieldsResponse.php b/src/Responses/Fields/GetFieldsResponse.php index bd2b8584..34a8f64a 100644 --- a/src/Responses/Fields/GetFieldsResponse.php +++ b/src/Responses/Fields/GetFieldsResponse.php @@ -5,13 +5,16 @@ use CodebarAg\DocuWare\DTO\Documents\Field; use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Saloon\Http\Response; final class GetFieldsResponse { - public static function fromResponse(Response $response): Collection|Enumerable + /** + * @return Collection + */ + public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); @@ -19,6 +22,6 @@ public static function fromResponse(Response $response): Collection|Enumerable $fields = $response->throw()->json('Fields'); - return collect($fields)->map(fn (array $field) => Field::fromJson($field)); + return collect(JsonArrays::listOfRecords($fields))->map(fn (array $field) => Field::fromJson($field)); } } diff --git a/src/Responses/FileCabinets/Dialogs/GetAllDialogsResponse.php b/src/Responses/FileCabinets/Dialogs/GetAllDialogsResponse.php index 6e1df2f3..64d0a56c 100644 --- a/src/Responses/FileCabinets/Dialogs/GetAllDialogsResponse.php +++ b/src/Responses/FileCabinets/Dialogs/GetAllDialogsResponse.php @@ -5,13 +5,16 @@ use CodebarAg\DocuWare\DTO\FileCabinets\Dialog; use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Saloon\Http\Response; final class GetAllDialogsResponse { - public static function fromResponse(Response $response): Collection|Enumerable + /** + * @return Collection + */ + public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); @@ -19,6 +22,6 @@ public static function fromResponse(Response $response): Collection|Enumerable $dialogs = $response->throw()->json('Dialog'); - return collect($dialogs)->map(fn (array $dialog) => Dialog::fromJson($dialog)); + return collect(JsonArrays::listOfRecords($dialogs))->map(fn (array $dialog) => Dialog::fromJson($dialog)); } } diff --git a/src/Responses/FileCabinets/Search/GetDocumentsFromAFileCabinetResponse.php b/src/Responses/FileCabinets/Search/GetDocumentsFromAFileCabinetResponse.php index c2786bd6..33049d63 100644 --- a/src/Responses/FileCabinets/Search/GetDocumentsFromAFileCabinetResponse.php +++ b/src/Responses/FileCabinets/Search/GetDocumentsFromAFileCabinetResponse.php @@ -10,7 +10,7 @@ final class GetDocumentsFromAFileCabinetResponse { - public static function fromResponse(Response $response, $page = 1, $perPage = 50): DocumentPaginator + public static function fromResponse(Response $response, int $page = 1, int $perPage = 50): DocumentPaginator { event(new DocuWareResponseLog($response)); diff --git a/src/Responses/General/Organization/GetAllFileCabinetsAndDocumentTraysResponse.php b/src/Responses/General/Organization/GetAllFileCabinetsAndDocumentTraysResponse.php index 52aa8d89..13ff8d75 100644 --- a/src/Responses/General/Organization/GetAllFileCabinetsAndDocumentTraysResponse.php +++ b/src/Responses/General/Organization/GetAllFileCabinetsAndDocumentTraysResponse.php @@ -5,13 +5,16 @@ use CodebarAg\DocuWare\DTO\General\Organization\FileCabinet; use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Saloon\Http\Response; final class GetAllFileCabinetsAndDocumentTraysResponse { - public static function fromResponse(Response $response): Collection|Enumerable + /** + * @return Collection + */ + public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); @@ -19,6 +22,6 @@ public static function fromResponse(Response $response): Collection|Enumerable $cabinets = $response->throw()->json('FileCabinet'); - return collect($cabinets)->map(fn (array $cabinet) => FileCabinet::fromJson($cabinet)); + return collect(JsonArrays::listOfRecords($cabinets))->map(fn (array $cabinet) => FileCabinet::fromJson($cabinet)); } } diff --git a/src/Responses/General/Organization/GetOrganizationResponse.php b/src/Responses/General/Organization/GetOrganizationResponse.php index a43e41dc..9090b253 100644 --- a/src/Responses/General/Organization/GetOrganizationResponse.php +++ b/src/Responses/General/Organization/GetOrganizationResponse.php @@ -5,13 +5,16 @@ use CodebarAg\DocuWare\DTO\General\Organization\Organization; use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Saloon\Http\Response; final class GetOrganizationResponse { - public static function fromResponse(Response $response): Collection|Enumerable + /** + * @return Collection + */ + public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); @@ -19,6 +22,6 @@ public static function fromResponse(Response $response): Collection|Enumerable $organizations = $response->throw()->json('Organization'); - return collect($organizations)->map(fn (array $organization) => Organization::fromJson($organization)); + return collect(JsonArrays::listOfRecords($organizations))->map(fn (array $organization) => Organization::fromJson($organization)); } } diff --git a/src/Responses/General/UserManagement/GetModifyGroups/GetGroupsResponse.php b/src/Responses/General/UserManagement/GetModifyGroups/GetGroupsResponse.php index 58228264..41d59ba5 100644 --- a/src/Responses/General/UserManagement/GetModifyGroups/GetGroupsResponse.php +++ b/src/Responses/General/UserManagement/GetModifyGroups/GetGroupsResponse.php @@ -5,13 +5,16 @@ use CodebarAg\DocuWare\DTO\General\UserManagement\GetModifyGroups\Group; use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Saloon\Http\Response; final class GetGroupsResponse { - public static function fromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); @@ -19,6 +22,6 @@ public static function fromResponse(Response $response): Enumerable|Collection $groups = $response->throw()->json('Item'); - return collect($groups)->map(fn (array $group) => Group::fromJson($group)); + return collect(JsonArrays::listOfRecords($groups))->map(fn (array $group) => Group::fromJson($group)); } } diff --git a/src/Responses/General/UserManagement/GetModifyRoles/GetRolesResponse.php b/src/Responses/General/UserManagement/GetModifyRoles/GetRolesResponse.php index b07ff814..d05c8268 100644 --- a/src/Responses/General/UserManagement/GetModifyRoles/GetRolesResponse.php +++ b/src/Responses/General/UserManagement/GetModifyRoles/GetRolesResponse.php @@ -5,13 +5,16 @@ use CodebarAg\DocuWare\DTO\General\UserManagement\GetModifyRoles\Role; use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Saloon\Http\Response; final class GetRolesResponse { - public static function fromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); @@ -19,6 +22,6 @@ public static function fromResponse(Response $response): Enumerable|Collection $roles = $response->throw()->json('Item'); - return collect($roles)->map(fn (array $role) => Role::fromJson($role)); + return collect(JsonArrays::listOfRecords($roles))->map(fn (array $role) => Role::fromJson($role)); } } diff --git a/src/Responses/General/UserManagement/GetUsers/GetUsersResponse.php b/src/Responses/General/UserManagement/GetUsers/GetUsersResponse.php index 40104035..4ea47eef 100644 --- a/src/Responses/General/UserManagement/GetUsers/GetUsersResponse.php +++ b/src/Responses/General/UserManagement/GetUsers/GetUsersResponse.php @@ -5,13 +5,16 @@ use CodebarAg\DocuWare\DTO\General\UserManagement\GetUsers\User; use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; -use Illuminate\Support\Enumerable; use Saloon\Http\Response; final class GetUsersResponse { - public static function fromResponse(Response $response): Enumerable|Collection + /** + * @return Collection + */ + public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); @@ -19,6 +22,6 @@ public static function fromResponse(Response $response): Enumerable|Collection $users = $response->throw()->json('User'); - return collect($users)->map(fn (array $user) => User::fromJson($user)); + return collect(JsonArrays::listOfRecords($users))->map(fn (array $user) => User::fromJson($user)); } } diff --git a/src/Responses/Search/GetSearchResponse.php b/src/Responses/Search/GetSearchResponse.php index 0faa8877..430bdc75 100644 --- a/src/Responses/Search/GetSearchResponse.php +++ b/src/Responses/Search/GetSearchResponse.php @@ -10,7 +10,7 @@ final class GetSearchResponse { - public static function fromResponse(Response $response, $page, $perPage): DocumentPaginator + public static function fromResponse(Response $response, int $page, int $perPage): DocumentPaginator { event(new DocuWareResponseLog($response)); diff --git a/src/Responses/Search/GetTrashSearchResponse.php b/src/Responses/Search/GetTrashSearchResponse.php index 6cc028a2..6a9fac11 100644 --- a/src/Responses/Search/GetTrashSearchResponse.php +++ b/src/Responses/Search/GetTrashSearchResponse.php @@ -10,7 +10,7 @@ final class GetTrashSearchResponse { - public static function fromResponse(Response $response, $page, $perPage): TrashDocumentPaginator + public static function fromResponse(Response $response, int $page, int $perPage): TrashDocumentPaginator { event(new DocuWareResponseLog($response)); diff --git a/src/Responses/Workflow/GetDocumentWorkflowHistoryResponse.php b/src/Responses/Workflow/GetDocumentWorkflowHistoryResponse.php index 0396d9b5..0b8436c6 100644 --- a/src/Responses/Workflow/GetDocumentWorkflowHistoryResponse.php +++ b/src/Responses/Workflow/GetDocumentWorkflowHistoryResponse.php @@ -5,11 +5,15 @@ use CodebarAg\DocuWare\DTO\Workflow\InstanceHistory; use CodebarAg\DocuWare\Events\DocuWareResponseLog; use CodebarAg\DocuWare\Support\EnsureValidResponse; +use CodebarAg\DocuWare\Support\JsonArrays; use Illuminate\Support\Collection; use Saloon\Http\Response; final class GetDocumentWorkflowHistoryResponse { + /** + * @return Collection + */ public static function fromResponse(Response $response): Collection { event(new DocuWareResponseLog($response)); @@ -18,6 +22,6 @@ public static function fromResponse(Response $response): Collection $instanceHistories = $response->throw()->json('InstanceHistory'); - return collect($instanceHistories)->map(fn (array $instanceHistory) => InstanceHistory::fromJson($instanceHistory)); + return collect(JsonArrays::listOfRecords($instanceHistories))->map(fn (array $instanceHistory) => InstanceHistory::fromJson($instanceHistory)); } } diff --git a/src/Support/Auth.php b/src/Support/Auth.php index 2b7887a6..cbf8ad87 100644 --- a/src/Support/Auth.php +++ b/src/Support/Auth.php @@ -18,7 +18,10 @@ class Auth public static function store(CookieJar $cookies): void { - $cookie = collect($cookies->toArray()) + /** @var list> $cookieList */ + $cookieList = $cookies->toArray(); + + $cookie = collect($cookieList) ->reject(fn (array $cookie) => Arr::get($cookie, 'Value') === '') ->firstWhere('Name', self::COOKIE_NAME); @@ -33,9 +36,14 @@ public static function store(CookieJar $cookies): void ); } + /** + * @return array|null + */ public static function cookies(): ?array { - return Cache::driver(self::cacheDriver())->get(self::CACHE_KEY); + $cached = Cache::driver(self::cacheDriver())->get(self::CACHE_KEY); + + return is_array($cached) ? $cached : null; } public static function cookieJar(): ?CookieJar @@ -49,7 +57,9 @@ public static function cookieJar(): ?CookieJar public static function cookieDate(): string { - return Arr::get(Cache::driver(self::cacheDriver())->get(self::CACHE_KEY), 'CreatedAt'); + $cached = Cache::driver(self::cacheDriver())->get(self::CACHE_KEY); + + return is_array($cached) ? (string) Arr::get($cached, 'CreatedAt') : ''; } public static function forget(): void diff --git a/src/Support/JsonArrays.php b/src/Support/JsonArrays.php new file mode 100644 index 00000000..ffc2683d --- /dev/null +++ b/src/Support/JsonArrays.php @@ -0,0 +1,57 @@ + + */ + public static function associativeRow(mixed $raw): array + { + if (! is_array($raw)) { + return []; + } + + return self::stringKeyedRow($raw); + } + + /** + * Normalize mixed JSON (e.g. decoded list or map of rows) to a list of associative records. + * + * @return list> + */ + public static function listOfRecords(mixed $raw): array + { + if (! is_array($raw)) { + return []; + } + + $out = []; + foreach (array_values($raw) as $item) { + if (! is_array($item)) { + continue; + } + + $out[] = self::stringKeyedRow($item); + } + + return $out; + } + + /** + * @param array $row + * @return array + */ + private static function stringKeyedRow(array $row): array + { + $normalized = []; + foreach ($row as $key => $value) { + $normalized[(string) $key] = $value; + } + + return $normalized; + } +} diff --git a/src/Support/ParseValue.php b/src/Support/ParseValue.php index 46db420c..b75e4896 100644 --- a/src/Support/ParseValue.php +++ b/src/Support/ParseValue.php @@ -10,6 +10,11 @@ class ParseValue { + /** + * @param array|null $field + * @param int|float|Carbon|string|Collection|null $default + * @return int|float|Carbon|string|Collection|null + */ public static function field( ?array $field, int|float|Carbon|string|Collection|null $default = null, @@ -25,9 +30,12 @@ public static function field( 'Int' => (int) $item, 'String' => (string) $item, 'Decimal' => (float) $item, - 'Date', 'DateTime' => self::date($item), - 'Keywords' => Arr::join($item['Keyword'], ', '), - 'Table' => self::table($item), + 'Date', 'DateTime' => is_string($item) ? self::date($item) : $default, + 'Keywords' => Arr::join( + is_array($item) && isset($item['Keyword']) && is_array($item['Keyword']) ? $item['Keyword'] : [], + ', ' + ), + 'Table' => is_array($item) ? self::table($item) : $default, default => $default, }; } @@ -42,20 +50,42 @@ public static function date(string $date): Carbon return Carbon::createFromTimestampMs($timestamp); } + /** + * @param array $Item + * @return Collection|null + */ public static function table(array $Item): ?Collection { - return match ($Item['$type']) { - 'DocumentIndexFieldTable' => self::documentIndexFieldTable($Item['Row']), + $type = $Item['$type'] ?? null; + + return match ($type) { + 'DocumentIndexFieldTable' => isset($Item['Row']) && is_array($Item['Row']) + ? self::documentIndexFieldTable($Item['Row']) + : null, default => null, }; } + /** + * @param array $Row + * @return Collection|null + */ public static function documentIndexFieldTable(array $Row): ?Collection { - $rows = collect($Row); + /** @var list> $list */ + $list = []; + foreach (array_values($Row) as $row) { + if (is_array($row)) { + $list[] = $row; + } + } + + $rows = collect($list); return $rows->map(function (array $row) { - return TableRow::fromJson($row['ColumnValue']); + $columnValue = $row['ColumnValue'] ?? []; + + return TableRow::fromJson(is_array($columnValue) ? $columnValue : []); }); } } diff --git a/tests/Feature/SaloonFixtures/GetOrganizationFixtureTest.php b/tests/Feature/SaloonFixtures/GetOrganizationFixtureTest.php new file mode 100644 index 00000000..657014b4 --- /dev/null +++ b/tests/Feature/SaloonFixtures/GetOrganizationFixtureTest.php @@ -0,0 +1,26 @@ + new Fixture('get-organization'), + ]); + + $connector = (new FixtureDocuWareConnector)->withMockClient($mockClient); + + $organizations = $connector->send(new GetOrganization)->dto(); + + expect($organizations)->toHaveCount(1); + expect($organizations->first()->name)->toBe('Fixture Org'); + expect($organizations->first()->id)->toBe('org-fixture-1'); + + Event::assertDispatched(DocuWareResponseLog::class); +}); diff --git a/tests/Fixtures/saloon/get-organization.json b/tests/Fixtures/saloon/get-organization.json new file mode 100644 index 00000000..3c02f100 --- /dev/null +++ b/tests/Fixtures/saloon/get-organization.json @@ -0,0 +1,10 @@ +{ + "statusCode": 200, + "headers": { + "Content-Type": [ + "application/json; charset=utf-8" + ] + }, + "data": "{\"Organization\":[{\"Id\":\"org-fixture-1\",\"Name\":\"Fixture Org\",\"Guid\":\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\"AdditionalInfo\":[],\"ConfigurationRights\":[]}]}", + "context": [] +} diff --git a/tests/Feature/DocuWareAuthenticationTest.php b/tests/Integration/DocuWareAuthenticationTest.php similarity index 100% rename from tests/Feature/DocuWareAuthenticationTest.php rename to tests/Integration/DocuWareAuthenticationTest.php diff --git a/tests/Feature/DocuWareTest.php b/tests/Integration/DocuWareTest.php similarity index 82% rename from tests/Feature/DocuWareTest.php rename to tests/Integration/DocuWareTest.php index 7ed6ded5..eb3af03c 100644 --- a/tests/Feature/DocuWareTest.php +++ b/tests/Integration/DocuWareTest.php @@ -1,7 +1,5 @@ validUntil(now()->addMinute()) ->make(); + $platform = trim(config('laravel-docuware.platform_path', 'DocuWare/Platform'), '/'); $endpoint = sprintf( - '%s/DocuWare/Platform/WebClient/Integration?ep=', - config('laravel-docuware.credentials.url'), + '%s/%s/WebClient/Integration?ep=', + rtrim((string) config('laravel-docuware.credentials.url'), '/'), + $platform, ); $this->assertStringStartsWith( @@ -70,9 +70,11 @@ ->validUntil(now()->addMinute()) ->make(); + $platform = trim(config('laravel-docuware.platform_path', 'DocuWare/Platform'), '/'); $endpoint = sprintf( - '%s/DocuWare/Platform/WebClient/Integration?ep=', - config('laravel-docuware.credentials.url'), + '%s/%s/WebClient/Integration?ep=', + rtrim((string) config('laravel-docuware.credentials.url'), '/'), + $platform, ); $this->assertStringStartsWith( diff --git a/tests/Feature/Requests/Documents/ApplicationProperties/ApplicationPropertiesTest.php b/tests/Integration/Requests/Documents/ApplicationProperties/ApplicationPropertiesTest.php similarity index 100% rename from tests/Feature/Requests/Documents/ApplicationProperties/ApplicationPropertiesTest.php rename to tests/Integration/Requests/Documents/ApplicationProperties/ApplicationPropertiesTest.php diff --git a/tests/Feature/Requests/Documents/ClipUnclipStapleUnstaple/ClipTest.php b/tests/Integration/Requests/Documents/ClipUnclipStapleUnstaple/ClipTest.php similarity index 100% rename from tests/Feature/Requests/Documents/ClipUnclipStapleUnstaple/ClipTest.php rename to tests/Integration/Requests/Documents/ClipUnclipStapleUnstaple/ClipTest.php diff --git a/tests/Feature/Requests/Documents/ClipUnclipStapleUnstaple/StapleTest.php b/tests/Integration/Requests/Documents/ClipUnclipStapleUnstaple/StapleTest.php similarity index 100% rename from tests/Feature/Requests/Documents/ClipUnclipStapleUnstaple/StapleTest.php rename to tests/Integration/Requests/Documents/ClipUnclipStapleUnstaple/StapleTest.php diff --git a/tests/Feature/Requests/Documents/ClipUnclipStapleUnstaple/UnclipTest.php b/tests/Integration/Requests/Documents/ClipUnclipStapleUnstaple/UnclipTest.php similarity index 100% rename from tests/Feature/Requests/Documents/ClipUnclipStapleUnstaple/UnclipTest.php rename to tests/Integration/Requests/Documents/ClipUnclipStapleUnstaple/UnclipTest.php diff --git a/tests/Feature/Requests/Documents/ClipUnclipStapleUnstaple/UnstapleTest.php b/tests/Integration/Requests/Documents/ClipUnclipStapleUnstaple/UnstapleTest.php similarity index 100% rename from tests/Feature/Requests/Documents/ClipUnclipStapleUnstaple/UnstapleTest.php rename to tests/Integration/Requests/Documents/ClipUnclipStapleUnstaple/UnstapleTest.php diff --git a/tests/Feature/Requests/Documents/DocumentsTrashBin/DeleteDocumentsFromTrashBinTest.php b/tests/Integration/Requests/Documents/DocumentsTrashBin/DeleteDocumentsFromTrashBinTest.php similarity index 100% rename from tests/Feature/Requests/Documents/DocumentsTrashBin/DeleteDocumentsFromTrashBinTest.php rename to tests/Integration/Requests/Documents/DocumentsTrashBin/DeleteDocumentsFromTrashBinTest.php diff --git a/tests/Feature/Requests/Documents/DocumentsTrashBin/GetDocumentsFromTrashBinTest.php b/tests/Integration/Requests/Documents/DocumentsTrashBin/GetDocumentsFromTrashBinTest.php similarity index 100% rename from tests/Feature/Requests/Documents/DocumentsTrashBin/GetDocumentsFromTrashBinTest.php rename to tests/Integration/Requests/Documents/DocumentsTrashBin/GetDocumentsFromTrashBinTest.php diff --git a/tests/Feature/Requests/Documents/DocumentsTrashBin/RestoreDocumentsFromTrashBinTest.php b/tests/Integration/Requests/Documents/DocumentsTrashBin/RestoreDocumentsFromTrashBinTest.php similarity index 100% rename from tests/Feature/Requests/Documents/DocumentsTrashBin/RestoreDocumentsFromTrashBinTest.php rename to tests/Integration/Requests/Documents/DocumentsTrashBin/RestoreDocumentsFromTrashBinTest.php diff --git a/tests/Feature/Requests/Documents/Download/DownloadDocumentTest.php b/tests/Integration/Requests/Documents/Download/DownloadDocumentTest.php similarity index 100% rename from tests/Feature/Requests/Documents/Download/DownloadDocumentTest.php rename to tests/Integration/Requests/Documents/Download/DownloadDocumentTest.php diff --git a/tests/Feature/Requests/Documents/Download/DownloadSectionTest.php b/tests/Integration/Requests/Documents/Download/DownloadSectionTest.php similarity index 100% rename from tests/Feature/Requests/Documents/Download/DownloadSectionTest.php rename to tests/Integration/Requests/Documents/Download/DownloadSectionTest.php diff --git a/tests/Feature/Requests/Documents/Download/DownloadThumbnailTest.php b/tests/Integration/Requests/Documents/Download/DownloadThumbnailTest.php similarity index 100% rename from tests/Feature/Requests/Documents/Download/DownloadThumbnailTest.php rename to tests/Integration/Requests/Documents/Download/DownloadThumbnailTest.php diff --git a/tests/Feature/Requests/Documents/GetDocumentCountRequestTest.php b/tests/Integration/Requests/Documents/GetDocumentCountRequestTest.php similarity index 100% rename from tests/Feature/Requests/Documents/GetDocumentCountRequestTest.php rename to tests/Integration/Requests/Documents/GetDocumentCountRequestTest.php diff --git a/tests/Feature/Requests/Documents/GetDocumentPreviewRequestTest.php b/tests/Integration/Requests/Documents/GetDocumentPreviewRequestTest.php similarity index 100% rename from tests/Feature/Requests/Documents/GetDocumentPreviewRequestTest.php rename to tests/Integration/Requests/Documents/GetDocumentPreviewRequestTest.php diff --git a/tests/Feature/Requests/Documents/PostDocumentRequestTest.php b/tests/Integration/Requests/Documents/PostDocumentRequestTest.php similarity index 100% rename from tests/Feature/Requests/Documents/PostDocumentRequestTest.php rename to tests/Integration/Requests/Documents/PostDocumentRequestTest.php diff --git a/tests/Feature/Requests/Documents/PutDocumentFieldsRequestTest.php b/tests/Integration/Requests/Documents/PutDocumentFieldsRequestTest.php similarity index 100% rename from tests/Feature/Requests/Documents/PutDocumentFieldsRequestTest.php rename to tests/Integration/Requests/Documents/PutDocumentFieldsRequestTest.php diff --git a/tests/Feature/Requests/Documents/Sections/DeleteSectionTest.php b/tests/Integration/Requests/Documents/Sections/DeleteSectionTest.php similarity index 100% rename from tests/Feature/Requests/Documents/Sections/DeleteSectionTest.php rename to tests/Integration/Requests/Documents/Sections/DeleteSectionTest.php diff --git a/tests/Feature/Requests/Documents/Sections/GetASpecificSectionTest.php b/tests/Integration/Requests/Documents/Sections/GetASpecificSectionTest.php similarity index 100% rename from tests/Feature/Requests/Documents/Sections/GetASpecificSectionTest.php rename to tests/Integration/Requests/Documents/Sections/GetASpecificSectionTest.php diff --git a/tests/Feature/Requests/Documents/Sections/GetAllSectionsFromADocumentTest.php b/tests/Integration/Requests/Documents/Sections/GetAllSectionsFromADocumentTest.php similarity index 100% rename from tests/Feature/Requests/Documents/Sections/GetAllSectionsFromADocumentTest.php rename to tests/Integration/Requests/Documents/Sections/GetAllSectionsFromADocumentTest.php diff --git a/tests/Feature/Requests/Documents/Sections/GetTextshotTest.php b/tests/Integration/Requests/Documents/Sections/GetTextshotTest.php similarity index 100% rename from tests/Feature/Requests/Documents/Sections/GetTextshotTest.php rename to tests/Integration/Requests/Documents/Sections/GetTextshotTest.php diff --git a/tests/Feature/Requests/Documents/Thumbnail/GetDocumentDownloadThumbnailRequestTest.php b/tests/Integration/Requests/Documents/Thumbnail/GetDocumentDownloadThumbnailRequestTest.php similarity index 100% rename from tests/Feature/Requests/Documents/Thumbnail/GetDocumentDownloadThumbnailRequestTest.php rename to tests/Integration/Requests/Documents/Thumbnail/GetDocumentDownloadThumbnailRequestTest.php diff --git a/tests/Feature/Requests/Fields/GetFieldsRequestTest.php b/tests/Integration/Requests/Fields/GetFieldsRequestTest.php similarity index 100% rename from tests/Feature/Requests/Fields/GetFieldsRequestTest.php rename to tests/Integration/Requests/Fields/GetFieldsRequestTest.php diff --git a/tests/Feature/Requests/FileCabinets/Dialogs/GetASpecificDialogTest.php b/tests/Integration/Requests/FileCabinets/Dialogs/GetASpecificDialogTest.php similarity index 100% rename from tests/Feature/Requests/FileCabinets/Dialogs/GetASpecificDialogTest.php rename to tests/Integration/Requests/FileCabinets/Dialogs/GetASpecificDialogTest.php diff --git a/tests/Feature/Requests/FileCabinets/Dialogs/GetAllDialogs.php b/tests/Integration/Requests/FileCabinets/Dialogs/GetAllDialogs.php similarity index 100% rename from tests/Feature/Requests/FileCabinets/Dialogs/GetAllDialogs.php rename to tests/Integration/Requests/FileCabinets/Dialogs/GetAllDialogs.php diff --git a/tests/Feature/Requests/FileCabinets/Dialogs/GetDialogsOfASpecificTypeTest.php b/tests/Integration/Requests/FileCabinets/Dialogs/GetDialogsOfASpecificTypeTest.php similarity index 100% rename from tests/Feature/Requests/FileCabinets/Dialogs/GetDialogsOfASpecificTypeTest.php rename to tests/Integration/Requests/FileCabinets/Dialogs/GetDialogsOfASpecificTypeTest.php diff --git a/tests/Feature/Requests/FileCabinets/General/GetFileCabinetInformationTest.php b/tests/Integration/Requests/FileCabinets/General/GetFileCabinetInformationTest.php similarity index 100% rename from tests/Feature/Requests/FileCabinets/General/GetFileCabinetInformationTest.php rename to tests/Integration/Requests/FileCabinets/General/GetFileCabinetInformationTest.php diff --git a/tests/Feature/Requests/FileCabinets/Search/GetASpecificDocumentFromAFileCabinetTest.php b/tests/Integration/Requests/FileCabinets/Search/GetASpecificDocumentFromAFileCabinetTest.php similarity index 100% rename from tests/Feature/Requests/FileCabinets/Search/GetASpecificDocumentFromAFileCabinetTest.php rename to tests/Integration/Requests/FileCabinets/Search/GetASpecificDocumentFromAFileCabinetTest.php diff --git a/tests/Feature/Requests/FileCabinets/Search/GetDocumentsFromAFileCabinetTest.php b/tests/Integration/Requests/FileCabinets/Search/GetDocumentsFromAFileCabinetTest.php similarity index 100% rename from tests/Feature/Requests/FileCabinets/Search/GetDocumentsFromAFileCabinetTest.php rename to tests/Integration/Requests/FileCabinets/Search/GetDocumentsFromAFileCabinetTest.php diff --git a/tests/Feature/Requests/FileCabinets/Upload/AppendASinglePDFToADocumentTest.php b/tests/Integration/Requests/FileCabinets/Upload/AppendASinglePDFToADocumentTest.php similarity index 100% rename from tests/Feature/Requests/FileCabinets/Upload/AppendASinglePDFToADocumentTest.php rename to tests/Integration/Requests/FileCabinets/Upload/AppendASinglePDFToADocumentTest.php diff --git a/tests/Feature/Requests/FileCabinets/Upload/AppendFilesToADataRecordTest.php b/tests/Integration/Requests/FileCabinets/Upload/AppendFilesToADataRecordTest.php similarity index 100% rename from tests/Feature/Requests/FileCabinets/Upload/AppendFilesToADataRecordTest.php rename to tests/Integration/Requests/FileCabinets/Upload/AppendFilesToADataRecordTest.php diff --git a/tests/Feature/Requests/FileCabinets/Upload/ReplaceAPDFDocumentSectionTest.php b/tests/Integration/Requests/FileCabinets/Upload/ReplaceAPDFDocumentSectionTest.php similarity index 100% rename from tests/Feature/Requests/FileCabinets/Upload/ReplaceAPDFDocumentSectionTest.php rename to tests/Integration/Requests/FileCabinets/Upload/ReplaceAPDFDocumentSectionTest.php diff --git a/tests/Feature/Requests/General/UserManagement/CreateUpdateUsers/CreateUpdateUserTest.php b/tests/Integration/Requests/General/UserManagement/CreateUpdateUsers/CreateUpdateUserTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/CreateUpdateUsers/CreateUpdateUserTest.php rename to tests/Integration/Requests/General/UserManagement/CreateUpdateUsers/CreateUpdateUserTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetModifyGroups/AddRemoveUserToAGroupTest.php b/tests/Integration/Requests/General/UserManagement/GetModifyGroups/AddRemoveUserToAGroupTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetModifyGroups/AddRemoveUserToAGroupTest.php rename to tests/Integration/Requests/General/UserManagement/GetModifyGroups/AddRemoveUserToAGroupTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetModifyGroups/GetAllGroupsForASpecificUserTest.php b/tests/Integration/Requests/General/UserManagement/GetModifyGroups/GetAllGroupsForASpecificUserTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetModifyGroups/GetAllGroupsForASpecificUserTest.php rename to tests/Integration/Requests/General/UserManagement/GetModifyGroups/GetAllGroupsForASpecificUserTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetModifyGroups/GetGroupsTest.php b/tests/Integration/Requests/General/UserManagement/GetModifyGroups/GetGroupsTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetModifyGroups/GetGroupsTest.php rename to tests/Integration/Requests/General/UserManagement/GetModifyGroups/GetGroupsTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetModifyRoles/AddRemoveUserToARoleTest.php b/tests/Integration/Requests/General/UserManagement/GetModifyRoles/AddRemoveUserToARoleTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetModifyRoles/AddRemoveUserToARoleTest.php rename to tests/Integration/Requests/General/UserManagement/GetModifyRoles/AddRemoveUserToARoleTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetModifyRoles/GetAllRolesForASpecificUserTest.php b/tests/Integration/Requests/General/UserManagement/GetModifyRoles/GetAllRolesForASpecificUserTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetModifyRoles/GetAllRolesForASpecificUserTest.php rename to tests/Integration/Requests/General/UserManagement/GetModifyRoles/GetAllRolesForASpecificUserTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetModifyRoles/GetRolesTest.php b/tests/Integration/Requests/General/UserManagement/GetModifyRoles/GetRolesTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetModifyRoles/GetRolesTest.php rename to tests/Integration/Requests/General/UserManagement/GetModifyRoles/GetRolesTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetUsers/GetUserByIdTest.php b/tests/Integration/Requests/General/UserManagement/GetUsers/GetUserByIdTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetUsers/GetUserByIdTest.php rename to tests/Integration/Requests/General/UserManagement/GetUsers/GetUserByIdTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetUsers/GetUsersOfAGroupTest.php b/tests/Integration/Requests/General/UserManagement/GetUsers/GetUsersOfAGroupTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetUsers/GetUsersOfAGroupTest.php rename to tests/Integration/Requests/General/UserManagement/GetUsers/GetUsersOfAGroupTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetUsers/GetUsersOfARoleTest.php b/tests/Integration/Requests/General/UserManagement/GetUsers/GetUsersOfARoleTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetUsers/GetUsersOfARoleTest.php rename to tests/Integration/Requests/General/UserManagement/GetUsers/GetUsersOfARoleTest.php diff --git a/tests/Feature/Requests/General/UserManagement/GetUsers/GetUsersTest.php b/tests/Integration/Requests/General/UserManagement/GetUsers/GetUsersTest.php similarity index 100% rename from tests/Feature/Requests/General/UserManagement/GetUsers/GetUsersTest.php rename to tests/Integration/Requests/General/UserManagement/GetUsers/GetUsersTest.php diff --git a/tests/Feature/Requests/Organization/GetOrganizationsRequestTest.php b/tests/Integration/Requests/Organization/GetOrganizationsRequestTest.php similarity index 100% rename from tests/Feature/Requests/Organization/GetOrganizationsRequestTest.php rename to tests/Integration/Requests/Organization/GetOrganizationsRequestTest.php diff --git a/tests/Feature/Requests/Search/GetSearchRequestTest.php b/tests/Integration/Requests/Search/GetSearchRequestTest.php similarity index 100% rename from tests/Feature/Requests/Search/GetSearchRequestTest.php rename to tests/Integration/Requests/Search/GetSearchRequestTest.php diff --git a/tests/Feature/Requests/SelectList/GetSelectListRequest.php b/tests/Integration/Requests/SelectList/GetSelectListRequest.php similarity index 100% rename from tests/Feature/Requests/SelectList/GetSelectListRequest.php rename to tests/Integration/Requests/SelectList/GetSelectListRequest.php diff --git a/tests/Feature/Requests/Workflow/GetDocumentWorkflowHistoryStepsTest.php b/tests/Integration/Requests/Workflow/GetDocumentWorkflowHistoryStepsTest.php similarity index 100% rename from tests/Feature/Requests/Workflow/GetDocumentWorkflowHistoryStepsTest.php rename to tests/Integration/Requests/Workflow/GetDocumentWorkflowHistoryStepsTest.php diff --git a/tests/Feature/Requests/Workflow/GetDocumentWorkflowHistoryTest.php b/tests/Integration/Requests/Workflow/GetDocumentWorkflowHistoryTest.php similarity index 100% rename from tests/Feature/Requests/Workflow/GetDocumentWorkflowHistoryTest.php rename to tests/Integration/Requests/Workflow/GetDocumentWorkflowHistoryTest.php diff --git a/tests/Manual/RecordGetOrganizationFixtureTest.php b/tests/Manual/RecordGetOrganizationFixtureTest.php new file mode 100644 index 00000000..e403e582 --- /dev/null +++ b/tests/Manual/RecordGetOrganizationFixtureTest.php @@ -0,0 +1,29 @@ +skip() below temporarily. + * 3. Run: vendor/bin/pest tests/Manual/RecordGetOrganizationFixtureTest.php + * 4. Review the JSON for secrets, then restore ->skip(). + */ + +use CodebarAg\DocuWare\Requests\General\Organization\GetOrganization; +use Saloon\Data\RecordedResponse; +use Saloon\MockConfig; + +it('records get-organization Saloon fixture', function () { + MockConfig::setFixturePath(dirname(__DIR__).'/Fixtures/saloon'); + + $response = getConnector()->send(new GetOrganization); + + $fixturePath = dirname(__DIR__).'/Fixtures/saloon/get-organization.json'; + + file_put_contents( + $fixturePath, + RecordedResponse::fromResponse($response)->toFile() + ); + + expect(file_exists($fixturePath))->toBeTrue(); +})->group('manual')->skip('Remove skip to record fixtures against a real DocuWare system.'); diff --git a/tests/Pest.php b/tests/Pest.php index fc959f42..53bb4714 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -3,6 +3,7 @@ use CodebarAg\DocuWare\Connectors\DocuWareConnector; use CodebarAg\DocuWare\DocuWare; use CodebarAg\DocuWare\DTO\Config\ConfigWithCredentials; +use CodebarAg\DocuWare\DTO\Documents\Document; use CodebarAg\DocuWare\Requests\Documents\DocumentsTrashBin\DeleteDocuments; use CodebarAg\DocuWare\Requests\Documents\ModifyDocuments\DeleteDocument; use CodebarAg\DocuWare\Requests\FileCabinets\Search\GetASpecificDocumentFromAFileCabinet; @@ -18,31 +19,41 @@ ->in(__DIR__); uses() + ->group('live') ->beforeEach(function () { $this->connector = getConnector(); - clearFiles(); + clearFiles($this->connector); }) ->afterEach(function () { - setUsersInactive(); + setUsersInactive($this->connector); }) - ->in('Feature'); + ->in('Integration'); -function clearFiles(): void +function clearFiles(DocuWareConnector $connector): void { - $connector = getConnector(); + $fileCabinetId = config('laravel-docuware.tests.file_cabinet_id'); - $paginator = $connector->send(new GetDocumentsFromAFileCabinet( - config('laravel-docuware.tests.file_cabinet_id') - ))->dto(); + $paginator = $connector->send(new GetDocumentsFromAFileCabinet($fileCabinetId))->dto(); + + if ($paginator->documents->isEmpty()) { + emptyTrashForConnector($connector); + + return; + } foreach ($paginator->documents as $document) { $connector->send(new DeleteDocument( - config('laravel-docuware.tests.file_cabinet_id'), + $fileCabinetId, $document->id, ))->dto(); } + emptyTrashForConnector($connector); +} + +function emptyTrashForConnector(DocuWareConnector $connector): void +{ $paginatorRequest = (new DocuWare) ->searchRequestBuilder() ->trashBin() @@ -56,10 +67,8 @@ function clearFiles(): void } } -function setUsersInactive(): void +function setUsersInactive(DocuWareConnector $connector): void { - $connector = getConnector(); - $response = $connector->send(new GetUsers); $users = $response->dto()->filter(function ($user) { @@ -76,7 +85,7 @@ function setUsersInactive(): void /** * @throws Throwable */ -function getConnector(): object +function getConnector(): DocuWareConnector { return new DocuWareConnector(new ConfigWithCredentials( username: config('laravel-docuware.credentials.username'), @@ -98,7 +107,38 @@ function cleanup($connector, $fileCabinetId): void } } -function uploadFiles($connector, $fileCabinetId, $path): array +function documentLooksProcessed(Document $document): bool +{ + return $document->total_pages > 0 + && $document->sections !== null + && $document->sections->isNotEmpty(); +} + +function refreshDocumentAfterProcessing(DocuWareConnector $connector, string $fileCabinetId, int $documentId): Document +{ + $maxAttempts = 60; + $sleepMs = 250; + + for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) { + $document = $connector->send(new GetASpecificDocumentFromAFileCabinet( + $fileCabinetId, + $documentId + ))->dto(); + + if (documentLooksProcessed($document)) { + return $document; + } + + Sleep::for($sleepMs)->milliseconds(); + } + + return $connector->send(new GetASpecificDocumentFromAFileCabinet( + $fileCabinetId, + $documentId + ))->dto(); +} + +function uploadFiles(DocuWareConnector $connector, $fileCabinetId, $path): array { $document = $connector->send(new CreateDataRecord( $fileCabinetId, @@ -112,19 +152,8 @@ function uploadFiles($connector, $fileCabinetId, $path): array 'test-2.pdf', ))->dto(); - Sleep::for(5)->seconds(); // Wait for the files to be uploaded and processed - - // Have to get document again as returned data is incorrect - $document = $connector->send(new GetASpecificDocumentFromAFileCabinet( - $fileCabinetId, - $document->id - ))->dto(); - - // Have to get document2 again as returned data is incorrect - $document2 = $connector->send(new GetASpecificDocumentFromAFileCabinet( - $fileCabinetId, - $document2->id - ))->dto(); + $document = refreshDocumentAfterProcessing($connector, $fileCabinetId, $document->id); + $document2 = refreshDocumentAfterProcessing($connector, $fileCabinetId, $document2->id); return [$document, $document2]; } diff --git a/tests/Support/FixtureDocuWareConnector.php b/tests/Support/FixtureDocuWareConnector.php new file mode 100644 index 00000000..fe2d43a2 --- /dev/null +++ b/tests/Support/FixtureDocuWareConnector.php @@ -0,0 +1,27 @@ + 'codebar\\DocuWare\\Database\\Factories\\'.class_basename($modelName).'Factory', - ); - - // Event::listen(DocuWareResponseLog::class, function (DocuWareResponseLog $event) { - // Log::info('Docuware response', [ - // $event->response->getPendingRequest()->getUrl(), - // ]); - // }); - // - // Event::listen(DocuWareOAuthLog::class, function (DocuWareOAuthLog $event) { - // Log::info($event->message, [ - // 'url' => $event->url, - // 'username' => $event->username, - // ]); - // }); - } - protected function getPackageProviders($app): array { return [ @@ -49,5 +23,7 @@ public function getEnvironmentSetUp($app): void 'database' => ':memory:', 'prefix' => '', ]); + + MockConfig::setFixturePath(__DIR__.'/Fixtures/saloon'); } }