From a46d195eaa9f59462e24b23b743da463a9952b82 Mon Sep 17 00:00:00 2001 From: Lasse Lehtinen Date: Tue, 7 May 2024 15:21:08 +0300 Subject: [PATCH] Initial commit for API v2 --- .github/workflows/run-tests.yml | 54 +++ .gitignore | 3 +- .scrutinizer.yml | 33 -- .styleci.yml | 1 - .travis.yml | 27 -- README.md | 119 +++-- composer.json | 10 +- grumphp.yml | 18 +- src/Bookmarks.php | 94 ---- src/Documents.php | 256 ----------- src/Drafts.php | 106 +++++ src/Exceptions/DocumentFailedConversion.php | 9 - src/Exceptions/DocumentNotFound.php | 9 - src/Exceptions/DocumentStillConverting.php | 9 - src/Exceptions/EmbedNotFound.php | 9 - .../ExceededQuotaForMonthlyUploads.php | 9 - .../ExceededQuotaForUnlistedPublications.php | 9 - src/Exceptions/FolderAlreadyExist.php | 9 - src/Exceptions/InvalidApiKey.php | 9 - src/Exceptions/InvalidFieldFormat.php | 9 - ...NotExist.php => InvalidTokenException.php} | 2 +- src/Exceptions/PageNotFound.php | 9 - src/Exceptions/RequiredFieldIsMissing.php | 9 - src/Folders.php | 111 ----- src/Issuu.php | 130 ++---- src/Publications.php | 69 +++ src/Stacks.php | 41 ++ tests/ApiErrorHandlingTest.php | 162 ------- tests/BookmarksTest.php | 63 --- tests/DocumentsTest.php | 114 ----- tests/DraftsTest.php | 200 ++++++++ tests/FoldersTest.php | 81 ---- tests/PublicationsTest.php | 120 +++++ tests/SampleResponses/bookmarks-delete.json | 5 - tests/SampleResponses/bookmarks-list.json | 31 -- tests/SampleResponses/bookmarks-response.json | 21 - tests/SampleResponses/documents-delete.json | 5 - tests/SampleResponses/documents-list.json | 265 ----------- tests/SampleResponses/documents-response.json | 29 -- .../SampleResponses/draft-getdraftbyslug.json | 42 ++ .../draft-publishdraftbyslug.json | 4 + tests/SampleResponses/drafts-create.json | 17 + tests/SampleResponses/drafts-list.json | 433 +++++++++++++++++ tests/SampleResponses/folders-delete.json | 5 - tests/SampleResponses/folders-list.json | 25 - tests/SampleResponses/folders-response.json | 15 - tests/SampleResponses/publications-list.json | 434 ++++++++++++++++++ tests/SampleResponses/stacks-list.json | 74 +++ tests/SignatureTest.php | 35 -- tests/StacksTest.php | 30 ++ tests/TestCase.php | 67 ++- tests/sample.pdf | Bin 11112 -> 0 bytes 52 files changed, 1832 insertions(+), 1618 deletions(-) create mode 100644 .github/workflows/run-tests.yml delete mode 100644 .scrutinizer.yml delete mode 100644 .styleci.yml delete mode 100644 .travis.yml delete mode 100644 src/Bookmarks.php delete mode 100644 src/Documents.php create mode 100644 src/Drafts.php delete mode 100644 src/Exceptions/DocumentFailedConversion.php delete mode 100644 src/Exceptions/DocumentNotFound.php delete mode 100644 src/Exceptions/DocumentStillConverting.php delete mode 100644 src/Exceptions/EmbedNotFound.php delete mode 100644 src/Exceptions/ExceededQuotaForMonthlyUploads.php delete mode 100644 src/Exceptions/ExceededQuotaForUnlistedPublications.php delete mode 100644 src/Exceptions/FolderAlreadyExist.php delete mode 100644 src/Exceptions/InvalidApiKey.php delete mode 100644 src/Exceptions/InvalidFieldFormat.php rename src/Exceptions/{FileDoesNotExist.php => InvalidTokenException.php} (60%) delete mode 100644 src/Exceptions/PageNotFound.php delete mode 100644 src/Exceptions/RequiredFieldIsMissing.php delete mode 100644 src/Folders.php create mode 100644 src/Publications.php create mode 100644 src/Stacks.php delete mode 100644 tests/ApiErrorHandlingTest.php delete mode 100644 tests/BookmarksTest.php delete mode 100644 tests/DocumentsTest.php create mode 100644 tests/DraftsTest.php delete mode 100644 tests/FoldersTest.php create mode 100644 tests/PublicationsTest.php delete mode 100644 tests/SampleResponses/bookmarks-delete.json delete mode 100644 tests/SampleResponses/bookmarks-list.json delete mode 100644 tests/SampleResponses/bookmarks-response.json delete mode 100644 tests/SampleResponses/documents-delete.json delete mode 100644 tests/SampleResponses/documents-list.json delete mode 100644 tests/SampleResponses/documents-response.json create mode 100644 tests/SampleResponses/draft-getdraftbyslug.json create mode 100644 tests/SampleResponses/draft-publishdraftbyslug.json create mode 100644 tests/SampleResponses/drafts-create.json create mode 100644 tests/SampleResponses/drafts-list.json delete mode 100644 tests/SampleResponses/folders-delete.json delete mode 100644 tests/SampleResponses/folders-list.json delete mode 100644 tests/SampleResponses/folders-response.json create mode 100644 tests/SampleResponses/publications-list.json create mode 100644 tests/SampleResponses/stacks-list.json delete mode 100644 tests/SignatureTest.php create mode 100644 tests/StacksTest.php delete mode 100644 tests/sample.pdf diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 0000000..96400be --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,54 @@ +name: Tests + +on: + push: + paths: + - '**.php' + - '.github/workflows/run-tests.yml' + - 'phpunit.xml.dist' + - 'composer.json' + - 'composer.lock' + +jobs: + test: + runs-on: ${{ matrix.os }} + timeout-minutes: 5 + strategy: + fail-fast: true + matrix: + os: [ubuntu-latest] + php: [8.3, 8.2] + stability: [prefer-lowest, prefer-stable] + + name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - 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 + + - name: Setup problem matchers + run: | + echo "::add-matcher::${{ runner.tool_cache }}/php.json" + echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Install dependencies + run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction + + - name: Run syntax checks + run: vendor/bin/grumphp run --tasks=composer,phplint + + - name: Run security checks + run: vendor/bin/grumphp run --tasks=securitychecker_roave + + - name: Run style checks + run: vendor/bin/grumphp run --tasks=phpcs + + - name: Run static analysis + run: vendor/bin/grumphp run --tasks=phpstan \ No newline at end of file diff --git a/.gitignore b/.gitignore index 029face..718e011 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /vendor composer.lock .idea/ -.phpunit.result.cache \ No newline at end of file +.phpunit.cache +.phpunit.result.cache diff --git a/.scrutinizer.yml b/.scrutinizer.yml deleted file mode 100644 index ac46cad..0000000 --- a/.scrutinizer.yml +++ /dev/null @@ -1,33 +0,0 @@ -filter: - excluded_paths: [tests/*] -checks: - php: - code_rating: true - remove_extra_empty_lines: true - remove_php_closing_tag: true - remove_trailing_whitespace: true - fix_use_statements: - remove_unused: true - preserve_multiple: false - preserve_blanklines: true - order_alphabetically: true - fix_php_opening_tag: true - fix_linefeed: true - fix_line_ending: true - fix_identation_4spaces: true - fix_doc_comments: true -tools: - external_code_coverage: false - php_analyzer: true - php_code_coverage: false - php_code_sniffer: - config: - standard: PSR2 - filter: - paths: ['src'] - php_loc: - enabled: true - excluded_dirs: [vendor, tests] - php_cpd: - enabled: true - excluded_dirs: [vendor, tests] \ No newline at end of file diff --git a/.styleci.yml b/.styleci.yml deleted file mode 100644 index b46b01d..0000000 --- a/.styleci.yml +++ /dev/null @@ -1 +0,0 @@ -preset: psr2 \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e5e1ec6..0000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -language: php - -env: - global: - - setup=stable - -matrix: - fast_finish: true - include: - - php: 7.2 - - php: 7.2 - env: setup=lowest - - php: 7.3 - - php: 7.3 - env: setup=lowest - -sudo: false - -before_install: - - phpenv config-rm xdebug.ini || true - - travis_retry composer self-update - -install: - - if [[ $setup = 'stable' ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-stable --no-suggest; fi - - if [[ $setup = 'lowest' ]]; then travis_retry composer update --prefer-dist --no-interaction --prefer-lowest --prefer-stable --no-suggest; fi - -script: vendor/bin/phpunit diff --git a/README.md b/README.md index b00d6ea..2bb5721 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,51 @@ You can install this package via composer using this command: ```shell composer require lasselehtinen/issuu ``` +## Supported functionality +# Drafts +| Endpoint | Supported | +|----------------------------------------|-----------| +| List drafts | Yes | +| Create a new Draft | Yes | +| Delete a Draft by slug | Yes | +| Update a Draft by slug | Yes | +| Upload a document for a Draft by slug | Yes | +| Publish a Draft by slug | Yes | + +# Publications +| Endpoint | Supported | +|------------------------------------------|-----------| +| List Publications | Yes | +| Get Publication by slug | Yes | +| Delete Publication by slug | Yes | +| Get Publication assets by slug | No | +| Get Publication Fullscreen share by slug | No | +| Get Publication Reader Share URL by slug | No | +| Get Publication QRCode share by slug | No | +| Get Publication Embed code by slug | No | + +# Stacks +| Endpoint | Supported | +|---------------------------------------|-----------| +| List Stacks | Yes | +| Create a new Stack | No | +| Get Stack data by ID | No | +| Delete a Stack by ID | No | +| Update Stack data by ID | No | +| Get Stack Items slug | No | +| Add Stack Item by slug to stack | No | +| Delete Stack Item by slug from stack | No | + +# Stats +| Endpoint | Supported | +|---------------------------------------|-----------| +| Get Stats | No | + +# User +| Endpoint | Supported | +|---------------------------------------|-----------| +| Get User Profile | No | +| Get User Features | No | ## Usage ### Creating a client @@ -16,46 +61,42 @@ First create a new instance with your API key and secret: ```php use lasselehtinen\Issuu\Issuu; -$issuu = new Issuu('apiSecret', 'apiKey'); -``` - -### Bookmarks -```php -use lasselehtinen\Issuu\Bookmarks; - -$bookmarks = new Bookmarks($issuu); - -// Available methods - See the methods DocBlock documentation for information about all available parameters -$bookmarksAdd = $bookmarks->add('publination', '081024182109-9280632f2866416d97634cdccc66715d'); -$bookmarksList = $bookmarks->list(); -$bookmarksDelete = $bookmarks->delete('11b27cd5-ecdc-4c39-b818-8f3c8eca443c'); -``` - -### Documents -```php -use lasselehtinen\Issuu\Documents; - -$documents = new Documents($issuu); - -// Available methods - See the methods DocBlock documentation for information about all available parameters -$documentsUpload = $documents->upload('/path/to/local/file.pdf'); -$documentsUrlUpload = $documents->urlUpload('http://www.example.com/sample.pdf'); -$documentsList = $documents->list(); -$documentsUpdate = $documents->update('racing', 'Rally cars'); -$documentsDelete = $documents->delete('racing'); -``` - -### Folders -```php -use lasselehtinen\Issuu\Folders; - -$folders = new Folders($issuu); +$issuu = new Issuu('apiKey'); +$drafts = new Drafts($issuu); + +$body = [ + 'confirmCopyright' => true, + 'fileUrl' => 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', + 'info' => [ + 'file' => 0, + 'access' => 'PUBLIC', + 'title' => 'Example title', + 'description' => 'Description', + 'preview' => false, + 'type' => 'editorial', + 'showDetectedLinks' => false, + 'downloadable' => false, + 'originalPublishDate' => '1970-01-01T00:00:00.000Z', + ], +]; + +$createDraft = $drafts->create($body); +$drafts->publishDraftBySlug($createDraft->slug); + +// Try few times until the file is converted +for ($i=0; $i < 10; $i++) { + $draft = $drafts->getDraftBySlug($createDraft->slug); + $conversionStatus = $draft->fileInfo->conversionStatus; + + if ($conversionStatus === 'DONE') { + break; + } + + sleep(2); +} + +$publishDraftBySlug = $drafts->publishDraftBySlug($createDraft->slug, ['desiredName' => 'foobar']); -// Available methods - See the methods DocBlock documentation for information about all available parameters -$foldersAdd = $folders->add('Cool stuff'); -$foldersList = $folders->list(); -$foldersUpdate = $folders->update('4c3ba964-60c3-4349-94d0-ff86db2d47c9', 'New folder name'); -$foldersDelete = $folders->delete('4c3ba964-60c3-4349-94d0-ff86db2d47c9'); ``` ## Contributing diff --git a/composer.json b/composer.json index 6e01d26..4ccde9a 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,10 @@ "require-dev": { "phpunit/phpunit": "^9.0", "phpro/grumphp": "^1.4", - "squizlabs/php_codesniffer": "^3.1" + "squizlabs/php_codesniffer": "^3.7", + "php-parallel-lint/php-parallel-lint": "^1.4", + "roave/security-advisories": "latest-dev", + "phpstan/phpstan": "^1.10" }, "autoload": { "psr-4": { @@ -27,5 +30,10 @@ "classmap": [ "tests/TestCase.php" ] + }, + "config": { + "allow-plugins": { + "phpro/grumphp": false + } } } diff --git a/grumphp.yml b/grumphp.yml index e2f48c7..f386c20 100644 --- a/grumphp.yml +++ b/grumphp.yml @@ -21,15 +21,25 @@ grumphp: paths: [] tasks: composer: - securitychecker_local: - phpunit: - config_file: ~ + phplint: + triggered_by: ['php'] + securitychecker_roave: + run_always: true + phpstan: + level: 9 + ignore_patterns: + - "vendor*" + triggered_by: ['php'] + memory_limit: "-1" phpcs: standard: PSR2 tab_width: 4 triggered_by: [php] + warning_severity: 6 ignore_patterns: - "vendor*" - - "tests*" + phpunit: + config_file: ~ + testsuites: [] extensions: [] \ No newline at end of file diff --git a/src/Bookmarks.php b/src/Bookmarks.php deleted file mode 100644 index d32ec14..0000000 --- a/src/Bookmarks.php +++ /dev/null @@ -1,94 +0,0 @@ -issuu = $issuu; - } - - /** - * Adding a bookmark - * @see http://developers.issuu.com/managing-your-publications/bookmarks/add/ - * @param string $documentUsername Owner of the document - * @param string $name Name of the document - * @param integer $page Page in document to bookmark. Default is page 1 - * @param string $folderIds Folder to add this bookmark to. If no value is submitted the bookmark will not be added to any folder - * @return stdClass - */ - public function add(string $documentUsername, string $name, int $page = 1, string $folderIds = null): stdClass - { - $query = [ - 'action' => 'issuu.bookmarks.list', - 'documentUsername' => $documentUsername, - 'name' => $name, - 'page' => $page, - 'folderIds' => $folderIds, - ]; - - $bookmark = $this->issuu->getResponse($query); - - return $bookmark->rsp->_content; - } - - /** - * List bookmarks - * @see http://developers.issuu.com/managing-your-publications/bookmarks/list/ - * @see http://developers.issuu.com/managing-your-publications/bookmarks/list/#resParam Response parameters list - * @param string $folderId Folder containing bookmarks to be listed - * @param string $resultOrder "asc" or "desc". Default value is "asc" - * @param integer $startIndex Zero based index to start pagination - * @param integer $pageSize Maximum number of documents to be returned. Value must be between 0 - 30. Default is 10. - * @param string $bookmarkSortBy Response parameter to sort the result by. Sorting can only be done on a single parameter. Default is no particular sort order. - * @param string $responseParams Comma-separated list of Response parameter to be returned. If no value is submitted all parameters will be returned - * @return stdClass - */ - public function list( - string $folderId = null, - string $resultOrder = 'asc', - int $startIndex = 0, - int $pageSize = 10, - string $bookmarkSortBy = null, - int $responseParams = null - ): stdClass { - $query = [ - 'action' => 'issuu.bookmarks.list', - 'folderId' => $folderId, - 'resultOrder' => $resultOrder, - 'startIndex' => $startIndex, - 'pageSize' => $pageSize, - 'bookmarkSortBy' => $bookmarkSortBy, - 'responseParams' => $responseParams, - ]; - - $bookmark = $this->issuu->getResponse($query); - - return $bookmark->rsp->_content->result; - } - - /** - * Deleting a bookmark - * @see https://developers.issuu.com/managing-your-publications/bookmarks/delete/ - * @param string $bookmarkIds - * @return string - */ - public function delete(string $bookmarkIds): string - { - $query = [ - 'action' => 'issuu.bookmarks.delete', - 'bookmarkIds' => $bookmarkIds, - ]; - - $bookmarks = $this->issuu->getResponse($query); - - return $bookmarks->rsp->stat; - } -} diff --git a/src/Documents.php b/src/Documents.php deleted file mode 100644 index 45d3cfa..0000000 --- a/src/Documents.php +++ /dev/null @@ -1,256 +0,0 @@ -issuu = $issuu; - } - - /** - * Add a document to a user’s profile by specifying its location on the web. - * @see http://developers.issuu.com/managing-your-publications/documents/url-upload/ - * @param string $file Full path to the file - * @param string $name Value determining the URL address of the publication http://issuu.com//docs/ - * @param string $title Title of the publication - * @param string $tags List of keywords describing the content - * @param boolean $commentsAllowed Can other people comment on this document? - * @param string $description Description of the document - * @param boolean $downloadable Can other people download the original document? - * @param string $infoLink URL linking to more information about this document - * @param string $language 2 char language code. See http://developers.issuu.com/managing-your-publications/documents/language-codes/ for allowed values - * @param string $access Must be “public” or “private” - default is “public”. - * @param boolean $explicit If the publication contains explicit content this should be set to “true” - * @param string $category 6 digit code indicating Document Category - See http://developers.issuu.com/managing-your-publications/documents/category/ - * @param string $type 6 digit code indicating Document Type - See http://developers.issuu.com/managing-your-publications/documents/type/ - * @param boolean $ratingAllowed Can other people rate this document? - * @param string $publishDate Datetime when this document was originally published. Default is at the time of upload. See http://developers.issuu.com/managing-your-publications/date-and-time-formats/ for formatting rules - * @param string $folderIds Folders to copy the document to when processing is done. Use method Folders list to find the id of a specific folder - See http://developers.issuu.com/managing-your-publications/folders/list/ - * @return stdClass - */ - public function upload( - string $file, - string $name = null, - string $title = null, - string $tags = null, - bool $commentsAllowed = true, - string $description = null, - bool $downloadable = false, - string $infoLink = null, - string $language = null, - string $access = 'public', - bool $explicit = false, - string $category = null, - string $type = null, - bool $ratingAllowed = true, - string $publishDate = null, - string $folderIds = null - ): stdClass { - // Check that file exists - if (!file_exists($file)) { - throw new FileDoesNotExist(); - } - - $query = [ - 'action' => 'issuu.document.upload', - 'file' => $file, - 'name' => $name, - 'title' => $title, - 'tags' => $tags, - 'commentsAllowed' => var_export($commentsAllowed, true), - 'description' => $description, - 'downloadable' => var_export($downloadable, true), - 'infoLink' => $infoLink, - 'language' => $language, - 'access' => $access, - 'explicit' => var_export($explicit, true), - 'category' => $category, - 'type' => $type, - 'ratingAllowed' => var_export($ratingAllowed, true), - 'publishDate' => $publishDate, - 'folderIds' => $folderIds, - ]; - - // Perform query - $documents = $this->issuu->getResponse($query); - - return $documents->rsp->_content; - } - - /** - * Add a document to a user’s profile by specifying its location on the web. - * @see http://developers.issuu.com/managing-your-publications/documents/url-upload/ - * @param string $slurpUrl URL of document to be uploaded. - * @param string $name Value determining the URL address of the publication http://issuu.com//docs/ - * @param string $title Title of the publication - * @param string $tags List of keywords describing the content - * @param boolean $commentsAllowed Can other people comment on this document? - * @param string $description Description of the document - * @param boolean $downloadable Can other people download the original document? - * @param string $infoLink URL linking to more information about this document - * @param string $language 2 char language code. See http://developers.issuu.com/managing-your-publications/documents/language-codes/ for allowed values - * @param string $access Must be “public” or “private” - default is “public”. - * @param boolean $explicit If the publication contains explicit content this should be set to “true” - * @param string $category 6 digit code indicating Document Category - See http://developers.issuu.com/managing-your-publications/documents/category/ - * @param string $type 6 digit code indicating Document Type - See http://developers.issuu.com/managing-your-publications/documents/type/ - * @param boolean $ratingAllowed Can other people rate this document? - * @param string $publishDate Datetime when this document was originally published. Default is at the time of upload. See http://developers.issuu.com/managing-your-publications/date-and-time-formats/ for formatting rules - * @param string $folderIds Folders to copy the document to when processing is done. Use method Folders list to find the id of a specific folder - See http://developers.issuu.com/managing-your-publications/folders/list/ - * @return stdClass - */ - public function urlUpload( - string $slurpUrl, - string $name = null, - string $title = null, - string $tags = null, - bool $commentsAllowed = true, - string $description = null, - bool $downloadable = false, - string $infoLink = null, - string $language = null, - string $access = 'public', - bool $explicit = false, - string $category = null, - string $type = null, - bool $ratingAllowed = true, - string $publishDate = null, - string $folderIds = null - ): stdClass { - $query = [ - 'action' => 'issuu.document.url_upload', - 'slurpUrl' => $slurpUrl, - 'name' => $name, - 'title' => $title, - 'tags' => $tags, - 'commentsAllowed' => var_export($commentsAllowed, true), - 'description' => $description, - 'downloadable' => var_export($downloadable, true), - 'infoLink' => $infoLink, - 'language' => $language, - 'access' => $access, - 'explicit' => var_export($explicit, true), - 'category' => $category, - 'type' => $type, - 'ratingAllowed' => var_export($ratingAllowed, true), - 'publishDate' => $publishDate, - 'folderIds' => $folderIds, - ]; - - // Perform query - $documents = $this->issuu->getResponse($query); - - return $documents->rsp->_content; - } - - /** - * Get the list of documents from Issuu - * @see http://developers.issuu.com/managing-your-publications/documents/list/ - * @param string $documentStates Comma-separated list document states indicated by a single char - * @param string $access "public" or "private" - * @param string $origins Comma-separated list of document origins. - * @param string $orgDocTypes Comma-separated list of original document formats - * @param string $orgDocName Original filename of document - * @param string $resultOrder "asc" or "desc" - * @param integer $startIndex Zero based index to start pagination from - * @param integer $pageSize Maximum number of documents to be returned. Value must be between 0 - 30. Default is 10 - * @param string $documentSortBy Reponse parameter to sort the result by. Sorting can only be done on a single parameter. Default is no particular sort order - * @param string $responseParams Comma-separated list of response parameters to be returned. - * @return stdClass - */ - public function list( - string $documentStates = null, - string $access = null, - string $origins = null, - string $orgDocTypes = null, - string $orgDocName = null, - string $resultOrder = 'asc', - int $startIndex = 0, - int $pageSize = 10, - string $documentSortBy = null, - string $responseParams = null - ): stdClass { - $query = [ - 'action' => 'issuu.documents.list', - 'documentStates' => $documentStates, - 'access' => $access, - 'origins' => $origins, - 'orgDocTypes' => $orgDocTypes, - 'orgDocName' => $orgDocName, - 'resultOrder' => $resultOrder, - 'startIndex' => $startIndex, - 'pageSize' => $pageSize, - 'documentSortBy' => $documentSortBy, - 'responseParams' => $responseParams, - ]; - - $documents = $this->issuu->getResponse($query); - - return $documents->rsp->_content->result; - } - - /** - * Update a document with the given information. - * @see http://developers.issuu.com/managing-your-publications/documents/update/ - * @param string $name Value determining the URL address of the publication http://issuu.com//docs/ - * @param string $title Title of the publication - * @param string $tags List of keywords describing the content - * @param string $description Description of the document - * @param string $language 2 char language code. See http://developers.issuu.com/managing-your-publications/documents/language-codes/ for allowed values - * @param string $category 6 digit code indicating Document Category - See http://developers.issuu.com/managing-your-publications/documents/category/ - * @param string $type 6 digit code indicating Document Type - See http://developers.issuu.com/managing-your-publications/documents/type/ - * @param string $publishDate Datetime when this document was originally published. Default is at the time of upload. See http://developers.issuu.com/managing-your-publications/date-and-time-formats/ for formatting rules - * @return stdClass - */ - public function update( - string $name, - string $title = null, - string $tags = null, - string $description = null, - string $language = null, - string $category = null, - string $type = null, - string $publishDate = null - ): stdClass { - $query = [ - 'action' => 'issuu.document.update', - 'name' => $name, - 'title' => $title, - 'tags' => $tags, - 'description' => $description, - 'language' => $language, - 'category' => $category, - 'type' => $type, - 'publishDate' > $publishDate, - ]; - - $documents = $this->issuu->getResponse($query); - - return $documents->rsp->_content; - } - - /** - * Delete one or more documents including all comments and ratings. - * @param string $names Comma-separated list of document names - * @return string - */ - public function delete(string $names): string - { - $query = [ - 'action' => 'issuu.document.delete', - 'names' => $names, - ]; - - $documents = $this->issuu->getResponse($query); - - return $documents->rsp->stat; - } -} diff --git a/src/Drafts.php b/src/Drafts.php new file mode 100644 index 0000000..2f22ec6 --- /dev/null +++ b/src/Drafts.php @@ -0,0 +1,106 @@ +issuu = $issuu; + } + + /** + * Get the list of drafts from Issuu + * @see https://api.issuu.com/v2/reference/#get-/publications + * @param int $size Determines the number of publications to return per page. + * @param int $page Specifies the page number to return. + * @param string $q A regular expression that is applied to the titles and descriptions of the drafts and returns only the drafts that match the expression + * @return stdClass + */ + public function list( + int $size = 10, + int $page = 1, + string $q = '', + ): stdClass { + $queryParameters = [ + 'size' => $size, + 'page' => $page, + 'q' => $q, + ]; + + return $this->issuu->getResponse(method: 'GET', endpoint: 'drafts', queryParameters: $queryParameters); + } + + /** + * Create a new Draft + * @see https://api.issuu.com/v2/reference/#post-/drafts + * @param array $body The data to create the draft with. + * @return stdClass + */ + public function create( + array $body = [], + ): stdClass { + return $this->issuu->getResponse(method: 'POST', endpoint: 'drafts', body: $body); + } + + /** + * Get Draft by slug + * @see https://api.issuu.com/v2/reference/#get-/drafts/-slug- + * @param string $slug The unique identifier of the draft to retrieve. This should be a string that corresponds to the slug of a draft. + * @return stdClass + */ + public function getDraftBySlug( + string $slug, + ): stdClass { + return $this->issuu->getResponse(method: 'GET', endpoint: 'drafts/'.$slug); + } + + /** + * Get Draft by slug + * @see https://api.issuu.com/v2/reference/#post-/drafts/-slug-/publish + * @param string $slug The unique identifier of the draft to publish. This should be a string that corresponds to the slug of a draft. + * @param array $body The data to publish the draft with. + * @return stdClass + */ + public function publishDraftBySlug( + string $slug, + array $body, + ): stdClass { + return $this->issuu->getResponse(method: 'POST', endpoint: 'drafts/'.$slug.'/publish', body: $body); + } + + /** + * Delete a Draft by slug + * @see https://api.issuu.com/v2/reference/#delete-/drafts/-slug- + * @param string $slug The unique identifier of the draft to delete. This should be a string that corresponds to the slug of a draft. + * @return null + */ + public function deleteDraftBySlug( + string $slug, + ): null { + $this->issuu->getResponse(method: 'DELETE', endpoint: 'drafts/'.$slug); + return null; + } + + /** + * Update a Draft by slug + * @see https://api.issuu.com/v2/reference/#patch-/drafts/-slug- + * @param string $slug The unique identifier of the draft to update. This should be a string that corresponds to the slug of a draft. + * @param array $body The data to update the draft with. + * @return stdClass + */ + public function updateDraftBySlug( + string $slug, + array $body = [], + ): stdClass { + return $this->issuu->getResponse(method: 'PATCH', endpoint: 'drafts/'.$slug, body: $body); + } +} diff --git a/src/Exceptions/DocumentFailedConversion.php b/src/Exceptions/DocumentFailedConversion.php deleted file mode 100644 index 099cf0d..0000000 --- a/src/Exceptions/DocumentFailedConversion.php +++ /dev/null @@ -1,9 +0,0 @@ -issuu = $issuu; - } - - /** - * Adding a folder - * @see https://developers.issuu.com/managing-your-publications/folders/add/ - * @param string $folderName Name of the folder. Must be different from other folder names - * @param string $folderDescription Description of folder content - * @return stdClass - */ - public function add(string $folderName, string $folderDescription = null): stdClass - { - $query = [ - 'action' => 'issuu.folders.add', - 'folderName' => $folderName, - 'folderDescription' => $folderDescription, - ]; - - $folder = $this->issuu->getResponse($query); - - return $folder->rsp->_content; - } - - /** - * List folders - * @see https://developers.issuu.com/managing-your-publications/folders/list/ - * @param string $resultOrder "asc" or "desc" - * @param integer $startIndex Zero based index to start pagination from - * @param integer $pageSize Maximum number of documents to be returned. Value must be between 0 - 30. Default is 10 - * @param string $folderSortBy Response parameter to sort the result by. Sorting can only be done on a single parameter. Default is no particular sort order - * @param string $responseParams Comma-separated list of response parameters to be returned. - * @return stdClass - */ - public function list( - string $resultOrder = 'asc', - int $startIndex = 0, - int $pageSize = 10, - string $folderSortBy = null, - string $responseParams = null - ): stdClass { - $query = [ - 'action' => 'issuu.folders.list', - 'resultOrder' => $resultOrder, - 'startIndex' => $startIndex, - 'pageSize' => $pageSize, - 'folderSortBy' => $folderSortBy, - 'responseParams' => $responseParams, - ]; - - $folders = $this->issuu->getResponse($query); - - return $folders->rsp->_content->result; - } - - /** - * Update a folder - * @see https://developers.issuu.com/managing-your-publications/folders/update/ - * @param string $folderId The folder to be updated - * @param string $folderName New name of the folder - * @param string $folderDescription New description of the folder - * @return stdClass - */ - public function update(string $folderId, string $folderName = null, string $folderDescription = null): stdClass - { - $query = [ - 'action' => 'issuu.folders.update', - 'folderId' => $folderId, - 'folderName' => $folderName, - 'folderDescription' => $folderDescription, - ]; - - $folder = $this->issuu->getResponse($query); - - return $folder->rsp->_content; - } - - /** - * Deleting a folder - * @see https://developers.issuu.com/managing-your-publications/folders/delete/ - * @param string $folderIds - * @return string - */ - public function delete(string $folderIds): string - { - $query = [ - 'action' => 'issuu.folders.delete', - 'folderIds' => $folderIds, - ]; - - $folders = $this->issuu->getResponse($query); - - return $folders->rsp->stat; - } -} diff --git a/src/Issuu.php b/src/Issuu.php index 03c8b36..af1b343 100644 --- a/src/Issuu.php +++ b/src/Issuu.php @@ -1,114 +1,77 @@ apiSecret = $apiSecret; $this->apiKey = $apiKey; - $this->client = $client ?: new Client(); + $this->client = $client ?: new Client(['base_uri' => 'https://api.issuu.com/v2/']); } /** - * Create a Issuu signature for the API requests + * Make a request to Issuu API * - * @see http://developers.issuu.com/signing-requests/ - * @param array $queryParameters - * @return string + * @param string $method + * @param string $endpoint + * @param array $queryParameters + * @param array $body + * @return stdClass */ - private function getSignature(array $queryParameters): string + public function getResponse(string $method, string $endpoint, array $queryParameters = [], array $body = []): stdClass { - // Sort request parameters alphabetically - ksort($queryParameters); - - $signature = $this->apiSecret; - - // Concatenate in order your API secret key and request name-value pairs (e.g. SECRETbar2baz3foo1) - foreach ($queryParameters as $key => $value) { - $signature .= $key . $value; + // Convert booleans to string + foreach ($queryParameters as $key => $queryParameter) { + if (is_bool($queryParameter)) { + $queryParameters[$key] = var_export($queryParameter, true); + } } - return md5($signature); - } - - public function getResponse(array $queryParameters): stdClass - { - $queryParameters['apiKey'] = $this->apiKey; - - // Force format to JSON - $queryParameters['format'] = 'json'; - - // Remove null/empty parameters - $queryParameters = array_filter($queryParameters); - $queryParameters['signature'] = $this->getSignature($queryParameters); - $response = $this->client->post('http://api.issuu.com/1_0', [ + $response = $this->client->request($method, $endpoint, [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $this->apiKey, + ], 'query' => $queryParameters, + RequestOptions::JSON => $body, ]); - $json = json_decode($response->getBody()->getContents()); - // Check for errors + $json = json_decode($response->getBody()->getContents(), false); + + // Some endpoints return empty response, return empty stdClass in those cases + if ($json instanceof stdClass === false) { + return new stdClass(); + } + if ($this->responseHasErrors($json)) { - switch ($this->getErrorCode($json)) { - case '010': - throw new InvalidApiKey(); - break; - case '200': - throw new RequiredFieldIsMissing(); - break; - case '201': - throw new InvalidFieldFormat(); - break; - case '300': - throw new DocumentNotFound(); - break; - case '311': - throw new PageNotFound(); - break; - case '294': - throw new ExceededQuotaForUnlistedPublications(); - break; - case '295': - throw new ExceededQuotaForMonthlyUploads(); - break; - case '307': - throw new DocumentStillConverting(); - break; - case '308': - throw new DocumentFailedConversion(); - break; - case '090': - throw new EmbedNotFound(); - break; - case '261': - throw new FolderAlreadyExist(); - break; - } + $this->throwException($json); } return $json; @@ -116,11 +79,16 @@ public function getResponse(array $queryParameters): stdClass public function responseHasErrors(stdClass $json): bool { - return isset($json->rsp->_content->error); + return isset($json->message); } - public function getErrorCode(stdClass $json): string + public function throwException(stdClass $json): bool { - return $json->rsp->_content->error->code; + switch ($json->message) { + case 'Invalid token': + throw new InvalidTokenException('The given token is invalid.'); + default: + throw new Exception($json->message); + } } } diff --git a/src/Publications.php b/src/Publications.php new file mode 100644 index 0000000..7254ed6 --- /dev/null +++ b/src/Publications.php @@ -0,0 +1,69 @@ +issuu = $issuu; + } + + /** + * Get the list of publications from Issuu + * @see https://api.issuu.com/v2/reference/#get-/publications + * @param int $size Determines the number of publications to return per page. + * @param int $page Specifies the page number to return. + * @param string $state Filters the publications to return based on their state. Allowed: ALL ┃ PUBLISHED ┃ SCHEDULED ┃ UNLISTED + * @param string $q A regular expression that is applied to the titles and descriptions of the publications and returns only the publications that match the expression. + * @return stdClass + */ + public function list( + int $size = 10, + int $page = 1, + string $state = 'ALL', + string $q = '', + ): stdClass { + $queryParameters = [ + 'size' => $size, + 'page' => $page, + 'state' => $state, + 'q' => $q, + ]; + + return $this->issuu->getResponse(method: 'GET', endpoint: 'publications', queryParameters: $queryParameters); + } + + /** + * Get Publication by slug + * @see https://api.issuu.com/v2/reference/#get-/publications/-slug- + * @param string $slug The unique identifier of the publication to retrieve. This should be a string that corresponds to the slug of a publication. + * @return stdClass + */ + public function getPublicationBySlug( + string $slug, + ): stdClass { + return $this->issuu->getResponse(method: 'GET', endpoint: 'publications/'.$slug); + } + + /** + * Delete a Publication by slug + * @see https://api.issuu.com/v2/reference/#delete-/publications/-slug- + * @param string $slug The unique identifier of the publication to delete. This should be a string that corresponds to the slug of a publication. + * @return null + */ + public function deletePublicationBySlug( + string $slug, + ): null { + $this->issuu->getResponse(method: 'DELETE', endpoint: 'publications/'.$slug); + return null; + } +} diff --git a/src/Stacks.php b/src/Stacks.php new file mode 100644 index 0000000..c649baf --- /dev/null +++ b/src/Stacks.php @@ -0,0 +1,41 @@ +issuu = $issuu; + } + + /** + * Get the list of Stacks from Issuu + * @see https://api.issuu.com/v2/reference/#get-/stacks + * @param int $size Determines the number of stacks to return per page. + * @param int $page Specifies the page number to return. + * @param bool $showUnlisted Include unlisted stacks in the list of stacks. + * @return stdClass + */ + public function list( + int $size = 10, + int $page = 1, + bool $showUnlisted = false, + ): stdClass { + $queryParameters = [ + 'size' => $size, + 'page' => $page, + 'showUnlisted' => $showUnlisted, + ]; + + return $this->issuu->getResponse(method: 'GET', endpoint: 'stacks', queryParameters: $queryParameters); + } +} diff --git a/tests/ApiErrorHandlingTest.php b/tests/ApiErrorHandlingTest.php deleted file mode 100644 index d173f2e..0000000 --- a/tests/ApiErrorHandlingTest.php +++ /dev/null @@ -1,162 +0,0 @@ -createMockedInstance($response); - - $this->expectException(InvalidApiKey::class); - $issuu->getResponse([]); - } - - /** - * Test that missing a required field throws an exception - * @return void - */ - public function testMissingRequiredFieldThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"200","message":"Required field is missing"}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(RequiredFieldIsMissing::class); - $issuu->getResponse([]); - } - - /** - * Test using invalid format in a field throws an exception - * @return void - */ - public function testUsingInvalidFormatInParameterThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"201","message":"Invalid field format"}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(InvalidFieldFormat::class); - $issuu->getResponse([]); - } - - /** - * Trying to request a missing document throws an exception - * @return void - */ - public function testRequestingNonExistantDocumentThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"300","message":"Document not found"}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(DocumentNotFound::class); - $issuu->getResponse([]); - } - - /** - * Trying to request a non-existant page throws an expection - * @return void - */ - public function testRequestingNonExistantPageThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"311","message":"Page not found"}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(PageNotFound::class); - $issuu->getResponse([]); - } - - /** - * Exceeding allowed quota for unlisted publications throws an exception - * @return void - */ - public function testExceedingQuotaForUnlistedPublicationsThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"294","message":"Exceeding allowed amount of unlisted publications"}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(ExceededQuotaForUnlistedPublications::class); - $issuu->getResponse([]); - } - - /** - * Exceeding allowed quota for monthly uploades throws an exception - * @return void - */ - public function testExceedingQuotaForMonthlyUploadsThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"295","message":"Exceeding allowed amount of monthly uploads"}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(ExceededQuotaForMonthlyUploads::class); - $issuu->getResponse([]); - } - - /** - * Trying to access a document that is still being converted - * @return void - */ - public function testTryingToAccessDocumentStillBeingConvertedThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"307","message":"Document still converting"}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(DocumentStillConverting::class); - $issuu->getResponse([]); - } - - /** - * Document failed conversion - * @return void - */ - public function testDocumentThatFailedConversionThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"308","message":"Document failed conversion."}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(DocumentFailedConversion::class); - $issuu->getResponse([]); - } - - /** - * Trying to access non-existant embed throws an exception - * @return [type] [description] - */ - public function testRequestingNonExistantEmbedThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"090","message":"Embed not found"}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(EmbedNotFound::class); - $issuu->getResponse([]); - } - - /** - * Trying to create a folder that already exists throws an exception - * @return void - */ - public function testCreatingAnExistingFolderThrowsAnException() - { - $response = '{"rsp":{"_content":{"error":{"code":"261","message":"Folder name exists for user"}},"stat":"fail"}}'; - $issuu = $this->createMockedInstance($response); - - $this->expectException(FolderAlreadyExist::class); - $issuu->getResponse([]); - } -} diff --git a/tests/BookmarksTest.php b/tests/BookmarksTest.php deleted file mode 100644 index 59828ed..0000000 --- a/tests/BookmarksTest.php +++ /dev/null @@ -1,63 +0,0 @@ -createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/bookmarks-response.json')); - $bookmarks = new Bookmarks($issuu); - $bookmarksAdd = $bookmarks->add('publination', '081024182109-9280632f2866416d97634cdccc66715d'); - - // Additional checks - $this->assertIsObject($bookmarksAdd); - $this->assertIsObject($bookmarksAdd->bookmark); - $this->assertSame('Wild Swim: The best outdoor swims across Britain', $bookmarksAdd->bookmark->title); - } - - /** - * Test listing bookmarks - * @return void - */ - public function testListingBookmarks() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/bookmarks-list.json')); - $bookmarks = new Bookmarks($issuu); - $bookmarksList = $bookmarks->list(); - - $this->assertIsObject($bookmarksList); - - // Pagination attributes - $this->assertSame(1, $bookmarksList->totalCount); - $this->assertSame(0, $bookmarksList->startIndex); - $this->assertSame(10, $bookmarksList->pageSize); - $this->assertSame(false, $bookmarksList->more); - - // Additional checks - $this->assertIsArray($bookmarksList->_content); - $this->assertCount(1, $bookmarksList->_content); - $this->assertIsObject($bookmarksList->_content[0]->bookmark); - } - - /** - * Test deleting a bookmark - * @return void - */ - public function testDeletingABookmark() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/bookmarks-delete.json')); - $bookmarks = new Bookmarks($issuu); - $bookmarksDelete = $bookmarks->delete('11b27cd5-ecdc-4c39-b818-8f3c8eca443c'); - - $this->assertSame('ok', $bookmarksDelete); - } -} diff --git a/tests/DocumentsTest.php b/tests/DocumentsTest.php deleted file mode 100644 index 3849714..0000000 --- a/tests/DocumentsTest.php +++ /dev/null @@ -1,114 +0,0 @@ -createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/documents-list.json')); - $documents = new Documents($issuu); - $documentsList = $documents->list(); - - $this->assertIsObject($documentsList); - - // Pagination attributes - $this->assertSame(1349, $documentsList->totalCount); - $this->assertSame(0, $documentsList->startIndex); - $this->assertSame(10, $documentsList->pageSize); - $this->assertSame(true, $documentsList->more); - - // Additional checks - $this->assertIsArray($documentsList->_content); - $this->assertCount(10, $documentsList->_content); - $this->assertIsObject($documentsList->_content[0]->document); - } - - /** - * Test document upload through URL - * @return void - */ - public function testUrlUploadingADocument() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/documents-response.json')); - $documents = new Documents($issuu); - $documentsUpload = $documents->urlUpload('http://www.example.com/sample.pdf'); - - $this->assertIsObject($documentsUpload); - - // Additional checks - $this->assertIsObject($documentsUpload); - $this->assertIsObject($documentsUpload->document); - $this->assertSame('public', $documentsUpload->document->access); - } - - /** - * Test document upload - * @return void - */ - public function testUploadingADocument() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/documents-response.json')); - $documents = new Documents($issuu); - $documentsUpload = $documents->upload(__DIR__ . '/sample.pdf'); - - $this->assertIsObject($documentsUpload); - - // Additional checks - $this->assertIsObject($documentsUpload); - $this->assertIsObject($documentsUpload->document); - $this->assertSame('public', $documentsUpload->document->access); - } - - /** - * Non existing file should throw an exception - * @return void - */ - public function testUploadingNonExistantFileThrowsException() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/documents-response.json')); - $documents = new Documents($issuu); - - $this->expectException(FileDoesNotExist::class); - $documentsUpload = $documents->upload('nonexistant.pdf'); - } - - /** - * Test updating a document - * @return void - */ - public function testUpdatingADocument() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/documents-response.json')); - $documents = new Documents($issuu); - $documentsUpload = $documents->update('racing'); - - $this->assertIsObject($documentsUpload); - - // Additional checks - $this->assertIsObject($documentsUpload); - $this->assertIsObject($documentsUpload->document); - $this->assertSame('public', $documentsUpload->document->access); - } - - /** - * Test deleting a document - * @return void - */ - public function testDeletingADocument() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/documents-delete.json')); - $documents = new Documents($issuu); - $documentsUpload = $documents->delete('racing'); - - $this->assertSame('ok', $documentsUpload); - } -} diff --git a/tests/DraftsTest.php b/tests/DraftsTest.php new file mode 100644 index 0000000..b3f9f71 --- /dev/null +++ b/tests/DraftsTest.php @@ -0,0 +1,200 @@ +issuu); + $draftsList = $drafts->list(); + + $this->assertIsObject($draftsList); + + // Pagination attributes + $this->assertIsInt($draftsList->count); + $this->assertIsInt($draftsList->pageSize); + + // Additional checks + $this->assertIsArray($draftsList->results); + $this->assertIsString($draftsList->results[0]->slug); + } + + /** + * Test creating drafts + * + * @return void + */ + public function testCreatingDrafts() + { + $drafts = new Drafts($this->issuu); + + $body = [ + 'confirmCopyright' => true, + 'fileUrl' => 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', + 'info' => [ + 'file' => 0, + 'access' => 'PUBLIC', + 'title' => 'Test document', + 'description' => 'Description', + 'preview' => false, + 'type' => 'editorial', + 'showDetectedLinks' => false, + 'downloadable' => false, + 'originalPublishDate' => '1970-01-01T00:00:00.000Z', + ], + ]; + + $createDraft = $drafts->create($body); + + $this->assertIsObject($createDraft); + $this->assertIsString($createDraft->slug); + } + + /** + * Test getting draft by slug + * + * @return void + */ + public function testGettingDraftBySlug() + { + $drafts = new Drafts($this->issuu); + + $getDraftBySlug = $drafts->getDraftBySlug('zp0m1zti7ir'); + + $this->assertIsObject($getDraftBySlug); + $this->assertIsString($getDraftBySlug->slug); + $this->assertSame('zp0m1zti7ir', $getDraftBySlug->slug); + } + + /** + * Test publishing draft by slug + * + * @return void + */ + public function testPublishingDraftBySlug() + { + $drafts = new Drafts($this->issuu); + + $body = [ + 'confirmCopyright' => true, + 'fileUrl' => 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', + 'info' => [ + 'file' => 0, + 'access' => 'PUBLIC', + 'title' => 'Test document', + 'description' => 'Description', + 'preview' => false, + 'type' => 'editorial', + 'showDetectedLinks' => false, + 'downloadable' => false, + 'originalPublishDate' => '1970-01-01T00:00:00.000Z', + ], + ]; + + $createDraft = $drafts->create($body); + + // Try few times until the file is converted + for ($i=0; $i < 10; $i++) { + $draft = $drafts->getDraftBySlug($createDraft->slug); + $conversionStatus = $draft->fileInfo->conversionStatus; + + if ($conversionStatus === 'DONE') { + break; + } + + sleep(2); + } + + $publishDraftBySlug = $drafts->publishDraftBySlug($createDraft->slug, ['desiredName' => 'foobar']); + $this->assertIsObject($publishDraftBySlug); + $this->assertIsString($publishDraftBySlug->location); + $this->assertIsString($publishDraftBySlug->publicLocation); + } + + /** + * Test deleting draft by slug + * + * @return void + */ + public function testDeletingDraftBySlug() + { + $drafts = new Drafts($this->issuu); + + $body = [ + 'confirmCopyright' => true, + 'fileUrl' => 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', + 'info' => [ + 'file' => 0, + 'access' => 'PUBLIC', + 'title' => 'Test document', + 'description' => 'Description', + 'preview' => false, + 'type' => 'editorial', + 'showDetectedLinks' => false, + 'downloadable' => false, + 'originalPublishDate' => '1970-01-01T00:00:00.000Z', + ], + ]; + + // Create draft + $createDraft = $drafts->create($body); + $getDraftBySlug = $drafts->getDraftBySlug($createDraft->slug); + $this->assertIsObject($getDraftBySlug); + $this->assertIsString($getDraftBySlug->slug); + + // Delete draft by slug + $drafts->deleteDraftBySlug($createDraft->slug); + + // Trying to get draft by slug should throw 404 error + $this->expectException(\GuzzleHttp\Exception\ClientException::class); + $getDraftBySlug = $drafts->getDraftBySlug($createDraft->slug); + } + + /** + * Test updating draft by slug + * + * @return void + */ + public function testUpdatingDraftBySlug() + { + $drafts = new Drafts($this->issuu); + + $body = [ + 'confirmCopyright' => true, + 'fileUrl' => 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', + 'info' => [ + 'file' => 0, + 'access' => 'PUBLIC', + 'title' => 'Test document', + 'description' => 'Description', + 'preview' => false, + 'type' => 'editorial', + 'showDetectedLinks' => false, + 'downloadable' => false, + 'originalPublishDate' => '1970-01-01T00:00:00.000Z', + ], + ]; + + $createDraft = $drafts->create($body); + $this->assertIsObject($createDraft); + $this->assertIsString($createDraft->slug); + + // Check before and after update + $getDraftBySlug = $drafts->getDraftBySlug($createDraft->slug); + $this->assertSame('Description', $getDraftBySlug->changes->description); + + $body['info']['description'] = 'Updated description'; + $drafts->updateDraftBySlug($createDraft->slug, $body); + + $getDraftBySlug = $drafts->getDraftBySlug($createDraft->slug); + $this->assertSame('Updated description', $getDraftBySlug->changes->description); + } +} diff --git a/tests/FoldersTest.php b/tests/FoldersTest.php deleted file mode 100644 index 054b7d3..0000000 --- a/tests/FoldersTest.php +++ /dev/null @@ -1,81 +0,0 @@ -createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/folders-response.json')); - $folders = new Folders($issuu); - $foldersAdd = $folders->add('Cool stuff'); - - // Additional checks - $this->assertIsObject($foldersAdd); - $this->assertIsObject($foldersAdd->folder); - $this->assertSame('Stuff I have collected', $foldersAdd->folder->description); - } - - /** - * Test listing folders - * @return void - */ - public function testListingFolders() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/folders-list.json')); - $folders = new Folders($issuu); - $foldersList = $folders->list(); - - $this->assertIsObject($foldersList); - - // Pagination attributes - $this->assertSame(1, $foldersList->totalCount); - $this->assertSame(0, $foldersList->startIndex); - $this->assertSame(10, $foldersList->pageSize); - $this->assertSame(false, $foldersList->more); - - // Additional checks - $this->assertIsArray($foldersList->_content); - $this->assertCount(1, $foldersList->_content); - $this->assertIsObject($foldersList->_content[0]->folder); - } - - /** - * Test updating a folder - * @return void - */ - public function testUpdatingAFolder() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/folders-response.json')); - $folders = new Folders($issuu); - $foldersUpdate = $folders->update('4c3ba964-60c3-4349-94d0-ff86db2d47c9'); - - $this->assertIsObject($foldersUpdate); - - // Additional checks - $this->assertIsObject($foldersUpdate); - $this->assertIsObject($foldersUpdate->folder); - $this->assertSame('Stuff I have collected', $foldersUpdate->folder->description); - } - - /** - * Test deleting a document - * @return void - */ - public function testDeletingADocument() - { - $issuu = $this->createMockedInstance(file_get_contents(__DIR__ . '/SampleResponses/folders-delete.json')); - $folders = new Folders($issuu); - $foldersDelete = $folders->delete('4c3ba964-60c3-4349-94d0-ff86db2d47c9'); - - $this->assertSame('ok', $foldersDelete); - } -} diff --git a/tests/PublicationsTest.php b/tests/PublicationsTest.php new file mode 100644 index 0000000..18f7acd --- /dev/null +++ b/tests/PublicationsTest.php @@ -0,0 +1,120 @@ +issuu); + $publicationsList = $publications->list(); + + $this->assertIsObject($publicationsList); + + // Pagination attributes + $this->assertIsInt($publicationsList->count); + $this->assertSame(10, $publicationsList->pageSize); + + // Additional checks + $this->assertIsArray($publicationsList->results); + $this->assertCount(10, $publicationsList->results); + $this->assertIsString($publicationsList->results[0]->state); + } + + /** + * Test getting Publications by slug + * + * @return void + */ + public function testGettingPublicationBySlug() + { + $slug = $this->createPublication(); + + $publications = new Publications($this->issuu); + + $getPublicationBySlug = $publications->getPublicationBySlug($slug); + $this->assertIsObject($getPublicationBySlug); + $this->assertIsString($getPublicationBySlug->slug); + $this->assertSame($slug, $getPublicationBySlug->slug); + } + + /** + * Test deleting publication by slug + * + * @return void + */ + public function testDeletingPublicationsBySlug() + { + $slug = $this->createPublication(); + + $publications = new Publications($this->issuu); + + // Publication should still exist + $getPublicationBySlug = $publications->getPublicationBySlug($slug); + $this->assertIsObject($getPublicationBySlug); + $this->assertIsString($getPublicationBySlug->slug); + $this->assertSame($slug, $getPublicationBySlug->slug); + + // Delete Publication + $publications->deletePublicationBySlug($slug); + + // Trying to get Publication by slug should throw 404 error + $this->expectException(\GuzzleHttp\Exception\ClientException::class); + $getPublicationBySlug = $publications->getPublicationBySlug($slug); + } + + /** + * Helper method to create Draft and publish it + * + * @return string + */ + public function createPublication() + { + $drafts = new Drafts($this->issuu); + + $body = [ + 'confirmCopyright' => true, + 'fileUrl' => 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf', + 'info' => [ + 'file' => 0, + 'access' => 'PUBLIC', + 'title' => 'Test document', + 'description' => 'Description', + 'preview' => false, + 'type' => 'editorial', + 'showDetectedLinks' => false, + 'downloadable' => false, + 'originalPublishDate' => '1970-01-01T00:00:00.000Z', + ], + ]; + + // Create draft and publish it + $createDraft = $drafts->create($body); + + // Try few times until the file is converted + for ($i=0; $i < 10; $i++) { + $draft = $drafts->getDraftBySlug($createDraft->slug); + $conversionStatus = $draft->fileInfo->conversionStatus; + + if ($conversionStatus === 'DONE') { + break; + } + + sleep(2); + } + + $publishDraftBySlug = $drafts->publishDraftBySlug($createDraft->slug, ['desiredName' => 'foobar']); + + return $createDraft->slug; + } +} diff --git a/tests/SampleResponses/bookmarks-delete.json b/tests/SampleResponses/bookmarks-delete.json deleted file mode 100644 index 45ae4de..0000000 --- a/tests/SampleResponses/bookmarks-delete.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rsp": { - "stat": "ok" - } -} \ No newline at end of file diff --git a/tests/SampleResponses/bookmarks-list.json b/tests/SampleResponses/bookmarks-list.json deleted file mode 100644 index 2c11b4c..0000000 --- a/tests/SampleResponses/bookmarks-list.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "rsp": { - "_content": { - "result": { - "totalCount": 1, - "startIndex": 0, - "pageSize": 10, - "more": false, - "_content": [ - { - "bookmark": { - "bookmarkId": "11b27cd5-ecdc-4c39-b818-8f3c8eca443c", - "username": "travelmagazine", - "documentId": "081024182109-9280632f2866416d97634cdccc66715d", - "documentUsername": "publination", - "name": "wildswim", - "title": "Wild Swim: The best outdoor swims across Britain", - "description": "Wild Swim by Kate Rew is the definitive guide to over 300 beautiful outdoor swims in rivers, lakes, tidal pools, the sea and lidos across Britain. By the founder of the Outdoor Swimming Society.", - "page": 1, - "created": "2009-06-22T07:54:17.000Z", - "folders": [ - "52ab7b36-946d-45b2-a446-f95e84b2682e" - ] - } - } - ] - } - }, - "stat": "ok" - } -} \ No newline at end of file diff --git a/tests/SampleResponses/bookmarks-response.json b/tests/SampleResponses/bookmarks-response.json deleted file mode 100644 index 241397d..0000000 --- a/tests/SampleResponses/bookmarks-response.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "rsp": { - "_content": { - "bookmark": { - "bookmarkId": "11b27cd5-ecdc-4c39-b818-8f3c8eca443c", - "username": "travelmagazine", - "documentId": "081024182109-9280632f2866416d97634cdccc66715d", - "documentUsername": "publination", - "name": "wildswim", - "title": "Wild Swim: The best outdoor swims across Britain", - "description": "Wild Swim by Kate Rew is the definitive guide to over 300 beautiful outdoor swims in rivers, lakes, tidal pools, the sea and lidos across Britain. By the founder of the Outdoor Swimming Society.", - "page": 1, - "created": "2009-06-22T07:54:17.000Z", - "folders": [ - "52ab7b36-946d-45b2-a446-f95e84b2682e" - ] - } - }, - "stat": "ok" - } -} \ No newline at end of file diff --git a/tests/SampleResponses/documents-delete.json b/tests/SampleResponses/documents-delete.json deleted file mode 100644 index 45ae4de..0000000 --- a/tests/SampleResponses/documents-delete.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rsp": { - "stat": "ok" - } -} \ No newline at end of file diff --git a/tests/SampleResponses/documents-list.json b/tests/SampleResponses/documents-list.json deleted file mode 100644 index 3848e14..0000000 --- a/tests/SampleResponses/documents-list.json +++ /dev/null @@ -1,265 +0,0 @@ -{ - "rsp": { - "_content": { - "result": { - "totalCount": 1349, - "startIndex": 0, - "pageSize": 10, - "more": true, - "_content": [ - { - "document": { - "username": "kirja", - "name": "9789510341117-jerusalemin-veri", - "publicationId": "eeb2e7f065b145c5b1a6249788ce0a48", - "revisionId": "150918113757", - "documentId": "150918113757-eeb2e7f065b145c5b1a6249788ce0a48", - "title": "Thompson, Jim: Jerusalemin veri (Johnny Kniga)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510341117_lukun.pdf", - "origin": "apislurp", - "pageCount": 16, - "publishDate": "2008-06-01T00:00:00.000Z", - "description": "Nopeatempoinen poliittinen trilleri, jonka panoksena on koko Lähi-idän tulevaisuus.", - "folders": [ - "18382a99-cea8-4fff-a432-bbd54b3a653e" - ] - } - }, - { - "document": { - "username": "kirja", - "name": "9789510369050-nicholas-nicklebyn-elama-ja-seikkail", - "publicationId": "6f4a2264e64e4577af68d12e29913f79", - "revisionId": "150918113803", - "documentId": "150918113803-6f4a2264e64e4577af68d12e29913f79", - "title": "Dickens, Charles: Nicholas Nicklebyn elämä ja seikkailut (WSOY)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510369050_lukun.pdf", - "origin": "apislurp", - "pageCount": 20, - "publishDate": "2012-02-21T00:00:00.000Z", - "description": "Teemoiltaan aina ajankohtainen teos kuvaa aikakautta, jolle tyypillistä on keinottelevaan ja pröystäilevään elämänmenoon kätkeytyvä romahduksen siemen.", - "folders": [ - "18382a99-cea8-4fff-a432-bbd54b3a653e" - ] - } - }, - { - "document": { - "username": "kirja", - "name": "9789510377451-lumottu", - "publicationId": "98cf82f62fea4862a0afd64132d411b2", - "revisionId": "150918113808", - "documentId": "150918113808-98cf82f62fea4862a0afd64132d411b2", - "title": "Harkness, Deborah: Lumottu (WSOY)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510377451_lukun.pdf", - "origin": "apislurp", - "pageCount": 20, - "publishDate": "2012-02-21T00:00:00.000Z", - "description": "Huikea tarina lumotusta käsikirjoituksesta, vampyyrin ja noidan välisestä vetovoimasta ja aikarajat ylittävästä pakomatkasta aina Pariisista New Yorkiin ja menneisyyden Englantiin.", - "folders": [ - "18382a99-cea8-4fff-a432-bbd54b3a653e" - ] - } - }, - { - "document": { - "username": "kirja", - "name": "9789510353653-jerusalem", - "publicationId": "9dba9f0326c94723b4739bf78960cdf1", - "revisionId": "150918113814", - "documentId": "150918113814-9dba9f0326c94723b4739bf78960cdf1", - "title": "Montefiore, Simon Sebag: Jerusalem (WSOY)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510353653_lukun.pdf", - "origin": "apislurp", - "pageCount": 20, - "publishDate": "2012-02-21T00:00:00.000Z", - "description": "Maailman kansainvälisimmän kaupungin, kansojen, uskontojen ja kulttuurien kohtauspaikan 3000 kuohuvaa vuotta kiehtovasti kerrottuna. Runsas kuvitus. ", - "folders": [ - "4ca4bbe4-7a46-4870-a79b-b54f0e42fa3e" - ] - } - }, - { - "document": { - "username": "kirja", - "name": "9789510388358-toinen-jalka-maassa", - "publicationId": "7449007f51bc4c4c9a6cc0acd0aaef52", - "revisionId": "150918113820", - "documentId": "150918113820-7449007f51bc4c4c9a6cc0acd0aaef52", - "title": "Envall, Markku: Toinen jalka maassa (WSOY)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510388358_lukun.pdf", - "origin": "apislurp", - "pageCount": 20, - "publishDate": "2012-06-01T00:00:00.000Z", - "description": "Toinen jalka maassa on virkistävä paluu envallilaisittain punnittujen oivallusten alkulähteille.", - "folders": [ - "3267d52d-b8c7-4217-bd2b-f5763503fcc4" - ] - } - }, - { - "document": { - "username": "kirja", - "name": "9789510384886-kristallikuningas", - "publicationId": "63c67f2f822f4e4099695da3aa804801", - "revisionId": "150918113826", - "documentId": "150918113826-63c67f2f822f4e4099695da3aa804801", - "title": "Raatikainen, Aki: Kristallikuningas (WSOY)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510384886_lukun.pdf", - "origin": "apislurp", - "pageCount": 20, - "publishDate": "2012-06-01T00:00:00.000Z", - "description": "Huikea historiallinen seikkailuromaani kuohuvalta 1600-luvulta", - "folders": [ - "3267d52d-b8c7-4217-bd2b-f5763503fcc4" - ] - } - }, - { - "document": { - "username": "kirja", - "name": "9789510383407-poika-ja-kapakkasaatana", - "publicationId": "70bedc2b834945bb98ca03a8cae4b02e", - "revisionId": "150918113832", - "documentId": "150918113832-70bedc2b834945bb98ca03a8cae4b02e", - "title": "Laiho, Pekka: Poika ja kapakkasaatana (WSOY)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510383407_lukun.pdf", - "origin": "apislurp", - "pageCount": 20, - "publishDate": "2012-06-01T00:00:00.000Z", - "description": "Laatunäyttelijän vauhdikas elämäkerta. Mehevä ajankuva tempaa mukaansa 1960-luvun Lapualaisoopperasta teatterin politisoitumisen vuosiin 1970-luvulle.", - "folders": [ - "4ca4bbe4-7a46-4870-a79b-b54f0e42fa3e" - ] - } - }, - { - "document": { - "username": "kirja", - "name": "9789510379509-etten-palaisi-tuhkaksi", - "publicationId": "a37e59910b91459da18bf6d0f5fd1d27", - "revisionId": "150918113839", - "documentId": "150918113839-a37e59910b91459da18bf6d0f5fd1d27", - "title": "Heivoll, Gaute: Etten palaisi tuhkaksi (WSOY)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510379509_lukun.pdf", - "origin": "apislurp", - "pageCount": 20, - "publishDate": "2012-03-06T00:00:00.000Z", - "description": "Kirjailija palaa kotikyläänsä tutkimaan menneisyyden tuhopolttosarjaa. Mitä yhteistä on suurkaupunkiin paenneella kirjailijalla ja palomestarin pojalla?", - "folders": [ - "18382a99-cea8-4fff-a432-bbd54b3a653e" - ] - } - }, - { - "document": { - "username": "kirja", - "name": "9789510127162-veljeni-sebastian", - "publicationId": "923d16e0d802458396ce519071f185fc", - "revisionId": "150918113844", - "documentId": "150918113844-923d16e0d802458396ce519071f185fc", - "title": "Idström, Annika: Veljeni Sebastian (WSOY)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510127162_lukun.pdf", - "origin": "apislurp", - "pageCount": 20, - "publishDate": "1985-06-01T00:00:00.000Z", - "description": "Väkevän myyttinen kuva hyvän ja pahan kerrostuneisuudesta, perhesuhteiden salatusta väkivallasta. Tekijän läpimurtoromaani sai Valtion kirjallisuuspalkinnon ja oli Finlandia-ehdokkaana 1985.", - "folders": [ - "3267d52d-b8c7-4217-bd2b-f5763503fcc4" - ] - } - }, - { - "document": { - "username": "kirja", - "name": "9789510386057-kaarmekonnun-salaisuudet", - "publicationId": "ca0c87729f7f4e4abe1affe01da40b30", - "revisionId": "150918113850", - "documentId": "150918113850-ca0c87729f7f4e4abe1affe01da40b30", - "title": "Mull, Brandon: Käärmekonnun salaisuudet (WSOY)", - "access": "public", - "state": "A", - "contentFlag": "1", - "errorCode": 0, - "category": "000000", - "type": "000000", - "orgDocType": "unknown", - "orgDocName": "http://media.bonnierbooks.fi/sample-pages/9789510386057_lukun.pdf", - "origin": "apislurp", - "pageCount": 20, - "publishDate": "2012-03-13T00:00:00.000Z", - "description": "Aamunkoiton ritarit valmistautuvat ennennäkemättömiin vaaroihin ja matkaavat lohikäärmeiden asuinsijoille. Kilpajuoksu Sfinksiä vastaan on armoton!", - "folders": [ - "2ad79055-a4bd-4627-b95d-64c00a234334" - ] - } - } - ] - } - }, - "stat": "ok" - } -} \ No newline at end of file diff --git a/tests/SampleResponses/documents-response.json b/tests/SampleResponses/documents-response.json deleted file mode 100644 index bee793a..0000000 --- a/tests/SampleResponses/documents-response.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "rsp": { - "_content": { - "document": { - "username": "lekkim", - "name": "racing", - "documentId": "090623122351-f691a27cfd744b80b25a2c8f5a51d596", - "title": "Race cars", - "access": "public", - "state": "P", - "category": "012000", - "type": "009000", - "origin": "singleupload", - "pageCount": 0, - "ep": 1245759831, - "description": "Race cars of Le Man 2009", - "tags": [ - "cars", - "le man", - "racing" - ], - "folders": [ - "3935f331-5d5b-4694-86ce-6f26c6dee809" - ] - } - }, - "stat": "ok" - } -} \ No newline at end of file diff --git a/tests/SampleResponses/draft-getdraftbyslug.json b/tests/SampleResponses/draft-getdraftbyslug.json new file mode 100644 index 0000000..155d46c --- /dev/null +++ b/tests/SampleResponses/draft-getdraftbyslug.json @@ -0,0 +1,42 @@ +{ + "slug": "zp0m1zti7ir", + "owner": "kirja", + "cover": { + "large": { + "url": "https://image.isu.pub/240425135049-c6739df8b215bb921d5fd15367d0cd31/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + }, + "medium": { + "url": "https://image.isu.pub/240425135049-c6739df8b215bb921d5fd15367d0cd31/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "small": { + "url": "https://image.isu.pub/240425135049-c6739df8b215bb921d5fd15367d0cd31/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789520458751_lukun.pdf", + "size": 11009929, + "pageCount": 20, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/zp0m1zti7ir", + "changes": { + "access": "PUBLIC", + "description": "

Saisiko olla yksi telttaretki ja lohi-herne-marmeladileipä?

", + "file": 119824977, + "originalPublishDate": "2024-06-10T00:00:00.000Z", + "preview": false, + "title": "Kortesuo, Katleena: Veevi ja aivopieruverkkarit (Tammi)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2024-04-25T13:50:49.000Z" + } \ No newline at end of file diff --git a/tests/SampleResponses/draft-publishdraftbyslug.json b/tests/SampleResponses/draft-publishdraftbyslug.json new file mode 100644 index 0000000..8ec6573 --- /dev/null +++ b/tests/SampleResponses/draft-publishdraftbyslug.json @@ -0,0 +1,4 @@ +{ + "location": "https://issuu.com/home/docs/1bc48nbik7l", + "publicLocation": "https://issuu.com/kirja/docs/string" + } \ No newline at end of file diff --git a/tests/SampleResponses/drafts-create.json b/tests/SampleResponses/drafts-create.json new file mode 100644 index 0000000..b228e63 --- /dev/null +++ b/tests/SampleResponses/drafts-create.json @@ -0,0 +1,17 @@ +{ + "slug": "ycx1lethynr", + "owner": "kirja", + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/ycx1lethynr", + "changes": { + "access": "PUBLIC", + "description": "string", + "originalPublishDate": "1970-01-01T00:00:00.000Z", + "preview": false, + "title": "string", + "type": "editorial", + "downloadable": false, + "showDetectedLinks": false + }, + "created": "2024-05-06T13:36:07.000Z" + } \ No newline at end of file diff --git a/tests/SampleResponses/drafts-list.json b/tests/SampleResponses/drafts-list.json new file mode 100644 index 0000000..24f70aa --- /dev/null +++ b/tests/SampleResponses/drafts-list.json @@ -0,0 +1,433 @@ +{ + "results": [ + { + "slug": "zp0m1zti7ir", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240425135049-c6739df8b215bb921d5fd15367d0cd31/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240425135049-c6739df8b215bb921d5fd15367d0cd31/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240425135049-c6739df8b215bb921d5fd15367d0cd31/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789520458751_lukun.pdf", + "size": 11009929, + "pageCount": 20, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/zp0m1zti7ir", + "changes": { + "access": "PUBLIC", + "description": "

Saisiko olla yksi telttaretki ja lohi-herne-marmeladileipä?

", + "file": 119824977, + "originalPublishDate": "2024-06-10T00:00:00.000Z", + "preview": false, + "title": "Kortesuo, Katleena: Veevi ja aivopieruverkkarit (Tammi)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2024-04-25T13:50:49.000Z" + }, + { + "slug": "odpussp4g3i", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240416075630-c15aef8e5d8a4df5a8ef96964e143eea/jpg/page_1_thumb_small.jpg", + "width": 71, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240416075630-c15aef8e5d8a4df5a8ef96964e143eea/jpg/page_1_thumb_medium.jpg", + "width": 106, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240416075630-c15aef8e5d8a4df5a8ef96964e143eea/jpg/page_1_thumb_large.jpg", + "width": 320, + "height": 451 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "Johnny%20Kniga%20syksy%202024.pdf", + "size": 13862935, + "pageCount": 22, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/odpussp4g3i", + "changes": { + "access": "PUBLIC", + "description": "Johnny Knigan syksyn 2024 kirjat.\n\n", + "file": 119592911, + "preview": false, + "title": "Johnny Kniga syksy 2024", + "downloadable": false, + "showDetectedLinks": false + }, + "created": "2024-04-16T07:56:24.000Z" + }, + { + "slug": "1e1w2jtoxx7", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240402124133-a966e076001c128d23b9532d2a95a690/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240402124133-a966e076001c128d23b9532d2a95a690/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240402124133-a966e076001c128d23b9532d2a95a690/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789523620322_lukun.pdf", + "size": 445348, + "pageCount": 18, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/1e1w2jtoxx7", + "changes": { + "access": "PUBLIC", + "description": "

Kun rikolliset luulevat, että kukaan ei kuuntele.

", + "file": 119269397, + "originalPublishDate": "2024-05-14T00:00:00.000Z", + "preview": false, + "title": "Salihu, Diamant: Huumekartellit kuuntelussa (Johnny Kniga)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2024-04-02T12:41:33.000Z" + }, + { + "slug": "3l5vvcpr785", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/fallback_small.jpg", + "width": 75, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/fallback_medium.jpg", + "width": 113, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/fallback_large.jpg", + "width": 320, + "height": 426 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789510500118_lukun.pdf", + "size": 369420, + "pageCount": 0, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/3l5vvcpr785", + "changes": { + "access": "PUBLIC", + "description": "

Millainen on vahva nainen?

", + "file": 118408738, + "originalPublishDate": "2024-04-09T00:00:00.000Z", + "preview": false, + "title": "Rytkönen, Millariikka: Täysin auki (Johnny Kniga)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2024-02-26T11:10:41.000Z" + }, + { + "slug": "b2ylh5yc1s4", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240219080032-b3353d1e6339417ae364a9849846e37c/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240219080032-b3353d1e6339417ae364a9849846e37c/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240219080032-b3353d1e6339417ae364a9849846e37c/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789522797339_lukun.pdf", + "size": 337409, + "pageCount": 20, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/b2ylh5yc1s4", + "changes": { + "access": "PUBLIC", + "description": "

Valovoimainen romaani Wivi Lönnistä, lasikattojen murtajasta

", + "file": 118256068, + "originalPublishDate": "2021-01-26T00:00:00.000Z", + "preview": false, + "title": "Soininen, Pirkko: Valosta rakentuvat huoneet (Bazar)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2024-02-19T08:00:32.000Z" + }, + { + "slug": "ocdo5nt6jmj", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240209080045-48c7fe1ccee6e74a51dcb3fffd2da106/jpg/page_1_thumb_small.jpg", + "width": 67, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240209080045-48c7fe1ccee6e74a51dcb3fffd2da106/jpg/page_1_thumb_medium.jpg", + "width": 101, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240209080045-48c7fe1ccee6e74a51dcb3fffd2da106/jpg/page_1_thumb_large.jpg", + "width": 320, + "height": 477 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789510487365_lukun.pdf", + "size": 885026, + "pageCount": 21, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/ocdo5nt6jmj", + "changes": { + "access": "PUBLIC", + "description": "

Kunnianhimoinen suurromaani natsi-Saksan noususta ja tuhosta.

", + "file": 118080637, + "originalPublishDate": "2024-03-22T00:00:00.000Z", + "preview": false, + "title": "Terho, Sampo: Stalingradin viemärit (WSOY)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2024-02-09T08:00:45.000Z" + }, + { + "slug": "cnep0zyir1z", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240131115034-0a6d4f9c9e507d47d71060ee8a75db74/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240131115034-0a6d4f9c9e507d47d71060ee8a75db74/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240131115034-0a6d4f9c9e507d47d71060ee8a75db74/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789523827844_lukun.pdf", + "size": 505560, + "pageCount": 25, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/cnep0zyir1z", + "changes": { + "access": "PUBLIC", + "description": "

Suureen kansansuosioon nousseen tiedustelueverstin ainutlaatuinen testamentti.

", + "file": 117905929, + "originalPublishDate": "2024-03-14T00:00:00.000Z", + "preview": false, + "title": "Halminen, Laura: Martti J. Kari (Docendo)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2024-01-31T11:50:34.000Z" + }, + { + "slug": "ue36mx59s4w", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240125132031-0b7ecbff6e630dea91081b525548f2eb/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240125132031-0b7ecbff6e630dea91081b525548f2eb/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240125132031-0b7ecbff6e630dea91081b525548f2eb/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789522797339_lukun.pdf", + "size": 337409, + "pageCount": 20, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/ue36mx59s4w", + "changes": { + "access": "PUBLIC", + "description": "

Valovoimainen romaani Wivi Lönnistä, lasikattojen murtajasta

", + "file": 117797669, + "originalPublishDate": "2021-01-26T00:00:00.000Z", + "preview": false, + "title": "Soininen, Pirkko: Valosta rakentuvat huoneet (Bazar)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2024-01-25T13:20:31.000Z" + }, + { + "slug": "pvi7fbh8ydg", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240108140408-fcaa446d960f5725b401d051b1c4e394/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240108140408-fcaa446d960f5725b401d051b1c4e394/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240108140408-fcaa446d960f5725b401d051b1c4e394/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789524030670_lukun.pdf", + "size": 813857, + "pageCount": 18, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/pvi7fbh8ydg", + "changes": { + "access": "PUBLIC", + "description": "

Nämä koirat ovat haistaneet veren

", + "file": 117483350, + "originalPublishDate": "2024-02-22T00:00:00.000Z", + "preview": false, + "title": "Jones, Dan: Essexin koirat (Bazar)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2024-01-08T14:04:08.000Z" + }, + { + "slug": "luppz7q7kkr", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/231130105406-b8e40384b66a4390e43639f47b214309/jpg/page_1_thumb_small.jpg", + "width": 67, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/231130105406-b8e40384b66a4390e43639f47b214309/jpg/page_1_thumb_medium.jpg", + "width": 100, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/231130105406-b8e40384b66a4390e43639f47b214309/jpg/page_1_thumb_large.jpg", + "width": 319, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789510302996_lukun.pdf", + "size": 1237575, + "pageCount": 22, + "type": "PDF", + "conversionStatus": "DONE" + }, + "state": "DRAFT", + "location": "https://issuu.com/home/drafts/luppz7q7kkr", + "changes": { + "access": "PUBLIC", + "description": "

Shakespearen varhaiskauden komedia, jota ei ole suomennettu sitten Paavo Cajanderin.

", + "file": 116843221, + "originalPublishDate": "2005-06-01T00:00:00.000Z", + "preview": false, + "title": "Shakespeare, William: Kaksi nuorta veronalaista (WSOY)", + "downloadable": true, + "showDetectedLinks": false + }, + "created": "2023-11-30T10:54:06.000Z" + } + ], + "links": { + "self": { + "href": "https://api.issuu.com/v2/drafts" + }, + "next": { + "href": "https://api.issuu.com/v2/drafts?size=10&page=2" + } + }, + "pageSize": 10, + "count": 16 + } \ No newline at end of file diff --git a/tests/SampleResponses/folders-delete.json b/tests/SampleResponses/folders-delete.json deleted file mode 100644 index 45ae4de..0000000 --- a/tests/SampleResponses/folders-delete.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rsp": { - "stat": "ok" - } -} \ No newline at end of file diff --git a/tests/SampleResponses/folders-list.json b/tests/SampleResponses/folders-list.json deleted file mode 100644 index c3114e3..0000000 --- a/tests/SampleResponses/folders-list.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "rsp": { - "_content": { - "result": { - "totalCount": 1, - "startIndex": 0, - "pageSize": 10, - "more": false, - "_content": [ - { - "folder": { - "folderId": "4c3ba964-60c3-4349-94d0-ff86db2d47c9", - "username": "ferrogate", - "name": "Cool stuff", - "description": "Stuff I have collected", - "items": 0, - "created": "2009-07-12T19:52:15.000Z" - } - } - ] - } - }, - "stat": "ok" - } -} \ No newline at end of file diff --git a/tests/SampleResponses/folders-response.json b/tests/SampleResponses/folders-response.json deleted file mode 100644 index f927b83..0000000 --- a/tests/SampleResponses/folders-response.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "rsp": { - "_content": { - "folder": { - "folderId": "4c3ba964-60c3-4349-94d0-ff86db2d47c9", - "username": "ferrogate", - "name": "Cool stuff", - "description": "Stuff I have collected", - "items": 0, - "created": "2009-07-12T19:52:15.000Z" - } - }, - "stat": "ok" - } -} \ No newline at end of file diff --git a/tests/SampleResponses/publications-list.json b/tests/SampleResponses/publications-list.json new file mode 100644 index 0000000..2f5b3dc --- /dev/null +++ b/tests/SampleResponses/publications-list.json @@ -0,0 +1,434 @@ +{ + "results": [ + { + "state": "PUBLISHED", + "slug": "od0gkhdqc32", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240502060045-debf16435e3e943fb148dcc90b6eed24/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240502060045-debf16435e3e943fb148dcc90b6eed24/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240502060045-debf16435e3e943fb148dcc90b6eed24/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789510494127_lukun.pdf", + "size": 528460, + "pageCount": 20, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": "Ahnhem, Stefan: Vaihto (WSOY)", + "description": "

Psykologinen trilleri ruotsalaiselta suosikkidekkaristilta!

", + "originalPublishDate": "2024-06-13T00:00:00.000Z", + "preview": false, + "file": 119986640, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2024-06-13T00:00:00.000Z", + "created": "2024-05-02T06:00:49.000Z", + "location": "https://issuu.com/home/docs/od0gkhdqc32", + "publicLocation": "https://issuu.com/kirja/docs/9789510494127-vaihto" + }, + { + "state": "PUBLISHED", + "slug": "jhi5muwuseq", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240430124139-10dcbd686fc5d0f7b08688a4965e0653/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240430124139-10dcbd686fc5d0f7b08688a4965e0653/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240430124139-10dcbd686fc5d0f7b08688a4965e0653/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789520461096_lukun.pdf", + "size": 487022, + "pageCount": 21, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": "Behm, Jukka: Enkelin nyrkki (Tammi)", + "description": "

\"Enkelin nyrkki Brownien apuna.\" – Evening Sun

", + "originalPublishDate": "2024-06-12T00:00:00.000Z", + "preview": false, + "file": 119943141, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2024-06-12T00:00:00.000Z", + "created": "2024-04-30T12:41:42.000Z", + "location": "https://issuu.com/home/docs/jhi5muwuseq", + "publicLocation": "https://issuu.com/kirja/docs/9789520461096-enkelin-nyrkki" + }, + { + "state": "PUBLISHED", + "slug": "2bdi6d81cgx", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240430110845-4b5042ccfc2884a039da5c05310588cd/jpg/page_1_thumb_small.jpg", + "width": 80, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240430110845-4b5042ccfc2884a039da5c05310588cd/jpg/page_1_thumb_medium.jpg", + "width": 120, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240430110845-4b5042ccfc2884a039da5c05310588cd/jpg/page_1_thumb_large.jpg", + "width": 320, + "height": 400 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789520461621_lukun.pdf", + "size": 53089182, + "pageCount": 20, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": ": Disney. 5 minuutin satuja eläinystävistä (Disney)", + "description": "

Eläinkavereiden kanssa on aina kivaa!

", + "originalPublishDate": "2024-06-12T00:00:00.000Z", + "preview": false, + "file": 119941197, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2024-06-12T00:00:00.000Z", + "created": "2024-04-30T11:08:50.000Z", + "location": "https://issuu.com/home/docs/2bdi6d81cgx", + "publicLocation": "https://issuu.com/kirja/docs/9789520461621-disney-5-minuutin-satuja-elainystavi" + }, + { + "state": "PUBLISHED", + "slug": "l80jafbp2im", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240430092739-be3985fbeeecf3caaa2b54623d312f7d/jpg/page_1_thumb_small.jpg", + "width": 67, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240430092739-be3985fbeeecf3caaa2b54623d312f7d/jpg/page_1_thumb_medium.jpg", + "width": 100, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240430092739-be3985fbeeecf3caaa2b54623d312f7d/jpg/page_1_thumb_large.jpg", + "width": 319, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789510302996_lukun.pdf", + "size": 1237575, + "pageCount": 22, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": "Shakespeare, William: Kaksi nuorta veronalaista (WSOY)", + "description": "

Shakespearen varhaiskauden komedia, jota ei ole suomennettu sitten Paavo Cajanderin.

", + "originalPublishDate": "2005-06-01T00:00:00.000Z", + "preview": false, + "file": 119938776, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2005-06-01T00:00:00.000Z", + "created": "2024-04-30T09:27:43.000Z", + "location": "https://issuu.com/home/docs/l80jafbp2im", + "publicLocation": "https://issuu.com/kirja/docs/9789510302996-kaksi-nuorta-veronalaista" + }, + { + "state": "PUBLISHED", + "slug": "340do6gt7sh", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240430091106-62783b2e4aee58fbe479029d5b40659e/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240430091106-62783b2e4aee58fbe479029d5b40659e/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240430091106-62783b2e4aee58fbe479029d5b40659e/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789510505533_lukun.pdf", + "size": 315676, + "pageCount": 22, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": "Harding, Andrew: Kylä joka ei luovuttanut (WSOY)", + "description": "

Venäläiset hyökkääjät ovat tulossa, mutta ukrainalaisen pikkukaupungin asukkailla on suunnitelma.

", + "originalPublishDate": "2024-06-06T00:00:00.000Z", + "preview": false, + "file": 119938312, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2024-06-06T00:00:00.000Z", + "created": "2024-04-30T09:11:09.000Z", + "location": "https://issuu.com/home/docs/340do6gt7sh", + "publicLocation": "https://issuu.com/kirja/docs/9789510505533-kyla-joka-ei-luovuttanut" + }, + { + "state": "PUBLISHED", + "slug": "lvzdquj55rz", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240430084654-6143e041c2d3ae973a58bce35254fb09/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240430084654-6143e041c2d3ae973a58bce35254fb09/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240430084654-6143e041c2d3ae973a58bce35254fb09/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789510501696_lukun.pdf", + "size": 633957, + "pageCount": 21, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": "Lähteenmäki, Selma: Eläinten turvakoti Tuulispää (WSOY)", + "description": "

Sykähdyttävä teos paikasta, joka tarjoaa loppuelämän kodin kaikenkarvaisille eläinystäville.

", + "originalPublishDate": "2024-06-05T00:00:00.000Z", + "preview": false, + "file": 119937756, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2024-06-05T00:00:00.000Z", + "created": "2024-04-30T08:46:56.000Z", + "location": "https://issuu.com/home/docs/lvzdquj55rz", + "publicLocation": "https://issuu.com/kirja/docs/9789510501696-elainten-turvakoti-tuulispaa" + }, + { + "state": "PUBLISHED", + "slug": "blx8559ye7g", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240430084608-8ce7d312d34de0e9c0b9fc40fde8360c/jpg/page_1_thumb_small.jpg", + "width": 65, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240430084608-8ce7d312d34de0e9c0b9fc40fde8360c/jpg/page_1_thumb_medium.jpg", + "width": 98, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240430084608-8ce7d312d34de0e9c0b9fc40fde8360c/jpg/page_1_thumb_large.jpg", + "width": 314, + "height": 479 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789524033787_lukun.pdf", + "size": 908394, + "pageCount": 17, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": "Jessup, Joel: Arsène Lupinin aivopähkinät (Bazar)", + "description": "

Mestarivarkaan mysteerit

", + "originalPublishDate": "2024-06-13T00:00:00.000Z", + "preview": false, + "file": 119937738, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2024-06-13T00:00:00.000Z", + "created": "2024-04-30T08:46:10.000Z", + "location": "https://issuu.com/home/docs/blx8559ye7g", + "publicLocation": "https://issuu.com/kirja/docs/9789524033787-arsene-lupinin-aivopahkinat" + }, + { + "state": "PUBLISHED", + "slug": "lbq99k9ncta", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240430083156-a775ef9a2f4768e987a5786051d7879c/jpg/page_1_thumb_small.jpg", + "width": 64, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240430083156-a775ef9a2f4768e987a5786051d7879c/jpg/page_1_thumb_medium.jpg", + "width": 97, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240430083156-a775ef9a2f4768e987a5786051d7879c/jpg/page_1_thumb_large.jpg", + "width": 308, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789523768055_lukun.pdf", + "size": 406681, + "pageCount": 21, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": "Vuorinen, Juha: Andalusialainen mäyräkoira (Bazar)", + "description": "

Animaalista menoa elävien ja kuolleiden kanssa

", + "originalPublishDate": "2024-06-14T00:00:00.000Z", + "preview": false, + "file": 119937425, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2024-06-14T00:00:00.000Z", + "created": "2024-04-30T08:31:59.000Z", + "location": "https://issuu.com/home/docs/lbq99k9ncta", + "publicLocation": "https://issuu.com/kirja/docs/9789523768055-andalusialainen-mayrakoira" + }, + { + "state": "PUBLISHED", + "slug": "g2lisde5zw0", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240429131102-8e0c6a05694c83c4e80c7125098ac749/jpg/page_1_thumb_small.jpg", + "width": 67, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240429131102-8e0c6a05694c83c4e80c7125098ac749/jpg/page_1_thumb_medium.jpg", + "width": 101, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240429131102-8e0c6a05694c83c4e80c7125098ac749/jpg/page_1_thumb_large.jpg", + "width": 320, + "height": 477 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789520462826_lukun.pdf", + "size": 31196120, + "pageCount": 21, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": "Oseman, Alice: Heartstopper. Osa 5 (Tammi)", + "description": "

Nickin ja Charlien tunteet syvenevät!

", + "originalPublishDate": "2024-06-12T00:00:00.000Z", + "preview": false, + "file": 119913114, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2024-06-12T00:00:00.000Z", + "created": "2024-04-29T13:11:06.000Z", + "location": "https://issuu.com/home/docs/g2lisde5zw0", + "publicLocation": "https://issuu.com/kirja/docs/9789520462826-heartstopper-osa-5" + }, + { + "state": "PUBLISHED", + "slug": "hrh42so3oby", + "owner": "kirja", + "cover": { + "small": { + "url": "https://image.isu.pub/240429112150-63bfdcb720e9b16023d3116ca479e4e0/jpg/page_1_thumb_small.jpg", + "width": 63, + "height": 100 + }, + "medium": { + "url": "https://image.isu.pub/240429112150-63bfdcb720e9b16023d3116ca479e4e0/jpg/page_1_thumb_medium.jpg", + "width": 94, + "height": 150 + }, + "large": { + "url": "https://image.isu.pub/240429112150-63bfdcb720e9b16023d3116ca479e4e0/jpg/page_1_thumb_large.jpg", + "width": 301, + "height": 480 + } + }, + "fileInfo": { + "isCopyrightConfirmed": false, + "name": "9789510504550_lukun.pdf", + "size": 944213, + "pageCount": 16, + "type": "PDF", + "conversionStatus": "DONE" + }, + "access": "PUBLIC", + "title": "Sarenbrant, Sofie: Parasiitti (WSOY)", + "description": "

Ruumiin palaneet jäännökset, tappolista – ja listan viimeisenä nimenä Emma Sköld.

", + "originalPublishDate": "2024-05-31T00:00:00.000Z", + "preview": false, + "file": 119910512, + "downloadable": true, + "showDetectedLinks": false, + "backDate": "2024-05-31T00:00:00.000Z", + "created": "2024-04-29T11:21:53.000Z", + "location": "https://issuu.com/home/docs/hrh42so3oby", + "publicLocation": "https://issuu.com/kirja/docs/9789510504550-parasiitti" + } + ], + "links": { + "self": { + "href": "https://api.issuu.com/v2/publications" + }, + "next": { + "href": "https://api.issuu.com/v2/publications?size=10&page=2" + } + }, + "pageSize": 10, + "count": 5347 + } \ No newline at end of file diff --git a/tests/SampleResponses/stacks-list.json b/tests/SampleResponses/stacks-list.json new file mode 100644 index 0000000..077651d --- /dev/null +++ b/tests/SampleResponses/stacks-list.json @@ -0,0 +1,74 @@ +{ + "results": [ + { + "id": "ce4d20effcc6497fa6597d20a6e08ab2", + "title": "Muut", + "description": "true", + "accessType": "PUBLIC" + }, + { + "id": "ac86c7cd7a18426bb6187c6ab62abb33", + "title": "Kevään 2023 katalogit", + "description": "WSOY:n, Tammen ja Johnny Knigan kevään 2023 katalogit.", + "accessType": "PUBLIC" + }, + { + "id": "713ac380a966438d88503d232156ae04", + "title": "Syksyn 2022 katalogit", + "description": "WSOY:n, Tammen ja Johnny Knigan syksyn 2022 katalogit.", + "accessType": "PUBLIC" + }, + { + "id": "98041eb277b6450c82b7034878142940", + "title": "Kevään 2022 katalogit", + "description": "WSOY:n, Tammen ja Johnny Knigan kevään 2022 katalogit.", + "accessType": "PUBLIC" + }, + { + "id": "4639a7ae0e1c4d1a9802eda11537b90f", + "title": "Syksyn 2021 katalogit", + "description": "WSOY:n, Tammen ja Johnny Knigan syksyn 2021 katalogit.", + "accessType": "PUBLIC" + }, + { + "id": "5f13948b5ee04c93bcb14c552782dc76", + "title": "Kevään 2021 katalogit", + "description": "WSOY:n, Tammen ja Johnny Knigan kevään 2021 katalogit.", + "accessType": "PUBLIC" + }, + { + "id": "33c6d5b5ce92447095a5eed8c91bd2d1", + "title": "Syksyn 2020 katalogit", + "description": "WSOY:n, Tammen ja Johnny Knigan syksyn 2020 katalogit.", + "accessType": "PUBLIC" + }, + { + "id": "d17877fab1d145bba1872af166dba3c6", + "title": "Kevään 2020 katalogit", + "description": "WSOY:n, Tammen ja Johnny Knigan kevään 2020 kirjakatalogit.", + "accessType": "PUBLIC" + }, + { + "id": "862f01721fe446aa9c923fa4e77bc465", + "title": "Syksyn 2019 katalogit", + "description": "WSOY:n, Tammen ja Johnny Knigan syksyn 2019 katalogit.", + "accessType": "PUBLIC" + }, + { + "id": "fdd01fbe47f74a5dbd42c9d4126a0ab8", + "title": "Kevään 2019 katalogit", + "description": "WSOY:n, Tammen ja Johnny Knigan kevään 2019 kirjakatalogit.", + "accessType": "PUBLIC" + } + ], + "links": { + "self": { + "href": "https://api.issuu.com/v2/stacks" + }, + "next": { + "href": "https://api.issuu.com/v2/stacks?size=10&page=2" + } + }, + "pageSize": 10, + "count": 16 + } \ No newline at end of file diff --git a/tests/SignatureTest.php b/tests/SignatureTest.php deleted file mode 100644 index 2d019b4..0000000 --- a/tests/SignatureTest.php +++ /dev/null @@ -1,35 +0,0 @@ - 'issuu.documents.list', - 'apiKey' => 'qyy6ls1qv15uh9xwwlvk853u2uvpfka7', - 'access' => 'public', - 'responseParams' => 'title,description', - 'format' => 'json', - ]; - - // Create new ReflectionClass to test private method - $reflection = new ReflectionClass(get_class($issuu)); - $method = $reflection->getMethod('getSignature'); - $method->setAccessible(true); - $signature = $method->invokeArgs($issuu, [$parameters]); - - $this->assertSame('7431d31140cf412ab5caa73586d6324a', $signature); - } -} diff --git a/tests/StacksTest.php b/tests/StacksTest.php new file mode 100644 index 0000000..cf9e0b4 --- /dev/null +++ b/tests/StacksTest.php @@ -0,0 +1,30 @@ +issuu); + $stacksList = $stacks->list(); + + $this->assertIsObject($stacksList); + + // Pagination attributes + $this->assertSame(16, $stacksList->count); + $this->assertSame(10, $stacksList->pageSize); + + // Additional checks + $this->assertIsArray($stacksList->results); + $this->assertCount(10, $stacksList->results); + $this->assertIsString($stacksList->results[0]->id); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 345a26d..e2d935a 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,33 +2,72 @@ namespace Tests; +use Exception; use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; -use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Psr7\Response; use lasselehtinen\Issuu\Issuu; +use lasselehtinen\Issuu\Drafts; +use GuzzleHttp\Handler\MockHandler; +use lasselehtinen\Issuu\Publications; use PHPUnit\Framework\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase { /** - * Creates a instance with a mocked response - * @param string $response - * @return Issuu + * Issuu instance + * + * @var Issuu */ - public function createMockedInstance($response) + public $issuu; + + /** + * Common setup for all tests + * + * @return void + */ + public function setUp(): void { - // Create a mock and queue response. - $mock = new MockHandler([ - new Response(200, [], $response), - ]); + parent::setUp(); + + $issuuApiKey = getenv('ISSUU_API_KEY'); + + if (empty($issuuApiKey)) { + throw new Exception('Could not fetch Issuu API key from env variable.'); + } + + $this->issuu = new Issuu($issuuApiKey); + } + + /** + * Clean up generated Drafts and Publications + * + * @return void + */ + public static function tearDownAfterClass(): void + { + $issuuApiKey = getenv('ISSUU_API_KEY'); + + if (empty($issuuApiKey)) { + throw new Exception('Could not fetch Issuu API key from env variable.'); + } - $handler = HandlerStack::create($mock); - $client = new Client(['handler' => $handler]); + $issuu = new Issuu($issuuApiKey); + + // Remove test Drafts + $drafts = new Drafts($issuu); + $draftsList = $drafts->list(q: 'Test document', size: 50); + + foreach ($draftsList->results as $result) { + $drafts->deleteDraftBySlug($result->slug); + } - // Create a new instance with mocked Guzzle - $issuu = new Issuu('', '', $client); + // Remove test Publications + $publications = new Publications($issuu); + $publicationsList = $publications->list(q: 'Test document', size: 50); - return $issuu; + foreach ($publicationsList->results as $result) { + $publications->deletePublicationBySlug($result->slug); + } } } diff --git a/tests/sample.pdf b/tests/sample.pdf deleted file mode 100644 index cdacbbebbbf8c1f6b4c41e9d9b36755d46e92fa4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11112 zcmeHN2UJtZ*GDV}7c9cf(ou3Q9%(! zY!p{O1O-tP#D)zOQNeVAxA6LwO2u3@U^W*af1}C{)-BVp3=f z*a!4XfLO3U#6(yKheJSRLcmXezWXDXL@7`aJ`;ivOi0=vm`dG(WcofjjnS?TU(&a9 z3<{-PACpdM*T-VC>q98yc5@&!D)U=jgvKO)+eanSkam4kS{q(W!4peR1;GSp(+_A5 zLKyHw1v(q3iiyC!aybTp*&$!pLne|#G)>bv$X>{2Fc>s}040+dB08T!5>Tlmp@>Q* zBSHa%MdH}=Nqh>O!W5!B8lB0c(wQsB|HpuMg?*q3M|f`!F~{h$>At51QnC;DKvOnJI}2xyu*EHvhV6S&6Khtvu6oDrBDG z$o1asYP!Inv%#ITuAc}dz+JS$w2p&oMB{)Hd7-Eh0=5Mj@{f){VJ9BOlgLA1e87vx zMV0uIuq#*@==1j{gY%%_2Tmdv_@P)33=Svkk49m^uuBx?=7%p1(7O2{5PlBuxmq`? z=GM%n))p=pc98+oiDjX1fLO+rDaHD4N1hT@Q*aexo&=a%p~RfRcnXL@hP`;&HbO>V zKNTOtmG7@mp?bN_s8XO1M__UVglPOWKrF<wrgyzkO6D-}Z;0N)= z)TENUact9q|#zv_LXiC8*W z)wOPP{QbBg&wB-|o5>q|$-jiM$i`8ezkov4O|KxToyhM1?J*chz$5F?2OJ93s7G-$F_P& zN{IINi|k)EUw(S)>J8Z^1caak+1*ytB)m04x=iZs(Y;e2NB8Spxz1gGba7t1cLTXf zin&g3Nw&=tWb~|>+jyySGpVtGnbZH;Z^;9gZpl8OyDm2kYieP&L^d_ux^uK8`ISM6 zRodR%t0Yr{l~pMh#>b!R-|t8MPGf`4CXnF|2IS}rTjE%AquRBnJhP|P7=Mi0I^Afs z_~>x2iesebUzQWEJt7#48^koSUZ1N-8apd{v<;R^C-r^&qRXs2>VcVC zk3RgRo>g6HvU2jmgEpbbjyp&%#7P0y25n%D*u#vxx@SW(bH>RVX%)LC-TPSc<#lHdZ{>b8l}jBS2Cz*QMD@=)_x@1cC89xmR+nQh>w~tO`CveLQ8c9J?fJQH zcSYMU24cLTqUPpi&dju$GXF}(`)xgo$2A?fP=?iPc^NXRg1qTK#ez+ZmRXs5>5T`b zCVOR;E_N7lcgB#nucD(uZO*KZN$bC={6xA}#?N(6t43YvrpoQ_7yiYs?|k(71ggWe z{Cq)Hr>yHn*|skYULGAEZqL=D?{|IY#JBFVBGz~NnB4}W7W%L5Pj)0$n(Q`ej9t2YNTsZyrE*e37p!MN zm$_ZNxxG@FQZ|wdFY|^%*><9DVt|Q&;e3z{^kJ;Jpk!!a#lY|b69;~=&T+20X<)-VGDJJ#k zms%IrXLDS|#lboKp1QoXLaj^p5$?uu-A6gHx5ts(uY0^* z7O^y9CCNK#{K!7A?2U%cTt!JdOm}Ct!-KDU@^n;&WPgFZ0pSRr15qxT=CA= zlTKNeSr4$eygtC6{`0t%DfJUa?|yp4ym4ORphjt9-@z;EolVowOILCpAdM zD-3QhE3gW7gj0Wd^tfTzrB#=UQyqAufwK58SMw9crj%Vj$2|FV^NX7J@OptI%`Y)` z)5^pl^g_v-L=Rp8S&-ckddt6mNK40<7PVbr(+Y)rU zi~LlQU})IZ(Ayy#{^#ZIMh>ehe3ABX)VyI|pf7e`(v~E<#4owTUwLv~+?oCt#z@EP zAZ|#wm0&a`E3hc%`2M>YqcZ4IRtDWV;F`hCpkzGGI25?;z&zoJgT{x}+{A90>&MRRlJF8Q?JQ~H};X8AqW^qd*nDfWWd z=M|d-$drEc#mT2cX3`<+%vSz3*38Om2Fo}}k!+XLlX+{_F1xtoGf75C6YMVJGxK*I z&dGnGI{aw-tbT&G?D;kn7w(#xwqxf%5+W*!ZceQNZj~~4HSO!|MhQ^j!oKlr}mn!cn@5SCL z_K6rj(c+1BqDPPM5+D1m&hFzqs#jx9Gp#mwMtX*>by~a8Vw=zQbYXgr^k3FBZrVG6 zozN}aB3xd;gj~_XnyyRfq zy#ey6_Q5~;U-=oEyFA3>#9F0i#>UCSPdgI>$BgFqJ6fNHZ}`1jG$xonY720|q5!)Q z8_OAIhK)+?*Lj6eMR&CL<@7-3!1*`k{=9hRjz(^@|GSWPBXXVD`#xAm1rYpCu3?JM?v!H(3HAtGk*e01J5z9AC?SD|> zHu}oc>X_fp9nLr?jfuYdGWhA0Hx+LjRBu(UBY!C#KL6wapThGGk|P5wGiz?5RcTEH z2S)vJ_083Wnaz#MX`RCJ_DA2!X!x93mKB=)Fm`%$(|~Z7@Yt%)`I(Yi&NCwJwuR|O%#Un2+VAM9B9o%UMPG_zikpu`9D7m{T5|9BjN>;?OgV9-bW-X0lb$Eb zPr05tQN}GRE@zh?Ic<0Pa0RpC&>8xfytA~kx#wu-a?jJx=Urf2$ggBo7F@KySaiwZ zQpsiK%crh*Tsd>q=jz3(pR2B4n|7`Cy6}3#4atoc)w8QV++0x8wPwYw-nSBNo83;m zV{<2~mR@_b&bjXFUBA0G?+NZbzOTIh@xkJHLVd!+VGs8-kQf zPnJIY;c3z{>t{JlLp%NSw;(*DOClyPgt<_>})IELx3}b>Y*hj9A;!p|@ z1!yEwNu)N=0Y@WkwxdUMupbu^@gzzVo-k3{@biX9wj?qvkI;{JLv6AvI8fAx@=-~Z z0Hmr>Z5y0|e`^T*VCU8~;Gk2}?Ic%${UWfZSf~ubak6i)24t&IcPmG`fS*F9BN|E_ z>efTVDc)YK@x8r66o9+oC z*j8#DJJ80vVJk>Yf`zlKrg%?;Fu7b3F2*3TEz1@mB9t+ZNC6xpQmzPx5L>zxE>j^C z+4(xVY9)d%wpAF0McBb`WMrgmB*j*)2!#bQ#kq{x0DIy+` z%AkvgObUxfq@cikP_mFmM)_9of7*6JfqumiDuqOSCWHbQm7w_Il)!ulSh7%HC&Dj6 z;LyB?2yl7wFkl22I3jQ_Fo=mU3CdBQIFKLEG$dmD1ldV=vQV~F6j6wZcq$2I#qkyc zhgHf&7!)8^2q7Y*(*#-Ls1mW(RBB0ZtMrcCSltH>Ij$C1e~Eyvb{WzCg^qtG`CCf; zS6%u+h`ZxR3NUH_`& zwx6a8?x)$4$)~e3Jn64c}+g7}#3sl+gUu*52 zN~gB#W3U))c-z&+>0o(nE7k}CR;R65Yjsbsw}%L@R{hXd`bWsE`X_v4fUoJ=+KB+G zO#oRtg1|Ez0<~6sd}*VV0qUE7q_*;@K!PK_tSvz^I2*Dh^es{R#2~Wi&Jrn3BNZK)RZowqUMNjvBpd zirGL_c)b?VmCeC7KH9c$j%!m_I!AChzEE4q>MoEjz(s3i>B)7VAA$kuhhS|nluQC| zG4QqN9tgCaEo~OyPf`F7KN>@oIOwBL@O;2OhUO-J6`PxwKx$CZ7U}+NU=Hqnbt*s) zlsbmxIx@RINAMg#Yu^^db2@f3-8r|h$Dx)U^Xu8$-btMALTU~3SG2nMwa4xoUWBZN z;~HKanT}0;#5nCwn1)(2s-soUD_3y7f8VuPAE49mX^s`A<5Tq)50zGLT2a6k+Cj+w zf`jOjAYfCqmRYlW%O)CS?MEuP$Yxp~O|F@6u#Z{!snj((3qu*|mw4 zZzliBL2&LilsaZtb-sY}O}ap{R_&OMRPQjF!;0g6Fa$P%=dHe%M(D`Dv*Pj5jW zS0}1t{c4U2o=E#Pa#rAxGl-$Te$b~5Hc8;69zhdVsv|{xtVwGfz~7U$29k_619U2= zXQ=tW>rfDt=w&e(lr|%}n9|;!pnY%2B(!;338J0WHh$bX6`9hw66AYp!5c=p|T_PkVjYQDIu>S+ynbuSQ