From 8e1620ef580cb453d1bd526c02629b54a2a384a8 Mon Sep 17 00:00:00 2001 From: Laurent Constantin Date: Fri, 16 Aug 2024 23:37:34 +0200 Subject: [PATCH 01/12] Back button on ebook reader --- assets/ReadEbook.vue | 39 ++++++++++++++++------ assets/read-ebook.js | 6 ++-- assets/styles/global.scss | 7 ++++ src/Controller/BookController.php | 4 +++ templates/book/reader-files-epub.html.twig | 8 ++++- 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/assets/ReadEbook.vue b/assets/ReadEbook.vue index 17ec3d64..992db459 100644 --- a/assets/ReadEbook.vue +++ b/assets/ReadEbook.vue @@ -1,13 +1,21 @@ @@ -17,11 +25,12 @@ const props = defineProps({ 'css': String, 'bgColor': String, 'percent': String, - 'progressionUrl': String + 'progressionUrl': String, + 'backUrl': { type: String, default: ''} }) import { VueReader } from 'vue-book-reader' const initialCfi = new URLSearchParams(window.location.search).get('cfi'); - +const initialReferrer = document.referrer function debounce(func, delay) { let timeoutId; return function(...args) { @@ -71,4 +80,12 @@ const getRendition = async (rendition) => { rendition.renderer.setStyles([props.css]) } +const canGoBack = () => { + return initialReferrer !== "" || props.backUrl !== "" +} + +const goBack = (e) => { + e.preventDefault() + window.location.href = props.backUrl ?? initialReferrer; +} diff --git a/assets/read-ebook.js b/assets/read-ebook.js index e6c94892..bae845b8 100644 --- a/assets/read-ebook.js +++ b/assets/read-ebook.js @@ -7,12 +7,14 @@ document.addEventListener('DOMContentLoaded', () => { const css = document.getElementById(mountId).getAttribute('data-css') const bgColor = document.getElementById(mountId).getAttribute('data-background-color') const percent = document.getElementById(mountId).getAttribute('data-percent') - const progressionUrl = document.getElementById(mountId).getAttribute('data-progressionUrl') + const progressionUrl = document.getElementById(mountId).getAttribute('data-progression-url') + const backUrl = document.getElementById(mountId).getAttribute('data-back-url') createApp(ReadEBook, { file: file, css: css, bgColor: bgColor, percent: percent, - progressionUrl: progressionUrl + progressionUrl: progressionUrl, + backUrl: backUrl }).mount(`#${mountId}`); }); diff --git a/assets/styles/global.scss b/assets/styles/global.scss index b1f7373d..1679bdf0 100644 --- a/assets/styles/global.scss +++ b/assets/styles/global.scss @@ -9,6 +9,13 @@ body.bg-darker{ #vue-book-reader{ width: 100%; + .flex{ + display: flex; + button{ + display: block; + } + } + } /* diff --git a/src/Controller/BookController.php b/src/Controller/BookController.php index 3cfc95bb..fa63fe50 100644 --- a/src/Controller/BookController.php +++ b/src/Controller/BookController.php @@ -130,6 +130,10 @@ public function read( 'file' => $fileSystemManager->getBookPublicPath($book), 'body_class' => $themeSelector->isDark() ? 'bg-darker' : '', 'isDark' => $themeSelector->isDark(), + 'backUrl' => $this->generateUrl('app_book', [ + 'book' => $book->getId(), + 'slug' => $book->getSlug(), + ]), ]); case 'pdf': case 'cbr': diff --git a/templates/book/reader-files-epub.html.twig b/templates/book/reader-files-epub.html.twig index dc800810..a00b18e3 100644 --- a/templates/book/reader-files-epub.html.twig +++ b/templates/book/reader-files-epub.html.twig @@ -13,7 +13,13 @@ {% endblock %} {% block content %} -
+ {% endblock %} From 91781c0ae2ae9781b3b59c00f197fdcead222bba Mon Sep 17 00:00:00 2001 From: Laurent Constantin Date: Sun, 25 Aug 2024 10:35:43 +0200 Subject: [PATCH 02/12] feat(kobo): Images are converted to jpg --- src/Controller/Kobo/KoboImageController.php | 2 +- src/Kobo/DownloadHelper.php | 32 +++++++++---------- src/Kobo/ImageProcessor/CoverTransformer.php | 33 ++++++++++++-------- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/Controller/Kobo/KoboImageController.php b/src/Controller/Kobo/KoboImageController.php index 4f20b645..9cfc1594 100644 --- a/src/Controller/Kobo/KoboImageController.php +++ b/src/Controller/Kobo/KoboImageController.php @@ -57,6 +57,6 @@ public function imageQuality(Request $request, KoboDevice $kobo, string $uuid, i $asAttachment = str_contains((string) $request->headers->get('User-Agent'), 'Kobo'); - return $this->downloadHelper->getCoverResponse($book, $width, $height, $isGreyscale, $asAttachment); + return $this->downloadHelper->getCoverResponse($book, $width, $height, '.jpg', $isGreyscale, $asAttachment); } } diff --git a/src/Kobo/DownloadHelper.php b/src/Kobo/DownloadHelper.php index 3fb6244e..c70f6b11 100644 --- a/src/Kobo/DownloadHelper.php +++ b/src/Kobo/DownloadHelper.php @@ -8,6 +8,7 @@ use App\Kobo\ImageProcessor\CoverTransformer; use App\Service\BookFileSystemManager; use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\HeaderUtils; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -55,34 +56,33 @@ public function exists(Book $book): bool /** * @throws NotFoundHttpException */ - public function getCoverResponse(Book $book, int $width, int $height, bool $grayscale = false, bool $asAttachement = true): StreamedResponse + public function getCoverResponse(Book $book, int $width, int $height, string $extensionWithDot, bool $grayscale = false, bool $asAttachement = true): StreamedResponse { $coverPath = $this->fileSystemManager->getCoverFilename($book); if ($coverPath === null || false === $this->fileSystemManager->coverExist($book)) { throw new BookFileNotFound($coverPath); } - $response = new StreamedResponse(function () use ($coverPath, $width, $height, $grayscale) { - $this->coverTransformer->streamFile($coverPath, $width, $height, $grayscale); + $responseExtensionWithDot = $this->coverTransformer->canConvertFile($coverPath) ? $extensionWithDot : '.'.pathinfo($coverPath, PATHINFO_EXTENSION); + $response = new StreamedResponse(function () use ($coverPath, $width, $height, $grayscale, $responseExtensionWithDot) { + $this->coverTransformer->streamFile($coverPath, $width, $height, $responseExtensionWithDot, $grayscale); }, Response::HTTP_OK); - match ($book->getImageExtension()) { - 'jpg', 'jpeg' => $response->headers->set('Content-Type', 'image/jpeg'), - 'png' => $response->headers->set('Content-Type', 'image/png'), - 'gif' => $response->headers->set('Content-Type', 'image/gif'), + match ($responseExtensionWithDot) { + CoverTransformer::JPG, CoverTransformer::JPEG => $response->headers->set('Content-Type', 'image/jpeg'), + CoverTransformer::PNG => $response->headers->set('Content-Type', 'image/png'), + CoverTransformer::GIF => $response->headers->set('Content-Type', 'image/gif'), default => $response->headers->set('Content-Type', 'application/octet-stream'), }; - if ($asAttachement) { - $filename = $book->getImageFilename(); - if ($filename === null) { - return $response; - } - $encodedFilename = rawurlencode($filename); - $simpleName = rawurlencode(sprintf('book-cover--%s-%s', $book->getId(), preg_replace('/[^a-zA-Z0-9\.\-_]/', '_', $filename))); - $response->headers->set('Content-Disposition', - sprintf('attachment; filename="%s"; filename*=UTF-8\'\'%s', $simpleName, $encodedFilename)); + $filename = $book->getImageFilename(); + if ($filename === null) { + return $response; } + $encodedFilename = rawurlencode($filename); + $simpleName = rawurlencode(sprintf('book-cover--%s-%s', $book->getId(), preg_replace('/[^a-zA-Z0-9\.\-_]/', '_', $filename))); + $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition($asAttachement ? HeaderUtils::DISPOSITION_ATTACHMENT : HeaderUtils::DISPOSITION_INLINE, $encodedFilename, $simpleName)); + return $response; } diff --git a/src/Kobo/ImageProcessor/CoverTransformer.php b/src/Kobo/ImageProcessor/CoverTransformer.php index 8f70ac97..0ecf5782 100644 --- a/src/Kobo/ImageProcessor/CoverTransformer.php +++ b/src/Kobo/ImageProcessor/CoverTransformer.php @@ -8,29 +8,36 @@ class CoverTransformer public const PNG = '.png'; public const GIF = '.gif'; public const JPEG = '.jpeg'; - public const WEBP = '.wepb'; + public const WEBP = '.webp'; private function fallback(string $coverPath): void { readfile($coverPath); } - public function streamFile(string $coverPath, int $maxWidth, int $maxHeight, bool $grayscale = false): void + public function canConvertFile(string $coverPath): bool { - // Check if GD extension is loaded - if (false === function_exists('imagecreatetruecolor')) { - $this->fallback($coverPath); - - return; + if (!function_exists('imagecreatetruecolor')) { + return false; } // We only support jpeg & png & gif & webp - if (false === str_ends_with($coverPath, self::JPG) + return !(false === str_ends_with($coverPath, self::JPG) && false === str_ends_with($coverPath, self::PNG) && false === str_ends_with($coverPath, self::GIF) && false === str_ends_with($coverPath, self::JPEG) - && false === str_ends_with($coverPath, self::WEBP) - ) { + && false === str_ends_with($coverPath, self::WEBP)); + } + + public function streamFile(string $coverPath, int $maxWidth, int $maxHeight, string $extensionWithDot, bool $grayscale = false): void + { + // Make sure the extension starts with a dot + if (false === str_starts_with($extensionWithDot, '.')) { + $extensionWithDot = '.'.$extensionWithDot; + } + + // Check if the file can be converted + if (false === $this->canConvertFile($coverPath)) { $this->fallback($coverPath); return; @@ -76,8 +83,8 @@ public function streamFile(string $coverPath, int $maxWidth, int $maxHeight, boo imagefill($image, 0, 0, $blackColor); // Load the original image based on the extension - $extension = pathinfo($coverPath, PATHINFO_EXTENSION); - $originalImage = match ($extension) { + $originalExtensionWithDot = '.'.pathinfo($coverPath, PATHINFO_EXTENSION); // Add a dot to the extension + $originalImage = match ($originalExtensionWithDot) { self::PNG => imagecreatefrompng($coverPath), self::GIF => imagecreatefromgif($coverPath), self::WEBP => imagecreatefromwebp($coverPath), @@ -101,7 +108,7 @@ public function streamFile(string $coverPath, int $maxWidth, int $maxHeight, boo } // Output the image based on the extension - match ($extension) { + match ($extensionWithDot) { self::PNG => imagepng($image, null, 9), self::GIF => imagegif($image), self::WEBP => imagewebp($image), From 10039eb9eaa8f8ed57e16951c959130982819eed Mon Sep 17 00:00:00 2001 From: Laurent Constantin Date: Sun, 25 Aug 2024 10:38:50 +0200 Subject: [PATCH 03/12] fix(kobo): Extend image when source is too small --- src/Kobo/ImageProcessor/CoverTransformer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Kobo/ImageProcessor/CoverTransformer.php b/src/Kobo/ImageProcessor/CoverTransformer.php index 0ecf5782..8cbb7836 100644 --- a/src/Kobo/ImageProcessor/CoverTransformer.php +++ b/src/Kobo/ImageProcessor/CoverTransformer.php @@ -55,8 +55,8 @@ public function streamFile(string $coverPath, int $maxWidth, int $maxHeight, str $aspectRatio = $originalWidth / max(1, $originalHeight); // Calculate the new dimensions while maintaining the aspect ratio and respecting maxWidth and maxHeight - $newWidth = min($maxWidth, $originalWidth); - $newHeight = min($maxHeight, $originalHeight); + $newWidth = $maxWidth; + $newHeight = $maxHeight; // New ratio if ($newWidth / $aspectRatio > $newHeight) { From 73daa276ffa18cad5c93dadb184918f778592a97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 20:57:01 +0000 Subject: [PATCH 04/12] build(deps-dev): bump symfony/web-profiler-bundle from 6.4.10 to 7.1.3 Bumps [symfony/web-profiler-bundle](https://github.com/symfony/web-profiler-bundle) from 6.4.10 to 7.1.3. - [Release notes](https://github.com/symfony/web-profiler-bundle/releases) - [Changelog](https://github.com/symfony/web-profiler-bundle/blob/7.1/CHANGELOG.md) - [Commits](https://github.com/symfony/web-profiler-bundle/compare/v6.4.10...v7.1.3) --- updated-dependencies: - dependency-name: symfony/web-profiler-bundle dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- composer.lock | 233 ++++++++++++++++++++++++-------------------------- 2 files changed, 115 insertions(+), 120 deletions(-) diff --git a/composer.json b/composer.json index d887292e..a60034c3 100644 --- a/composer.json +++ b/composer.json @@ -176,6 +176,6 @@ "symfony/maker-bundle": "^1.0", "symfony/phpunit-bridge": "^7.0", "symfony/stopwatch": "^6.2", - "symfony/web-profiler-bundle": "^6.2" + "symfony/web-profiler-bundle": "^7.1" } } diff --git a/composer.lock b/composer.lock index 3aab2b8d..0c11579a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "014a11ba5c02a45cd8d9989f6603d811", + "content-hash": "935c85b449842665db62230ca6de5e0b", "packages": [ { "name": "acseo/typesense-bundle", @@ -4957,31 +4957,32 @@ }, { "name": "symfony/cache", - "version": "v6.4.10", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "6702d2d777260e6ff3451fee2d7d78ab5f715cdc" + "reference": "8ac37acee794372f9732fe8a61a8221f6762148e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/6702d2d777260e6ff3451fee2d7d78ab5f715cdc", - "reference": "6702d2d777260e6ff3451fee2d7d78ab5f715cdc", + "url": "https://api.github.com/repos/symfony/cache/zipball/8ac37acee794372f9732fe8a61a8221f6762148e", + "reference": "8ac37acee794372f9732fe8a61a8221f6762148e", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/cache": "^2.0|^3.0", "psr/log": "^1.1|^2|^3", "symfony/cache-contracts": "^2.5|^3", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.3.6|^7.0" + "symfony/var-exporter": "^6.4|^7.0" }, "conflict": { - "doctrine/dbal": "<2.13.1", - "symfony/dependency-injection": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/var-dumper": "<5.4" + "doctrine/dbal": "<3.6", + "symfony/dependency-injection": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/var-dumper": "<6.4" }, "provide": { "psr/cache-implementation": "2.0|3.0", @@ -4990,15 +4991,15 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/dbal": "^2.13.1|^3|^4", + "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/filesystem": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5033,7 +5034,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.10" + "source": "https://github.com/symfony/cache/tree/v7.1.3" }, "funding": [ { @@ -5049,7 +5050,7 @@ "type": "tidelift" } ], - "time": "2024-07-17T06:05:49+00:00" + "time": "2024-07-17T06:10:24+00:00" }, { "name": "symfony/cache-contracts", @@ -5774,22 +5775,22 @@ }, { "name": "symfony/error-handler", - "version": "v6.4.10", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "231f1b2ee80f72daa1972f7340297d67439224f0" + "reference": "432bb369952795c61ca1def65e078c4a80dad13c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/231f1b2ee80f72daa1972f7340297d67439224f0", - "reference": "231f1b2ee80f72daa1972f7340297d67439224f0", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/432bb369952795c61ca1def65e078c4a80dad13c", + "reference": "432bb369952795c61ca1def65e078c4a80dad13c", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/var-dumper": "^6.4|^7.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", @@ -5798,7 +5799,7 @@ "require-dev": { "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^5.4|^6.0|^7.0" + "symfony/serializer": "^6.4|^7.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -5829,7 +5830,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.10" + "source": "https://github.com/symfony/error-handler/tree/v7.1.3" }, "funding": [ { @@ -5845,28 +5846,28 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2024-07-26T13:02:51+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.8", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b" + "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8d7507f02b06e06815e56bb39aa0128e3806208b", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", + "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -5875,13 +5876,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0|^7.0" + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5909,7 +5910,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.8" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.1" }, "funding": [ { @@ -5925,7 +5926,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-05-31T14:57:53+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6680,36 +6681,36 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.10", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "117f1f20a7ade7bcea28b861fb79160a21a1e37b" + "reference": "f602d5c17d1fa02f8019ace2687d9d136b7f4a1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/117f1f20a7ade7bcea28b861fb79160a21a1e37b", - "reference": "117f1f20a7ade7bcea28b861fb79160a21a1e37b", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f602d5c17d1fa02f8019ace2687d9d136b7f4a1a", + "reference": "f602d5c17d1fa02f8019ace2687d9d136b7f4a1a", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.1", "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.3" + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4" }, "require-dev": { - "doctrine/dbal": "^2.13.1|^3|^4", + "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.3|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", - "symfony/mime": "^5.4|^6.0|^7.0", - "symfony/rate-limiter": "^5.4|^6.0|^7.0" + "symfony/cache": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6737,7 +6738,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.10" + "source": "https://github.com/symfony/http-foundation/tree/v7.1.3" }, "funding": [ { @@ -6753,7 +6754,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:36:27+00:00" + "time": "2024-07-26T12:41:01+00:00" }, { "name": "symfony/http-kernel", @@ -8370,36 +8371,34 @@ }, { "name": "symfony/routing", - "version": "v6.4.10", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "aad19fe10753ba842f0d653a8db819c4b3affa87" + "reference": "8a908a3f22d5a1b5d297578c2ceb41b02fa916d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/aad19fe10753ba842f0d653a8db819c4b3affa87", - "reference": "aad19fe10753ba842f0d653a8db819c4b3affa87", + "url": "https://api.github.com/repos/symfony/routing/zipball/8a908a3f22d5a1b5d297578c2ceb41b02fa916d0", + "reference": "8a908a3f22d5a1b5d297578c2ceb41b02fa916d0", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<6.2", - "symfony/dependency-injection": "<5.4", - "symfony/yaml": "<5.4" + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^6.2|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -8433,7 +8432,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.10" + "source": "https://github.com/symfony/routing/tree/v7.1.3" }, "funding": [ { @@ -8449,7 +8448,7 @@ "type": "tidelift" } ], - "time": "2024-07-15T09:26:24+00:00" + "time": "2024-07-17T06:10:24+00:00" }, { "name": "symfony/runtime", @@ -10098,34 +10097,32 @@ }, { "name": "symfony/var-dumper", - "version": "v6.4.10", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "a71cc3374f5fb9759da1961d28c452373b343dd4" + "reference": "86af4617cca75a6e28598f49ae0690f3b9d4591f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a71cc3374f5fb9759da1961d28c452373b343dd4", - "reference": "a71cc3374f5fb9759da1961d28c452373b343dd4", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/86af4617cca75a6e28598f49ae0690f3b9d4591f", + "reference": "86af4617cca75a6e28598f49ae0690f3b9d4591f", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/console": "<5.4" + "symfony/console": "<6.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^6.3|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/uid": "^5.4|^6.0|^7.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.0.4" }, "bin": [ "Resources/bin/var-dump-server" @@ -10163,7 +10160,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.10" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.3" }, "funding": [ { @@ -10179,30 +10176,29 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2024-07-26T12:41:01+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.9", + "version": "v7.1.2", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "f9a060622e0d93777b7f8687ec4860191e16802e" + "reference": "b80a669a2264609f07f1667f891dbfca25eba44c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f9a060622e0d93777b7f8687ec4860191e16802e", - "reference": "f9a060622e0d93777b7f8687ec4860191e16802e", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/b80a669a2264609f07f1667f891dbfca25eba44c", + "reference": "b80a669a2264609f07f1667f891dbfca25eba44c", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.2" }, "require-dev": { "symfony/property-access": "^6.4|^7.0", "symfony/serializer": "^6.4|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -10240,7 +10236,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.9" + "source": "https://github.com/symfony/var-exporter/tree/v7.1.2" }, "funding": [ { @@ -10256,7 +10252,7 @@ "type": "tidelift" } ], - "time": "2024-06-24T15:53:56+00:00" + "time": "2024-06-28T08:00:31+00:00" }, { "name": "symfony/web-link", @@ -15233,38 +15229,37 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.10", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "370c9f1e3567cd4670d44311838e37d16182c3a7" + "reference": "b9357f73d2c14dcd36783a67386f510654828668" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/370c9f1e3567cd4670d44311838e37d16182c3a7", - "reference": "370c9f1e3567cd4670d44311838e37d16182c3a7", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/b9357f73d2c14dcd36783a67386f510654828668", + "reference": "b9357f73d2c14dcd36783a67386f510654828668", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/config": "^5.4|^6.0|^7.0", + "php": ">=8.2", + "symfony/config": "^6.4|^7.0", "symfony/framework-bundle": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", - "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/twig-bundle": "^5.4|^6.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/routing": "^6.4|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", + "twig/twig": "^3.10" }, "conflict": { - "symfony/form": "<5.4", - "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4", - "symfony/twig-bundle": ">=7.0" + "symfony/form": "<6.4", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4" }, "require-dev": { - "symfony/browser-kit": "^5.4|^6.0|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/css-selector": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0" + "symfony/browser-kit": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" }, "type": "symfony-bundle", "autoload": { @@ -15295,7 +15290,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.10" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.1.3" }, "funding": [ { @@ -15311,7 +15306,7 @@ "type": "tidelift" } ], - "time": "2024-07-19T07:26:48+00:00" + "time": "2024-07-26T12:41:01+00:00" }, { "name": "theseer/tokenizer", From 98076aca706e281bc82caae1215ad948237a2b91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 25 Aug 2024 16:37:56 +0000 Subject: [PATCH 05/12] build(deps): bump symfony/psr-http-message-bridge from 6.4.10 to 7.1.3 Bumps [symfony/psr-http-message-bridge](https://github.com/symfony/psr-http-message-bridge) from 6.4.10 to 7.1.3. - [Release notes](https://github.com/symfony/psr-http-message-bridge/releases) - [Changelog](https://github.com/symfony/psr-http-message-bridge/blob/7.1/CHANGELOG.md) - [Commits](https://github.com/symfony/psr-http-message-bridge/compare/v6.4.10...v7.1.3) --- updated-dependencies: - dependency-name: symfony/psr-http-message-bridge dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- composer.lock | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index a60034c3..bd6e0bd2 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "symfony/process": "^6.2", "symfony/property-access": "^6.2", "symfony/property-info": "^7.1", - "symfony/psr-http-message-bridge": "^6.2", + "symfony/psr-http-message-bridge": "^7.1", "symfony/runtime": "^6.2", "symfony/security-bundle": "^6.2", "symfony/serializer": "^6.2", diff --git a/composer.lock b/composer.lock index 0c11579a..33d2c3e2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "935c85b449842665db62230ca6de5e0b", + "content-hash": "62bf585f3f5d63de7f07ce75d96bc57a", "packages": [ { "name": "acseo/typesense-bundle", @@ -8288,36 +8288,36 @@ }, { "name": "symfony/psr-http-message-bridge", - "version": "v6.4.10", + "version": "v7.1.3", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "89a24648d73e4eee30893b0da16abc454a65c53b" + "reference": "1365d10f5476f74a27cf9c2d1eee70c069019db0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/89a24648d73e4eee30893b0da16abc454a65c53b", - "reference": "89a24648d73e4eee30893b0da16abc454a65c53b", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/1365d10f5476f74a27cf9c2d1eee70c069019db0", + "reference": "1365d10f5476f74a27cf9c2d1eee70c069019db0", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0" + "symfony/http-foundation": "^6.4|^7.0" }, "conflict": { "php-http/discovery": "<1.15", - "symfony/http-kernel": "<6.2" + "symfony/http-kernel": "<6.4" }, "require-dev": { "nyholm/psr7": "^1.1", "php-http/discovery": "^1.15", "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^5.4|^6.0|^7.0", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/framework-bundle": "^6.2|^7.0", - "symfony/http-kernel": "^6.2|^7.0" + "symfony/browser-kit": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0" }, "type": "symfony-bridge", "autoload": { @@ -8351,7 +8351,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v6.4.10" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.1.3" }, "funding": [ { @@ -8367,7 +8367,7 @@ "type": "tidelift" } ], - "time": "2024-07-15T09:36:38+00:00" + "time": "2024-07-17T06:10:24+00:00" }, { "name": "symfony/routing", From 936acccd6f86990edbc5586a6f3744c6c357ee9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 25 Aug 2024 16:43:58 +0000 Subject: [PATCH 06/12] build(deps-dev): bump symfony/debug-bundle from 6.4.8 to 7.1.1 Bumps [symfony/debug-bundle](https://github.com/symfony/debug-bundle) from 6.4.8 to 7.1.1. - [Release notes](https://github.com/symfony/debug-bundle/releases) - [Changelog](https://github.com/symfony/debug-bundle/blob/7.1/CHANGELOG.md) - [Commits](https://github.com/symfony/debug-bundle/compare/v6.4.8...v7.1.1) --- updated-dependencies: - dependency-name: symfony/debug-bundle dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- composer.lock | 44 ++++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/composer.json b/composer.json index bd6e0bd2..e3104398 100644 --- a/composer.json +++ b/composer.json @@ -172,7 +172,7 @@ "roave/security-advisories": "dev-latest", "symfony/browser-kit": "^7.1", "symfony/css-selector": "^7.1", - "symfony/debug-bundle": "^6.2", + "symfony/debug-bundle": "^7.1", "symfony/maker-bundle": "^1.0", "symfony/phpunit-bridge": "^7.0", "symfony/stopwatch": "^6.2", diff --git a/composer.lock b/composer.lock index 33d2c3e2..5b61b8ca 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "62bf585f3f5d63de7f07ce75d96bc57a", + "content-hash": "92c8ef0b3a14928ba6c20145c35d7140", "packages": [ { "name": "acseo/typesense-bundle", @@ -4467,16 +4467,16 @@ }, { "name": "psr/log", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "reference": "79dff0b268932c640297f5208d6298f71855c03e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/php-fig/log/zipball/79dff0b268932c640297f5208d6298f71855c03e", + "reference": "79dff0b268932c640297f5208d6298f71855c03e", "shasum": "" }, "require": { @@ -4511,9 +4511,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "source": "https://github.com/php-fig/log/tree/3.0.1" }, - "time": "2021-07-14T16:46:02+00:00" + "time": "2024-08-21T13:31:24+00:00" }, { "name": "ralouphie/getallheaders", @@ -14914,33 +14914,33 @@ }, { "name": "symfony/debug-bundle", - "version": "v6.4.8", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", - "reference": "689f1bcb0bd3b945e3c671cbd06274b127c64dc9" + "reference": "aa024d28ce7ce0c6a16ee57c066838bece92893f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/689f1bcb0bd3b945e3c671cbd06274b127c64dc9", - "reference": "689f1bcb0bd3b945e3c671cbd06274b127c64dc9", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/aa024d28ce7ce0c6a16ee57c066838bece92893f", + "reference": "aa024d28ce7ce0c6a16ee57c066838bece92893f", "shasum": "" }, "require": { "ext-xml": "*", - "php": ">=8.1", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/twig-bridge": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "php": ">=8.2", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "conflict": { - "symfony/config": "<5.4", - "symfony/dependency-injection": "<5.4" + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4" }, "require-dev": { - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" + "symfony/config": "^6.4|^7.0", + "symfony/web-profiler-bundle": "^6.4|^7.0" }, "type": "symfony-bundle", "autoload": { @@ -14968,7 +14968,7 @@ "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug-bundle/tree/v6.4.8" + "source": "https://github.com/symfony/debug-bundle/tree/v7.1.1" }, "funding": [ { @@ -14984,7 +14984,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-05-31T14:55:39+00:00" }, { "name": "symfony/dom-crawler", From a694c1e2f09dce49c1d19c96162dc7fa27c19262 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 25 Aug 2024 16:52:07 +0000 Subject: [PATCH 07/12] build(deps): bump symfony/yaml from 6.4.8 to 7.1.1 Bumps [symfony/yaml](https://github.com/symfony/yaml) from 6.4.8 to 7.1.1. - [Release notes](https://github.com/symfony/yaml/releases) - [Changelog](https://github.com/symfony/yaml/blob/7.1/CHANGELOG.md) - [Commits](https://github.com/symfony/yaml/compare/v6.4.8...v7.1.1) --- updated-dependencies: - dependency-name: symfony/yaml dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- composer.lock | 21 ++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index e3104398..946e0218 100644 --- a/composer.json +++ b/composer.json @@ -65,7 +65,7 @@ "symfony/validator": "^6.2", "symfony/web-link": "^6.2", "symfony/webpack-encore-bundle": "^2.0", - "symfony/yaml": "^6.2", + "symfony/yaml": "^7.1", "twig/extra-bundle": "^2.12|^3.0", "twig/twig": "^2.12|^3.0" }, diff --git a/composer.lock b/composer.lock index 5b61b8ca..4f965b7e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "92c8ef0b3a14928ba6c20145c35d7140", + "content-hash": "2d7df2e20b37bc1e667c49bd1b2342de", "packages": [ { "name": "acseo/typesense-bundle", @@ -10410,28 +10410,27 @@ }, { "name": "symfony/yaml", - "version": "v6.4.8", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "52903de178d542850f6f341ba92995d3d63e60c9" + "reference": "fa34c77015aa6720469db7003567b9f772492bf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/52903de178d542850f6f341ba92995d3d63e60c9", - "reference": "52903de178d542850f6f341ba92995d3d63e60c9", + "url": "https://api.github.com/repos/symfony/yaml/zipball/fa34c77015aa6720469db7003567b9f772492bf2", + "reference": "fa34c77015aa6720469db7003567b9f772492bf2", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/console": "<5.4" + "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -10462,7 +10461,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.8" + "source": "https://github.com/symfony/yaml/tree/v7.1.1" }, "funding": [ { @@ -10478,7 +10477,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-05-31T14:57:53+00:00" }, { "name": "twig/extra-bundle", From 425c1a31d02d8496dfa5a0eb200dcfb2104df875 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 25 Aug 2024 16:56:40 +0000 Subject: [PATCH 08/12] build(deps): bump symfony/intl from 6.4.8 to 7.1.1 Bumps [symfony/intl](https://github.com/symfony/intl) from 6.4.8 to 7.1.1. - [Release notes](https://github.com/symfony/intl/releases) - [Changelog](https://github.com/symfony/intl/blob/7.1/CHANGELOG.md) - [Commits](https://github.com/symfony/intl/compare/v6.4.8...v7.1.1) --- updated-dependencies: - dependency-name: symfony/intl dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- composer.json | 2 +- composer.lock | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index 946e0218..bbd2e5d2 100644 --- a/composer.json +++ b/composer.json @@ -44,7 +44,7 @@ "symfony/form": "^7.1", "symfony/framework-bundle": "^6.2", "symfony/http-client": "^6.2", - "symfony/intl": "^6.2", + "symfony/intl": "^7.1", "symfony/mailer": "^6.2", "symfony/mime": "^7.1", "symfony/monolog-bundle": "^3.0", diff --git a/composer.lock b/composer.lock index 4f965b7e..062fb0aa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2d7df2e20b37bc1e667c49bd1b2342de", + "content-hash": "b7b7b75ad066eb8f4f0636b738cfd60b", "packages": [ { "name": "acseo/typesense-bundle", @@ -6872,25 +6872,28 @@ }, { "name": "symfony/intl", - "version": "v6.4.8", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "50265cdcf5a44bec3fcf487b5d0015aece91d1eb" + "reference": "66c1ecda092b1130ada2cf5f59dacfd5b6e9c99c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/50265cdcf5a44bec3fcf487b5d0015aece91d1eb", - "reference": "50265cdcf5a44bec3fcf487b5d0015aece91d1eb", + "url": "https://api.github.com/repos/symfony/intl/zipball/66c1ecda092b1130ada2cf5f59dacfd5b6e9c99c", + "reference": "66c1ecda092b1130ada2cf5f59dacfd5b6e9c99c", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/string": "<7.1" }, "require-dev": { - "symfony/filesystem": "^5.4|^6.0|^7.0", - "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/filesystem": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6935,7 +6938,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.4.8" + "source": "https://github.com/symfony/intl/tree/v7.1.1" }, "funding": [ { @@ -6951,7 +6954,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-05-31T14:57:53+00:00" }, { "name": "symfony/mailer", From 9f7c7ed5caffc4f8d828be15b1ebb2c9fa544218 Mon Sep 17 00:00:00 2001 From: Laurent Constantin Date: Sat, 17 Aug 2024 11:44:39 +0200 Subject: [PATCH 09/12] feat(kobo): composer require symfony/messenger --- composer.json | 1 + composer.lock | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index bbd2e5d2..d70aea71 100644 --- a/composer.json +++ b/composer.json @@ -46,6 +46,7 @@ "symfony/http-client": "^6.2", "symfony/intl": "^7.1", "symfony/mailer": "^6.2", + "symfony/messenger": "^6.2", "symfony/mime": "^7.1", "symfony/monolog-bundle": "^3.0", "symfony/notifier": "^7.1", diff --git a/composer.lock b/composer.lock index 062fb0aa..be5d169e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b7b7b75ad066eb8f4f0636b738cfd60b", + "content-hash": "e853de97e2941e34c342ccb09bd3c784", "packages": [ { "name": "acseo/typesense-bundle", From 94ad066e379e1f13f2122c77c5f832323747632a Mon Sep 17 00:00:00 2001 From: Laurent Constantin Date: Sun, 18 Aug 2024 11:11:40 +0200 Subject: [PATCH 10/12] feat(kobo): Convert ebooks using kepubify on the fly --- .env | 2 +- config/services.yaml | 2 + src/Kobo/DownloadHelper.php | 36 ++++++--- src/Kobo/Messenger/KepubifyMessage.php | 21 ++++++ src/Kobo/Messenger/KepubifyMessageHandler.php | 74 +++++++++++++++++++ .../Kobo/KoboDownloadControllerTest.php | 2 +- 6 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 src/Kobo/Messenger/KepubifyMessage.php create mode 100644 src/Kobo/Messenger/KepubifyMessageHandler.php diff --git a/.env b/.env index b20bbb2c..54dbb535 100644 --- a/.env +++ b/.env @@ -50,4 +50,4 @@ BOOK_FILE_NAMING_FORMAT="{serie}-{serieIndex}-{title}" KOBO_PROXY_USE_DEV=0 KOBO_PROXY_USE_EVERYWHERE=0 KOBO_PROXY_ENABLED=1 -###< kobo/proxy \ No newline at end of file +###< kobo/proxy diff --git a/config/services.yaml b/config/services.yaml index e22f5b7f..5a58c8d4 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -14,6 +14,8 @@ parameters: KOBO_API_URL: '%env(KOBO_API_URL)%' env(KOBO_IMAGE_API_URL): "https://cdn.kobo.com/book-images" KOBO_IMAGE_API_URL: '%env(KOBO_IMAGE_API_URL)%' + env(KEPUBIFY_BIN): "/usr/bin/kepubify" + KEPUBIFY_BIN: '%env(KEPUBIFY_BIN)%' services: # default configuration for services in *this* file _defaults: diff --git a/src/Kobo/DownloadHelper.php b/src/Kobo/DownloadHelper.php index c70f6b11..16ec1b46 100644 --- a/src/Kobo/DownloadHelper.php +++ b/src/Kobo/DownloadHelper.php @@ -6,12 +6,15 @@ use App\Entity\KoboDevice; use App\Exception\BookFileNotFound; use App\Kobo\ImageProcessor\CoverTransformer; +use App\Kobo\Messenger\KepubifyMessage; use App\Service\BookFileSystemManager; use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\HeaderUtils; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; class DownloadHelper @@ -20,8 +23,9 @@ public function __construct( private readonly BookFileSystemManager $fileSystemManager, private readonly CoverTransformer $coverTransformer, protected UrlGeneratorInterface $urlGenerator, - protected LoggerInterface $logger) - { + protected LoggerInterface $logger, + protected MessageBusInterface $messageBus + ) { } protected function getBookFilename(Book $book): string @@ -86,15 +90,20 @@ public function getCoverResponse(Book $book, int $width, int $height, string $ex return $response; } - public function getResponse(Book $book): StreamedResponse + public function getResponse(Book $book): Response { $bookPath = $this->getBookFilename($book); if (false === $this->exists($book)) { throw new BookFileNotFound($bookPath); } - $response = new StreamedResponse(function () use ($bookPath) { - readfile($bookPath); - }, Response::HTTP_OK); + + // Convert the file to kepub (Kobo's epub format) as a temporary file + $temporaryFile = $this->runKepubify($bookPath); + $fileToStream = $temporaryFile ?? $bookPath; + $fileSize = filesize($fileToStream); + + $response = (new BinaryFileResponse($fileToStream, Response::HTTP_OK)) + ->deleteFileAfterSend($temporaryFile !== null); $filename = $book->getBookFilename(); $encodedFilename = rawurlencode($filename); @@ -104,10 +113,11 @@ public function getResponse(Book $book): StreamedResponse 'epub', 'epub3' => 'application/epub+zip', default => 'application/octet-stream' }); - $response->headers->set('Content-Disposition', - sprintf('attachment; filename="%s"; filename*=UTF-8\'\'%s', $simpleName, $encodedFilename)); + $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, $encodedFilename, $simpleName)); - $response->headers->set('Content-Length', (string) $this->getSize($book)); + if ($fileSize !== false) { + $response->headers->set('Content-Length', (string) $fileSize); + } return $response; } @@ -116,4 +126,12 @@ public function coverExist(Book $book): bool { return $this->fileSystemManager->coverExist($book); } + + private function runKepubify(string $bookPath): ?string + { + $conversionDto = new KepubifyMessage($bookPath); + $this->messageBus->dispatch($conversionDto); + + return $conversionDto->destination; + } } diff --git a/src/Kobo/Messenger/KepubifyMessage.php b/src/Kobo/Messenger/KepubifyMessage.php new file mode 100644 index 00000000..12973ae6 --- /dev/null +++ b/src/Kobo/Messenger/KepubifyMessage.php @@ -0,0 +1,21 @@ +kepubifyBinary) === '') { + return; + } + + // Create a temporary file + $temporaryFile = $this->getTemporaryFilename(); + if ($temporaryFile === false) { + $this->logger->error('Error while creating temporary file'); + + return; + } + + // Run the conversion + $process = new Process([$this->kepubifyBinary, '--output', $temporaryFile, $message->source]); + $this->logger->debug('Run kepubify command: {command}', ['command' => $process->getCommandLine()]); + $process->run(); + + if (!$process->isSuccessful()) { + $this->logger->error('Error while running kepubify: {output}: {error}', [ + 'output' => $process->getOutput(), + 'error' => $process->getErrorOutput(), + ]); + @unlink($temporaryFile); + + return; + } + + $message->destination = $temporaryFile; + } + + /** + * Create a temporary file to handle the conversion result. + * Note that the name must be unique to handle concurrent requests + * because the file will be deleted once the request is served. + * + * @return string|false + */ + private function getTemporaryFilename(): string|false + { + $dir = $this->cacheDir.self::CACHE_FOLDER; + if (!is_dir($dir) && !mkdir($dir, 0777, true) && !is_dir($dir)) { + return false; + } + + return tempnam($dir, self::TEMP_NAME_SUFFIX); + } +} diff --git a/tests/Controller/Kobo/KoboDownloadControllerTest.php b/tests/Controller/Kobo/KoboDownloadControllerTest.php index a337aecf..62bbfeaf 100644 --- a/tests/Controller/Kobo/KoboDownloadControllerTest.php +++ b/tests/Controller/Kobo/KoboDownloadControllerTest.php @@ -29,7 +29,7 @@ public function testDownload(): void self::assertResponseHeaderSame('Content-Type', 'application/epub+zip'); self::assertResponseHasHeader('Content-Length'); - $expectedDisposition = "attachment; filename=\"book-1-TheOdysses.epub\"; filename*=UTF-8''TheOdysses.epub"; + $expectedDisposition = "attachment; filename=book-1-TheOdysses.epub; filename*=utf-8''TheOdysses.epub"; self::assertResponseHeaderSame('Content-Disposition', $expectedDisposition, 'The Content-Disposition header is not as expected'); } From ecc548bc71dbfcf6bcf7071fffebf3d524e0295c Mon Sep 17 00:00:00 2001 From: Laurent Constantin Date: Sun, 18 Aug 2024 12:34:57 +0200 Subject: [PATCH 11/12] feat(kobo): Use the kepub url extension to provide the ebook to kobo --- .../Kobo/KoboDownloadController.php | 4 +- src/Kobo/DownloadHelper.php | 29 ++++++--- src/Kobo/Kepubify/KepubifyEnabler.php | 37 +++++++++++ .../KepubifyMessage.php | 2 +- .../KepubifyMessageHandler.php | 9 ++- src/Kobo/Response/MetadataResponseService.php | 18 +++++- .../Kobo/KoboDownloadControllerTest.php | 63 ++++++++++++++++++- 7 files changed, 140 insertions(+), 22 deletions(-) create mode 100644 src/Kobo/Kepubify/KepubifyEnabler.php rename src/Kobo/{Messenger => Kepubify}/KepubifyMessage.php (93%) rename src/Kobo/{Messenger => Kepubify}/KepubifyMessageHandler.php (87%) diff --git a/src/Controller/Kobo/KoboDownloadController.php b/src/Controller/Kobo/KoboDownloadController.php index 0fb4e719..db56ac10 100644 --- a/src/Controller/Kobo/KoboDownloadController.php +++ b/src/Controller/Kobo/KoboDownloadController.php @@ -25,11 +25,11 @@ public function __construct( } #[Route('/v1/download/{id}.{extension}', name: 'download', requirements: ['bookId' => '\d+', 'extension' => '[A-Za-z0-9]+'], methods: ['GET'])] - public function download(KoboDevice $kobo, Book $book): Response + public function download(KoboDevice $kobo, Book $book, string $extension): Response { $this->assertCanDownload($kobo, $book); - return $this->downloadHelper->getResponse($book); + return $this->downloadHelper->getResponse($book, $extension); } private function assertCanDownload(KoboDevice $kobo, Book $book): void diff --git a/src/Kobo/DownloadHelper.php b/src/Kobo/DownloadHelper.php index 16ec1b46..d50b38e9 100644 --- a/src/Kobo/DownloadHelper.php +++ b/src/Kobo/DownloadHelper.php @@ -6,7 +6,8 @@ use App\Entity\KoboDevice; use App\Exception\BookFileNotFound; use App\Kobo\ImageProcessor\CoverTransformer; -use App\Kobo\Messenger\KepubifyMessage; +use App\Kobo\Kepubify\KepubifyMessage; +use App\Kobo\Response\MetadataResponseService; use App\Service\BookFileSystemManager; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\BinaryFileResponse; @@ -43,12 +44,12 @@ public function getCoverSize(Book $book): int return $this->fileSystemManager->getCoverSize($book) ?? 0; } - public function getUrlForKoboDevice(Book $book, KoboDevice $kobo): string + public function getUrlForKoboDevice(Book $book, KoboDevice $kobo, string $extension): string { return $this->urlGenerator->generate('app_kobodownload', [ 'id' => $book->getId(), 'accessKey' => $kobo->getAccessKey(), - 'extension' => $book->getExtension(), + 'extension' => $extension, ], UrlGeneratorInterface::ABSOLUTE_URL); } @@ -90,27 +91,37 @@ public function getCoverResponse(Book $book, int $width, int $height, string $ex return $response; } - public function getResponse(Book $book): Response + /** + * @throws NotFoundHttpException Book conversion failed + */ + public function getResponse(Book $book, string $format): Response { $bookPath = $this->getBookFilename($book); if (false === $this->exists($book)) { throw new BookFileNotFound($bookPath); } - // Convert the file to kepub (Kobo's epub format) as a temporary file - $temporaryFile = $this->runKepubify($bookPath); + $temporaryFile = null; + + if ($format === MetadataResponseService::KEPUB_FORMAT) { + $temporaryFile = $this->runKepubify($bookPath); + if ($temporaryFile === null) { + throw new NotFoundHttpException('The conversion to KEPUB failed'); + } + } + $fileToStream = $temporaryFile ?? $bookPath; $fileSize = filesize($fileToStream); $response = (new BinaryFileResponse($fileToStream, Response::HTTP_OK)) ->deleteFileAfterSend($temporaryFile !== null); - $filename = $book->getBookFilename(); + $filename = basename($book->getBookFilename(), $book->getExtension()).strtolower($format); $encodedFilename = rawurlencode($filename); $simpleName = rawurlencode(sprintf('book-%s-%s', $book->getId(), preg_replace('/[^a-zA-Z0-9\.\-_]/', '_', $filename))); - $response->headers->set('Content-Type', match (strtolower($book->getExtension())) { - 'epub', 'epub3' => 'application/epub+zip', + $response->headers->set('Content-Type', match (strtoupper($format)) { + MetadataResponseService::KEPUB_FORMAT, MetadataResponseService::EPUB_FORMAT, MetadataResponseService::EPUB3_FORMAT => 'application/epub+zip', default => 'application/octet-stream' }); $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, $encodedFilename, $simpleName)); diff --git a/src/Kobo/Kepubify/KepubifyEnabler.php b/src/Kobo/Kepubify/KepubifyEnabler.php new file mode 100644 index 00000000..44778e58 --- /dev/null +++ b/src/Kobo/Kepubify/KepubifyEnabler.php @@ -0,0 +1,37 @@ +kepubifyBinary = $kepubifyBinary; + } + + public function isEnabled(): bool + { + return trim($this->kepubifyBinary) !== ''; + } + + public function getKepubifyBinary(): string + { + return $this->kepubifyBinary; + } + + public function disable(): string + { + $lastValue = $this->kepubifyBinary; + $this->kepubifyBinary = ''; + + return $lastValue; + } +} diff --git a/src/Kobo/Messenger/KepubifyMessage.php b/src/Kobo/Kepubify/KepubifyMessage.php similarity index 93% rename from src/Kobo/Messenger/KepubifyMessage.php rename to src/Kobo/Kepubify/KepubifyMessage.php index 12973ae6..38a26426 100644 --- a/src/Kobo/Messenger/KepubifyMessage.php +++ b/src/Kobo/Kepubify/KepubifyMessage.php @@ -1,6 +1,6 @@ kepubifyBinary) === '') { + if (false === $this->kepubifyEnabler->isEnabled()) { return; } @@ -38,7 +37,7 @@ public function __invoke(KepubifyMessage $message): void } // Run the conversion - $process = new Process([$this->kepubifyBinary, '--output', $temporaryFile, $message->source]); + $process = new Process([$this->kepubifyEnabler->getKepubifyBinary(), '--output', $temporaryFile, $message->source]); $this->logger->debug('Run kepubify command: {command}', ['command' => $process->getCommandLine()]); $process->run(); diff --git a/src/Kobo/Response/MetadataResponseService.php b/src/Kobo/Response/MetadataResponseService.php index 9f6d2e15..2e2f98f9 100644 --- a/src/Kobo/Response/MetadataResponseService.php +++ b/src/Kobo/Response/MetadataResponseService.php @@ -5,11 +5,18 @@ use App\Entity\Book; use App\Entity\KoboDevice; use App\Kobo\DownloadHelper; +use App\Kobo\Kepubify\KepubifyEnabler; use App\Kobo\SyncToken; class MetadataResponseService { - public function __construct(protected DownloadHelper $downloadHelper) + public const KEPUB_FORMAT = 'KEPUB'; + public const EPUB3_FORMAT = 'EPUB3'; + public const EPUB_FORMAT = 'EPUB'; + + public function __construct( + protected DownloadHelper $downloadHelper, + protected KepubifyEnabler $kepubifyEnabler) { } @@ -21,12 +28,17 @@ protected function getDownloadUrls(Book $book, KoboDevice $kobo, ?array $filters $response = []; - $formats = ['EPUB3']; // EPUB3 is required for Kobo + $formats = [self::EPUB3_FORMAT]; // At least EPUB3 is required for Kobo + if ($this->kepubifyEnabler->isEnabled()) { + $formats[] = self::KEPUB_FORMAT; + } + foreach ($formats as $format) { // and ... EPUB3FL ?; + $extension = $format === self::KEPUB_FORMAT ? $format : $book->getExtension(); $response[] = [ 'Format' => $format, 'Size' => $this->downloadHelper->getSize($book), - 'Url' => $this->downloadHelper->getUrlForKoboDevice($book, $kobo), + 'Url' => $this->downloadHelper->getUrlForKoboDevice($book, $kobo, $extension), 'Platform' => $platform, ]; } diff --git a/tests/Controller/Kobo/KoboDownloadControllerTest.php b/tests/Controller/Kobo/KoboDownloadControllerTest.php index 62bbfeaf..f4534360 100644 --- a/tests/Controller/Kobo/KoboDownloadControllerTest.php +++ b/tests/Controller/Kobo/KoboDownloadControllerTest.php @@ -6,6 +6,8 @@ use App\Entity\Book; use App\Entity\KoboDevice; use App\Kobo\DownloadHelper; +use App\Kobo\Kepubify\KepubifyEnabler; +use App\Kobo\Response\MetadataResponseService; class KoboDownloadControllerTest extends AbstractKoboControllerTest { @@ -14,6 +16,55 @@ public function testDownload(): void $client = static::getClient(); $this->injectFakeFileSystemManager(); + $book = $this->findByIdAndKobo(BookFixture::ID, $this->getKoboDevice()); + self::assertNotNull($book, 'The book is not linked to the Kobo'); + + /** @var DownloadHelper $downloadHelper */ + $downloadHelper = self::getContainer()->get(DownloadHelper::class); + + self::assertTrue($downloadHelper->exists($book), 'The book file does not exist'); + + $client?->request('GET', sprintf('/kobo/%s/v1/download/%s.%s', $this->accessKey, BookFixture::ID, 'epub')); + + self::assertResponseIsSuccessful(); + self::assertResponseHeaderSame('Content-Type', 'application/epub+zip'); + self::assertResponseHasHeader('Content-Length'); + $expectedDisposition = "attachment; filename=book-1-TheOdysses.epub; filename*=utf-8''TheOdysses.epub"; + self::assertResponseHeaderSame('Content-Disposition', $expectedDisposition, 'The Content-Disposition header is not as expected'); + + } + + public function testDownloadKepubFailed(): void + { + $client = static::getClient(); + $this->injectFakeFileSystemManager(); + + // Disable Kepubify conversion + $lastValue = $this->getKepubifyEnabler()->disable(); + + try { + $book = $this->findByIdAndKobo(BookFixture::ID, $this->getKoboDevice()); + self::assertNotNull($book, 'The book is not linked to the Kobo'); + + /** @var DownloadHelper $downloadHelper */ + $downloadHelper = self::getContainer()->get(DownloadHelper::class); + + self::assertTrue($downloadHelper->exists($book), 'The book file does not exist'); + + + $client?->request('GET', sprintf('/kobo/%s/v1/download/%s.%s', $this->accessKey, BookFixture::ID, MetadataResponseService::KEPUB_FORMAT)); + self::assertResponseStatusCodeSame(404); // We can not download kepub as the conversion is disabled + } finally { + // Re-enable Kepubify conversion for other tests + $this->getKepubifyEnabler()->setKepubifyBinary($lastValue); + } + } + + public function testDownloadKepub(): void + { + $client = static::getClient(); + $this->injectFakeFileSystemManager(); + $book = $this->findByIdAndKobo(BookFixture::ID, $this->getKoboDevice()); self::assertNotNull($book, 'The book is not linked to the Kobo'); @@ -23,13 +74,13 @@ public function testDownload(): void self::assertTrue($downloadHelper->exists($book), 'The book file does not exist'); - $client?->request('GET', sprintf('/kobo/%s/v1/download/%s.epub', $this->accessKey, BookFixture::ID)); + $client?->request('GET', sprintf('/kobo/%s/v1/download/%s.'.MetadataResponseService::KEPUB_FORMAT, $this->accessKey, BookFixture::ID)); self::assertResponseIsSuccessful(); self::assertResponseHeaderSame('Content-Type', 'application/epub+zip'); self::assertResponseHasHeader('Content-Length'); - $expectedDisposition = "attachment; filename=book-1-TheOdysses.epub; filename*=utf-8''TheOdysses.epub"; + $expectedDisposition = "attachment; filename=book-1-TheOdysses.kepub; filename*=utf-8''TheOdysses.kepub"; self::assertResponseHeaderSame('Content-Disposition', $expectedDisposition, 'The Content-Disposition header is not as expected'); } @@ -38,4 +89,12 @@ private function findByIdAndKobo(int $bookId, KoboDevice $kobo): ?Book { return $this->getEntityManager()->getRepository(Book::class)->findByIdAndKoboDevice($bookId, $kobo); } + + private function getKepubifyEnabler(): KepubifyEnabler + { + $service = self::getContainer()->get(KepubifyEnabler::class); + assert($service instanceof KepubifyEnabler); + + return $service; + } } \ No newline at end of file From 6ee58fe9d5af521cb50d04e23bcc5b10a25c069c Mon Sep 17 00:00:00 2001 From: Laurent Constantin Date: Sun, 25 Aug 2024 09:02:28 +0200 Subject: [PATCH 12/12] feat(kobo): Install kepubify on pipeline --- .env.test | 2 +- .github/workflows/symfony.yml | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.env.test b/.env.test index 16c52ced..d2ff4f8b 100644 --- a/.env.test +++ b/.env.test @@ -13,4 +13,4 @@ TYPESENSE_KEY=xyz # Disable the proxy for the test env KOBO_PROXY_USE_EVERYWHERE=0 -KOBO_PROXY_ENABLED=0 \ No newline at end of file +KOBO_PROXY_ENABLED=0 diff --git a/.github/workflows/symfony.yml b/.github/workflows/symfony.yml index d38b77b4..e0cc84e5 100644 --- a/.github/workflows/symfony.yml +++ b/.github/workflows/symfony.yml @@ -31,7 +31,9 @@ jobs: php-version: '8.2' - uses: actions/checkout@v3 - name: Copy .env.test.local - run: php -r "file_exists('.env.test.local') || copy('.env.test', '.env.test.local');" + run: | + php -r "file_exists('.env.test.local') || copy('.env.test', '.env.test.local');" + echo "KEPUBIFY_BIN=/usr/local/bin/kepubify" >> .env.test.local - name: Cache Composer packages id: composer-cache uses: actions/cache@v3 @@ -42,6 +44,28 @@ jobs: ${{ runner.os }}-php- - name: Install Dependencies run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist + - name: Cache kepubify + id: kepubify-cache-restore + uses: actions/cache@v3 + with: + path: /usr/local/bin/kepubify + key: ${{ runner.os }}-kepubify-cache + - name: Install kepubify + if: steps.kepubify-cache-restore.outputs.cache-hit != 'true' + run: | + mkdir -p /usr/local/bin/ + # Install kepubify (from https://github.com/linuxserver/docker-calibre-web/blob/master/Dockerfile) + KEPUBIFY_RELEASE=$(curl -sX GET "https://api.github.com/repos/pgaskin/kepubify/releases/latest" | awk '/tag_name/{print $4;exit}' FS='[""]'); + curl -o /usr/local/bin/kepubify -L https://github.com/pgaskin/kepubify/releases/download/${KEPUBIFY_RELEASE}/kepubify-linux-64bit + chmod +x /usr/local/bin/kepubify + - name: Cache kepubify + uses: actions/cache/save@v4 + if: steps.kepubify-cache-restore.outputs.cache-hit != 'true' + id: kepubify-cache-save + with: + path: /usr/local/bin/kepubify + key: ${{ runner.os }}-kepubify-cache + - name: Create Database run: | mkdir -p data