]> _ Git - cubist_cms-back.git/commitdiff
wait #5284 @2
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Wed, 18 May 2022 13:24:41 +0000 (15:24 +0200)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Wed, 18 May 2022 13:24:41 +0000 (15:24 +0200)
src/app/Http/Controllers/CubistFilesorURLUpload.php [new file with mode: 0644]
src/app/Magic/Fields/FilesOrURL.php
src/app/Magic/Models/CubistMagicAbstractModel.php
src/resources/views/fields/filesorurl.blade.php [new file with mode: 0644]
src/routes/cubist/backpack/filesorurlupload.php [new file with mode: 0644]

diff --git a/src/app/Http/Controllers/CubistFilesorURLUpload.php b/src/app/Http/Controllers/CubistFilesorURLUpload.php
new file mode 100644 (file)
index 0000000..ee83a52
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+namespace Cubist\Backpack\Http\Controllers;
+
+use Cubist\Backpack\Magic\Models\CubistMagicAbstractModel;
+use Illuminate\Http\UploadedFile;
+
+class CubistFilesorURLUpload
+{
+    public function upload()
+    {
+        $res = [];
+        $className = request()->get('entity');
+        $id = request()->get('entry_id');
+        $attribute = request()->get('attribute');
+        /** @var CubistMagicAbstractModel $instance */
+        $instance = $className::find($id);
+
+        foreach (request()->allFiles() as $files) {
+            if (!is_array($files)) {
+                $files = [$files];
+            }
+            foreach ($files as $file) {
+                /** @var $file UploadedFile */
+                $res[] = $instance->uploadFreeFile($file, $attribute);
+            }
+        }
+        return response()->json($res);
+    }
+}
index b5dacf35c3167b0e5e1bcf4569c13924e154553f..1899d8277e064903e66281ea2b48925894d0342a 100644 (file)
@@ -2,7 +2,34 @@
 
 namespace Cubist\Backpack\Magic\Fields;
 
+use Cubist\Backpack\CubistBackpackServiceProvider;
+
 class FilesOrURL extends Field
 {
+    protected $_adminType = 'filesorurl';
+    protected $_viewNamespace = CubistBackpackServiceProvider::NAMESPACE . '::fields';
+    protected $_destination = '';
+
+    public function getDefaultAttributes()
+    {
+        return array_merge(parent::getDefaultAttributes(), ['destination' => $this->_destination]);
+    }
+
+    protected function _postSetAttributes()
+    {
+        parent::_postSetAttributes();
+        $accept = $this->getAttribute('accept', null);
+        if ($accept !== null) {
+            $this->setAttribute('accept', $this->_normalizeAccept($accept));
+        }
+    }
 
+    protected function _normalizeAccept($accept)
+    {
+        if (is_array($accept)) {
+            $accept = implode(', ', $accept);
+        }
+        $accept = str_replace('*.', '.', $accept);
+        return $accept;
+    }
 }
index f6adedae4dfe3edca1a2f47e450c744944f1b565..be2b1be2672234c21128f6511b5ef01fc8b265f1 100644 (file)
@@ -8,6 +8,7 @@ use Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation;
 use Cubist\Backpack\Magic\Fields\Composed;
 use Cubist\Backpack\Magic\Fields\Datetime;
 use Cubist\Backpack\Magic\Fields\Files;
+use Cubist\Backpack\Magic\Fields\FilesOrURL;
 use Cubist\Backpack\Magic\Operations\CreateOperation;
 use Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
 use Cubist\Backpack\Magic\Operations\UpdateOperation;
@@ -29,6 +30,7 @@ use Doctrine\DBAL\Schema\Schema;
 use Doctrine\DBAL\Schema\Table;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Http\UploadedFile;
 use Illuminate\Support\Arr;
 use Illuminate\Support\Carbon;
 use Illuminate\Support\Facades\Cache;
@@ -1174,6 +1176,40 @@ class CubistMagicAbstractModel extends Model implements HasMedia
         return $saved;
     }
 
