From 1871b7237da09527f5efdf939895ba266d38e25b Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Thu, 21 Jul 2022 14:18:24 +0200 Subject: [PATCH] wait #5370 @0.25 --- .../CompositionOperation.php | 22 +++ app/Jobs/FluidbookDocumentFileProcess.php | 44 ++++++ app/Jobs/FluidbookDocumentUpload.php | 52 +++++++ app/Models/FluidbookDocument.php | 138 ++++++++++++------ resources/quiz/style/030-quiz.sass | 4 +- .../fields/fluidbook_composition.blade.php | 41 ++++-- 6 files changed, 247 insertions(+), 54 deletions(-) create mode 100644 app/Jobs/FluidbookDocumentFileProcess.php create mode 100644 app/Jobs/FluidbookDocumentUpload.php diff --git a/app/Http/Controllers/Admin/Operations/FluidbookPublication/CompositionOperation.php b/app/Http/Controllers/Admin/Operations/FluidbookPublication/CompositionOperation.php index 27706990a..127514524 100644 --- a/app/Http/Controllers/Admin/Operations/FluidbookPublication/CompositionOperation.php +++ b/app/Http/Controllers/Admin/Operations/FluidbookPublication/CompositionOperation.php @@ -2,9 +2,12 @@ namespace App\Http\Controllers\Admin\Operations\FluidbookPublication; +use App\Jobs\FluidbookDocumentUpload; use App\Models\FluidbookDocument; use Cubist\Backpack\Http\Controllers\Base\XSendFileController; +use Cubist\Util\Crypt; use Cubist\Util\Files\Files; +use Cubist\Util\Str; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Session; @@ -14,6 +17,7 @@ trait CompositionOperation { Route::match(['get'], $segment . '/{id}/composition', $controller . '@getComposition'); Route::match(['get'], $segment . '/docs/{doc_id}/thumb_{doc_page}.jpg', $controller . '@getThumb'); + Route::match(['post'], $segment . '/uploaddocument', $controller . '@upload'); } protected function setupCompositionDefaults() @@ -28,4 +32,22 @@ trait CompositionOperation $path = $doc->getFile($doc_page, 'jpg', 'thumb', true, true, ''); return XSendFileController::sendfile($path); } + + protected function upload() + { + $uploadID = Str::random(); + FluidbookDocumentUpload::updateProgression($uploadID, __('Copie du document'), 1); + + $file = request()->file('file'); + $document = new FluidbookDocument(); + $document->file = $file->getClientOriginalName(); + $document->file_data = ["fileName" => $file->getClientOriginalName(), "fileSize" => $file->getSize(), "modificationDate" => $file->getMTime(), "creationDate" => $file->getCTime()]; + $document->owner = backpack_user()->id; + $document->save(); + move_uploaded_file($file->getPathname(), Files::mkdir($document->path()) . 'original.pdf'); + FluidbookDocumentUpload::updateProgression($uploadID, __('Mise en file d\'attente du traitement du document'), 1.2); + + FluidbookDocumentUpload::dispatch($uploadID, $document, backpack_user()); + return response()->json(['uploadID' => $uploadID]); + } } diff --git a/app/Jobs/FluidbookDocumentFileProcess.php b/app/Jobs/FluidbookDocumentFileProcess.php new file mode 100644 index 000000000..970032b84 --- /dev/null +++ b/app/Jobs/FluidbookDocumentFileProcess.php @@ -0,0 +1,44 @@ +onQueue('fluidbookprocess'); + $this->document = $document; + $this->page = $page; + $this->format = $format; + $this->resolution = $resolution; + $this->withGraphics = $withGraphics; + $this->withText = $withText; + $this->version = $version; + $this->force = $force; + } + + public function handle() + { + $this->document->getFile($this->page, $this->format, $this->resolution, $this->withText, $this->withGraphics, $this->version, $this->force); + } + + /** + * @return boolean + */ + public function isDone() + { + return $this->document->hasFile($this->page, $this->format, $this->resolution, $this->withText, $this->withGraphics, $this->version); + } +} diff --git a/app/Jobs/FluidbookDocumentUpload.php b/app/Jobs/FluidbookDocumentUpload.php new file mode 100644 index 000000000..13ea82c5c --- /dev/null +++ b/app/Jobs/FluidbookDocumentUpload.php @@ -0,0 +1,52 @@ +onQueue('fluidbookprocess'); + $this->uploadID = $uploadID; + $this->document = $document; + $this->setUser($user); + } + + public function handle() + { + FluidbookDocumentUpload::updateProgression($this->uploadID, __('Début du traitement du document'), 1.25); + $this->document->processUpload($this->uploadID); + } + + public static function updateProgression($id, $message, $progress) + { + Cache::put('FluidbookDocumentUpload_' . $id, ['message' => $message, 'progress' => $progress]); + } + + public static function getProgression($id) + { + $key = 'FluidbookDocumentUpload_' . $id; + if (Cache::has($key)) { + return Cache::get($key); + } + return ['message' => '', 'progress' => 0]; + } +} diff --git a/app/Models/FluidbookDocument.php b/app/Models/FluidbookDocument.php index 70b1d0a6e..08ad55933 100644 --- a/app/Models/FluidbookDocument.php +++ b/app/Models/FluidbookDocument.php @@ -2,12 +2,15 @@ namespace App\Models; +use App\Jobs\FluidbookDocumentFileProcess; +use App\Jobs\FluidbookDocumentUpload; use App\Models\Base\ToolboxModel; use App\Util\FluidbookFarm; use Cubist\Backpack\Magic\Fields\Integer; use Cubist\Backpack\Magic\Fields\Text; use Cubist\Backpack\Magic\Fields\Textarea; use Cubist\PDF\PDFTools; +use Illuminate\Support\Facades\Cache; class FluidbookDocument extends ToolboxModel { @@ -42,6 +45,35 @@ class FluidbookDocument extends ToolboxModel return sqrt($a4surface / $docSurface); } + public function processUpload($uploadID) + { + FluidbookDocumentUpload::updateProgression($uploadID, __('Analyse du document'), 1.3); + $this->checkInfos(); + FluidbookDocumentUpload::updateProgression($uploadID, __('Génération des miniatures (:done/:pages)', ['pages' => $this->pages, 'done' => 0]), 2); + $jobs = []; + for ($i = 1; $i <= $this->pages; $i++) { + $job = new FluidbookDocumentFileProcess($this, $i, 'jpg', 'thumb'); + $job->dispatch(); + $jobs[] = $job; + } + + while (true) { + $done = 0; + foreach ($jobs as $job) { + /** @var $job FluidbookDocumentFileProcess */ + if ($job->isDone()) { + $done++; + } + } + $progress = $done / $this->pages; + FluidbookDocumentUpload::updateProgression($uploadID, __('Génération des miniatures (:done/:pages)', ['pages' => $this->pages, 'done' => $done]), 2 + $progress); + usleep(0.25 * 1000000); + if ($progress === 1) { + break; + } + } + } + public function getMobileFirstRatio() { $this->checkInfos(); @@ -52,9 +84,10 @@ class FluidbookDocument extends ToolboxModel { if (null === $this->pdf_data) { $infos = PDFTools::infos(); + $this->pages = $infos['pages']; $this->pdf_data = $infos['infos']; $this->bookmarks = $infos['bookmarks']; - $this->pagenumbers = $infos['numberSections']; + $this->pagesnumbers = $infos['numberSections']; $this->saveWithoutFlushingCache(); } } @@ -67,33 +100,43 @@ class FluidbookDocument extends ToolboxModel return rtrim(self::WS_DOCS . $this->id . ($path ? DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR) : $path), DIRECTORY_SEPARATOR); } - public function getFilesData() + public function hasFile($page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html') { - if ($this->_filesData === null) { - $limit = time() - 604800; - $f = $this->path('filesdata.json'); - if (file_exists($f) && filemtime($f) > $limit) { - $this->_filesData = json_decode(file_get_contents($f), true); - } else { - $this->_filesData = []; + $cacheKey = $this->fileCacheKey($page, $format, $resolution, $withText, $withGraphics, $version); + if (Cache::has($cacheKey)) { + return true; + } else { + $path = $this->_getPath($page, $format, $resolution, $withText, $withGraphics, $version); + $minsize = $format === 'svg' ? 100 : 1; + + if (!file_exists($path)) { + return false; + } + if (filesize($path) < $minsize) { + return false; + } + if ($format === 'svg') { + $reffile = $this->path('/html/fp' . $page . '.svg'); + if (!file_exists($reffile) || filemtime($path) < filemtime($reffile)) { + return false; + } + $t = filemtime($path); + if ($t < 1603181003 && $t > 1602662603) { + return false; + } } + Cache::put($cacheKey, $path); + return true; } - return $this->_filesData; } - public function getFile($page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html', $force = false) + protected function _getPath($page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html') { - $this->getFilesData(); - $cacheKey = md5($page . '||' . $format . '//' . $resolution . '""' . ($withText ? '1' : '0') . '---' . ($withGraphics ? '1' : '0') . '%%' . $version); - if (!isset($this->_filesData[$cacheKey]) || $force) { - $this->_filesData[$cacheKey] = $this->_getFile($page, $format, $resolution, $withText, $withGraphics, $version, $force); + $cacheKey = $this->fileCacheKey($page, $format, $resolution, $withText, $withGraphics, $version); + if (Cache::has($cacheKey)) { + return Cache::get($cacheKey); } - return $this->_filesData[$cacheKey]; - } - - public function _getFile($page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html', $force = false) - { if ($format === 'jpeg') { $format = 'jpg'; } @@ -110,7 +153,7 @@ class FluidbookDocument extends ToolboxModel } $dir = $this->path($version) . '/'; - $minsize = 1; + if ($format === 'svg') { $prefix = $withGraphics ? 'f' : 't'; $file = $dir . $prefix . 'o' . $page; @@ -119,8 +162,6 @@ class FluidbookDocument extends ToolboxModel } $file .= '.svg'; - $reffile = $this->path('/html/fp' . $page . '.svg'); - $minsize = 100; } else if ($format === 'png' || $format === 'jpg') { $prefix = $withText ? 't' : 'h'; if ($resolution === 'thumb') { @@ -132,30 +173,45 @@ class FluidbookDocument extends ToolboxModel $file = $dir . 'p' . $page . '.' . $format; } - $do = false; - if (!file_exists($file)) { - $do = true; - } else if (filesize($file) < $minsize) { - $do = true; - } else if (isset($reffile) && (!file_exists($reffile) || filemtime($file) < filemtime($reffile))) { - $do = true; - } else if ($format === 'svg') { - $t = filemtime($file); - $do = $t < 1603181003 && $t > 1602662603; - } + return $file; + } - if ($do || $force) { - return FluidbookFarm::getFile($page, $format, $resolution, $withText, $withGraphics, $version, $this->getResolutionRatio(), $this->getMobileFirstRatio(), $this->path(), $force); + protected function fileCacheKey($page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html') + { + return 'FluidbookDocument_' . $this->id . '_' . $page . '_' . $format . '_' . $resolution . '_' . ($withText ? '1' : '0') . '_' . ($withGraphics ? '1' : '0') . '_' . $version; + } + + public function getFile($page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html', $force = false) + { + if ($force) { + $this->removeFile($page, $format, $resolution, $withText, $withGraphics, $version); } - touch($file); - return $file; + $doc = $this; + return Cache::rememberForever($this->fileCacheKey($page, $format, $resolution, $withText, $withGraphics, $version), function () use ($doc, $page, $format, $resolution, $withText, $withGraphics, $version) { + return $doc->_getFile($page, $format, $resolution, $withText, $withGraphics, $version); + }); } - public function __destruct() + public function removeFile($page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html') { - if (null !== $this->_filesData) { - file_put_contents($this->path('filesdata.json'), json_encode($this->_filesData)); + $path = $this->_getPath($page, $format, $resolution, $withText, $withGraphics, $version); + if (file_exists($path)) { + unlink($path); } + Cache::forget($this->fileCacheKey($page, $format, $resolution, $withText, $withGraphics, $version)); } + + + public function _getFile($page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html') + { + if (!$this->hasFile($page, $format, $resolution, $withText, $withGraphics, $version)) { + return FluidbookFarm::getFile($page, $format, $resolution, $withText, $withGraphics, $version, $this->getResolutionRatio(), $this->getMobileFirstRatio(), $this->path(), $force); + } + + $path = $this->_getPath($page, $format, $resolution, $withText, $withGraphics, $version); + touch($path); + return $path; + } + } diff --git a/resources/quiz/style/030-quiz.sass b/resources/quiz/style/030-quiz.sass index e696f94da..c0292be1a 100644 --- a/resources/quiz/style/030-quiz.sass +++ b/resources/quiz/style/030-quiz.sass @@ -122,7 +122,7 @@ section background-color: $color-answer-back !important #badge - @include badge(220, 4px) + @include badge(220px, 4px) display: none #resultsscreen @@ -167,7 +167,7 @@ section position: absolute left: -20px top: 8px - @include badge(40, 0) + @include badge(40px, 0) font-weight: 400 @media (max-width: 640px) diff --git a/resources/views/fields/fluidbook_composition.blade.php b/resources/views/fields/fluidbook_composition.blade.php index 07c82fb48..547454ff3 100644 --- a/resources/views/fields/fluidbook_composition.blade.php +++ b/resources/views/fields/fluidbook_composition.blade.php @@ -3,7 +3,7 @@ @push('crud_fields_scripts')