]> _ Git - fluidbook-toolbox.git/commitdiff
wait #5370 @0.25
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Thu, 21 Jul 2022 12:18:24 +0000 (14:18 +0200)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Thu, 21 Jul 2022 12:18:24 +0000 (14:18 +0200)
app/Http/Controllers/Admin/Operations/FluidbookPublication/CompositionOperation.php
app/Jobs/FluidbookDocumentFileProcess.php [new file with mode: 0644]
app/Jobs/FluidbookDocumentUpload.php [new file with mode: 0644]
app/Models/FluidbookDocument.php
resources/quiz/style/030-quiz.sass
resources/views/fields/fluidbook_composition.blade.php

index 27706990a2917ac204f4735bccff0178e31554e7..12751452458f59a5efe36cb2678b2f722be5655f 100644 (file)
@@ -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 (file)
index 0000000..970032b
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Models\FluidbookDocument;
+
+class FluidbookDocumentFileProcess extends Base
+{
+    /** @var FluidbookDocument */
+    protected $document;
+    protected $page;
+    protected $format;
+    protected $resolution;
+    protected $withText;
+    protected $withGraphics;
+    protected $version;
+    protected $force;
+
+    public function __construct($document, $page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html', $force = false)
+    {
+        $this->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 (file)
index 0000000..13ea82c
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Models\FluidbookDocument;
+use App\Models\User;
+use Illuminate\Support\Facades\Cache;
+
+class FluidbookDocumentUpload extends Base
+{
+    protected $uploadID;
+
+    /**
+     * @var FluidbookDocument
+     */
+    protected $document;
+
+
+
+    /**
+     * @var User
+     */
+    protected $user;
+
+    public function __construct($uploadID, FluidbookDocument $document, $user)
+    {
+        $this->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];
+    }
+}
index 70b1d0a6e959827137eee754c95d14e7f07b4665..08ad55933b625ead1f1244cffb001ae3fdd4c145 100644 (file)
@@ -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;
+    }
+
 }
index e696f94da820571ba12d28dd2cda7ea1e942b925..c0292be1a45de2172e3984c1ab80601414846e29 100644 (file)
@@ -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)
index 07c82fb48237bd2e045dcf0788802936092ac202..547454ff36af5ecfb0cb5390275092b386830323 100644 (file)
@@ -3,7 +3,7 @@
     @push('crud_fields_scripts')
         <script>
             $(function () {
-                var conversion = 0;
+                var conversion = '';
                 var conversionOperation;
                 var conversionPages;
 
                         $("#compositionUploadForm").submit();
                     });
                     $(document).on('submit', '#compositionUploadForm', function () {
-                        $(form).ajaxSubmit({
-                            success: function (data) {
-                                var bm = $('[data-bunch-name="{{$field['name']}}"]').data('bunchmultiple');
-                                bm.replaceData(data[0].data);
+                        $(this).ajaxSubmit({
+                            complete: function (data) {
+                                console.log(data);
+                            },
+                            uploadProgress: function (event, position, total, percentComplete) {
+                                console.log(percentComplete);
+                            },
+                            error: function (data) {
+                                new Noty({
+                                    type: 'error',
+                                    text: '{{__('Une erreur s\'est produite lors du chargement du document')}}',
+                                }).show();
+                                conversion = '';
                             }
                         });
                         return false;
                 }
 
                 function compositionBrowse(operation, pages) {
-                    if (conversion > 0) {
-                        Noty.warn('{{__("Un document est déjà en cours d'ajout")}}');
+                    if (conversion !== '') {
+                        new Noty({
+                            type: 'warning',
+                            text: '{{__("Un document est déjà en cours d'ajout")}}',
+                        }).show();
                         return;
                     }
                     conversionOperation = operation;
                     conversionPages = pages;
 
                     $("#compositionUploadForm").remove();
-                    var form = $('<form id="compositionUploadForm" action="{{backpack_url('publications/uploaddocument')}}" enctype="multipart/form-data" method="post">' +
+                    var form = $('<form id="compositionUploadForm" action="{{backpack_url($entry->getOption('name').'/uploaddocument')}}" enctype="multipart/form-data" method="post">' +
                         '<input type="file" id="compositionUploadBrowse" name="file" value="" accept=".pdf" />' +
                         '<input type="hidden" name="_token" value="{{csrf_token()}}" />' +
                         '</form>');
                                 compositionBrowse('before', opt.$trigger[0].index() + 1);
                             }
                         },
+                        replacePage: {
+                            name: "{{__('Remplacer cette page')}}",
+                            callback: function (key, opt) {
+                                compositionBrowse('replace', [opt.$trigger[0].index() + 1]);
+                            }
+                        },
                         sep3: "---------",
                         nonum: {
                             name: "{{__('Pas de numérotation à partir de cette page')}}",
             .context-menu-item.context-menu-hover {
                 background-color: #467fcf;
             }
-            #composition_uploader{
+
+            #composition_uploader {
                 position: relative;
-                top:-10px;
-                left:12px;
+                top: -10px;
+                left: 12px;
             }
         </style>