+    /**
+     * @param $uploadedFile UploadedFile
+     * @param $attribute string
+     * @return string
+     * @throws \Exception
+     */
+    public function uploadFreeFile($uploadedFile, $attribute)
+    {
+        $field = $this->getField($attribute);
+        if (!$field instanceof FilesOrURL) {
+            throw new \Exception('Field must be FilesOrURL');
+        }
+        $baseDirectory = $this->_getFreeFileBaseDirectory();
+        if (null === $baseDirectory) {
+            throw new \Exception('Base directory must be set');
+        }
+        $dir = \Cubist\Util\Files\Files::mkdir($baseDirectory . '/' . $field->getAttribute('destination', ''));
+        $name = $uploadedFile->getClientOriginalName();
+        $e = explode('.', $name);
+        $ext = array_pop($e);
+        $name = implode('.', $e);
+        $name = Str::slug($name) . '.' . $ext;
+        $uploadedFile->move($dir, $name);
+        return $name;
+    }
+
+    /**
+     * @return string
+     */
+    protected function _getFreeFileBaseDirectory()
+    {
+        return null;
+    }
+
     public function saveWithoutFlushingCache($options = [])
     {
         $this->_flushCacheOnSave = false;
diff --git a/src/resources/views/fields/filesorurl.blade.php b/src/resources/views/fields/filesorurl.blade.php
new file mode 100644 (file)
index 0000000..692cfbc
--- /dev/null
@@ -0,0 +1,193 @@
+@php
+    $field['wrapper'] = $field['wrapper'] ?? $field['wrapperAttributes'] ?? [];
+    $field['wrapper']['data-init-function'] = $field['wrapper']['data-init-function'] ?? 'bpFieldInitUploadElement';
+    $field['wrapper']['data-field-name'] = $field['wrapper']['data-field-name'] ?? $field['name'];
+
+    $form_id='filesorurl_'.uniqid();
+@endphp
+
+    <!-- text input -->
+@include('crud::fields.inc.wrapper_start')
+<label>{!! $field['label'] !!}</label>
+@include('crud::fields.inc.translatable_icon')
+
+@push('before_scripts')
+    <form id="{{$form_id}}" class="filesorurlupload" action="{{backpack_url('filesorurlupload')}}" method="post"
+          enctype="multipart/form-data">
+        <input type="hidden" name="entity" value="{{ get_class($entry)}}">
+        <input type="hidden" name="entry_id" value="{{ $entry->id}}">
+        <input type="hidden" name="attribute" value="{{$field['name']}}">
+    </form>
+@endpush
+
+{{-- Show the file picker on CREATE form. --}}
+<div class="freefile-file">
+    <input type="file" multiple name="upload[]"
+           @if(isset($field['accept']) && $field['accept'])
+               accept="{{$field['accept']}}"
+           @endif
+           class="freefile-file-input" form="{{$form_id}}">
+    <input type="text" name="{{ $field['name'] }}"
+           value="{{ old(square_brackets_to_dots($field['name'])) ?? $field['value'] ?? $field['default'] ?? '' }}"
+        @include('crud::fields.inc.attributes', ['default_class' =>  'form-control freefile-text-input'])
+    >
+    <label class="freefile-file-label" for="customFile"></label>
+</div>
+
+{{-- HINT --}}
+@if (isset($field['hint']))
+    <p class="help-block">{!! $field['hint'] !!}</p>
+@endif
+@include('crud::fields.inc.wrapper_end')
+
+
+{{-- ########################################## --}}
+{{-- Extra CSS and JS for this particular field --}}
+{{-- If a field type is shown multiple times on a form, the CSS and JS will only be loaded once --}}
+@if ($crud->fieldTypeNotLoaded($field))
+    @php
+        $crud->markFieldTypeAsLoaded($field);
+    @endphp
+
+    @push('crud_fields_styles')
+        <style type="text/css">
+
+            .freefile-file {
+                position: relative;
+                display: inline-block;
+                width: 100%;
+                height: calc(1.5em + 0.75rem + 2px);
+                margin-bottom: 0;
+            }
+
+            .freefile-file.loading .freefile-file-input {
+                display: none;
+            }
+
+            .freefile-file.loading .freefile-file-input:lang(en) ~ .freefile-file-label::after {
+                content: "Loading";
+            }
+
+            .freefile-file.loading .freefile-file-input:lang(fr) ~ .freefile-file-label::after {
+                content: "Chargement";
+            }
+
+            .freefile-file-input {
+                position: absolute;
+                z-index: 3;
+                width: 15%;
+                height: calc(1.5em + 0.75rem + 2px);
+                margin: 0;
+                opacity: 0;
+                cursor: pointer;
+                right: 0;
+            }
+
+            .freefile-text-input {
+                position: absolute;
+                z-index: 2;
+                height: calc(1.5em + 0.75rem + 2px);
+                margin: 0;
+                left: 0;
+                width: 85%;
+                border-color: transparent;
+                background-color: transparent;
+            }
+
+            .freefile-text-input:focus {
+                background-color: transparent;
+                border-color: transparent;
+            }
+
+            .freefile-text-input:lang(en) {
+                width: calc(100% - 74px);
+            }
+
+            .freefile-text-input:lang(fr) {
+                width: calc(100% - 87px);
+            }
+
+            .freefile-file-input:lang(en) {
+                width: 74px;
+            }
+
+            .freefile-file-input:lang(fr) {
+                width: 87px;
+            }
+
+            .freefile-text-input:focus ~ .freefile-file-label {
+                border-color: #2f66b3;
+                box-shadow: 0 0 0 0rem rgba(70, 127, 208, 0.25);
+            }
+
+            .freefile-text-input:disabled ~ .freefile-file-label {
+                background-color: #e4e7ea;
+            }
+
+            .freefile-file-input:lang(en) ~ .freefile-file-label::after {
+                content: "Browse";
+            }
+
+            .freefile-file-input:lang(fr) ~ .freefile-file-label::after {
+                content: "Parcourir";
+            }
+
+            .freefile-file-input ~ .freefile-file-label[data-browse]::after {
+                content: attr(data-browse);
+            }
+
+            .freefile-file-label {
+                position: absolute;
+                top: 0;
+                right: 0;
+                left: 0;
+                z-index: 1;
+                height: calc(1.5em + 0.75rem + 2px);
+                padding: 0.375rem 0.75rem;
+                font-weight: 400;
+                line-height: 1.5;
+                color: #5c6873;
+                background-color: #fff;
+                border: 1px solid #e4e7ea;
+                border-radius: 0.25rem;
+                font-weight: 400 !important;
+            }
+
+            .freefile-file-label::after {
+                position: absolute;
+                top: 0;
+                right: 0;
+                bottom: 0;
+                z-index: 3;
+                display: block;
+                height: calc(1.5em + 0.75rem);
+                padding: 0.375rem 0.75rem;
+                line-height: 1.5;
+                color: #5c6873;
+                content: "Browse";
+                background-color: #f0f3f9;
+                border-left: inherit;
+                border-radius: 0 0.25rem 0.25rem 0;
+            }
+        </style>
+    @endpush
+
+    @push('crud_fields_scripts')
+        <script>
+            jQuery(document).ready(function ($) {
+
+                $(document).on('change', '.freefile-file-input', function () {
+                    var parent = $(this).closest('.freefile-file');
+                    $(parent).addClass('loading');
+                    var form = $("#" + $(this).attr('form'));
+                    var f = $(form).ajaxSubmit({dataType: 'json'});
+                    var xhr = f.data('jqxhr');
+                    xhr.done(function (data) {
+                        $(parent).find('.freefile-text-input').val(data[0]);
+                        $(parent).removeClass('loading');
+                    });
+                });
+            });
+        </script>
+    @endpush
+@endif
diff --git a/src/routes/cubist/backpack/filesorurlupload.php b/src/routes/cubist/backpack/filesorurlupload.php
new file mode 100644 (file)
index 0000000..93663e3
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+
+Route::group([
+    'prefix' => config('backpack.base.route_prefix', 'admin'),
+    'middleware' => ['web', config('backpack.base.middleware_key', 'admin')],
+], function () { // custom admin routes
+    Route::post('filesorurlupload', '\Cubist\Backpack\Http\Controllers\CubistFilesorURLUpload@upload');
+});