diff --git a/composer.json b/composer.json index cb43d65..e99b2d1 100644 --- a/composer.json +++ b/composer.json @@ -12,13 +12,13 @@ "homepage": "https://github.com/laravel-backpack/filemanager", "keywords": ["Laravel", "FileManager"], "require": { - "backpack/crud": "^6.0", + "backpack/crud": "^7.0.0-beta", "barryvdh/laravel-elfinder": "^0.5.2" }, "require-dev": { - "phpunit/phpunit": "^10.0", + "phpunit/phpunit": "^10.0|^11.0", "mockery/mockery": "^1.5", - "orchestra/testbench": "^8" + "orchestra/testbench": "^8|^9|^10|^11" }, "autoload": { "psr-4": { diff --git a/readme.md b/readme.md index 1ae23f1..ae032ad 100644 --- a/readme.md +++ b/readme.md @@ -34,17 +34,25 @@ That's it. Hit refresh in your admin panel, and you'll find a new sidebar item p You can use elFinder in Backpack: - stand-alone, by accessing the ```/admin/elfinder``` route (see screenshot above); -- inside the [```browse```](https://backpackforlaravel.com/docs/4.1/crud-fields#browse), [```browse_multiple```](https://backpackforlaravel.com/docs/4.1/crud-fields#browse_multiple) or [```ckeditor```](https://backpackforlaravel.com/docs/4.1/crud-fields#ckeditor) field types; +- inside the [```browse```](https://backpackforlaravel.com/docs/4.1/crud-fields#browse), [```browse_multiple```](https://backpackforlaravel.com/docs/4.1/crud-fields#browse_multiple); + +## Customization + +You can publish the views to your `resources/views/vendor/backpack/filemanager` folder by running: + +```bash +php vendor:publish --provider="Backpack\FileManager\FileManagerServiceProvider" --tag="elfinder-views" +php vendor:publish --provider="Backpack\FileManager\FileManagerServiceProvider" --tag="elfinder-fields" +php vendor:publish --provider="Backpack\FileManager\FileManagerServiceProvider" --tag="elfinder-columns" + +``` ## Upgrade -To upgrade from v2 to v3 of this package: +To upgrade from v3 to v4 of this package: ```bash # remove the published blade views rm -rf resources/views/vendor/elfinder - -# publish the new blade views -php artisan backpack:filemanager:install ``` ## Security diff --git a/resources/assets/css/elfinder.backpack.theme.css b/resources/assets/css/elfinder.backpack.theme.css deleted file mode 100644 index 10c1fee..0000000 --- a/resources/assets/css/elfinder.backpack.theme.css +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Laravel Backpack theme for elFinder. - * Required jquery ui "smoothness" theme. - * - * @author Cristian Tabacitu [hello@tabacitu.ro] - **/ - -body.elfinder { margin:0; } -body #elfinder.ui-widget-content { - border: 1px solid #cccccc; - background: #ffffff; - color: #23282c; - border-radius: 3px!important; -} - -.elfinder-cwd-icon:before { - background: #ccc; -} - -#elfinder .ui-state-default, -#elfinder .ui-widget-content .ui-state-default, -#elfinder .ui-widget-header .ui-state-default { - background: #e6e6e6; -} - -.elfinder-contextmenu .ui-state-hover { - color: black!important; -} - -.elfinder-cwd-file.ui-state-hover, -.elfinder-cwd-file.ui-widget-content .ui-state-hover, -.elfinder-cwd-file.ui-widget-header .ui-state-hover, -.elfinder-cwd-file.ui-state-focus, -.elfinder-cwd-file.ui-widget-content .ui-state-focus, -.elfinder-cwd-file.ui-widget-header .ui-state-focus { - background: transparent!important; - /*border: 1px solid #ccc;*/ -} - -.elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover, -.elfinder-cwd table td.ui-state-hover, -.elfinder-button-menu .ui-state-hover { - /*color: black!important;*/ - /*font-weight: bold;*/ -} - -.elfinder .elfinder-contextmenu, .elfinder .elfinder-contextmenu-sub { - border: 1px solid #ccc!important; -} - -/* input textarea */ -.elfinder input, -.elfinder textarea { - color: #000; - background-color: #FFF; -} - -/* dialogs */ -.std42-dialog, .std42-dialog .ui-widget-content { background-color:#ededed; background-image:none; background-clip: content-box; } - -/* navbar */ -.elfinder .elfinder-navbar { background:#dde4eb; } -.elfinder-navbar .ui-state-hover { color:#000; background-color:#edf1f4; border-color:#bdcbd8; } -.elfinder-navbar-root.ui-state-active.ui-state-hover { color:white; background: #3875d7!important; } -.elfinder-navbar .ui-state-active { background: #3875d7; border-color:#3875d7; color:#fff; } -.elfinder-navbar .elfinder-droppable-active {background:#A7C6E5 !important;} -/* disabled elfinder */ -.elfinder-disabled .elfinder-navbar .ui-state-active { background: #dadada; border-color:#aaa; color:#fff; } - - -/* current directory */ -/* selected file in "icons" view */ -.elfinder-cwd-view-icons .elfinder-cwd-file .ui-state-hover { background:#ccc; } - -/* list view*/ -.elfinder-cwd table thead td.ui-state-hover { background:#ddd; } -.elfinder-cwd table tr:nth-child(odd) { background-color:#edf3fe; } -.elfinder-cwd table tr { - border: 1px solid transparent; - border-top:1px solid #fff; -} -.elfinder-cwd .elfinder-droppable-active td { background:#A7C6E5 !important; } - - -/* common selected background/color */ -.elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover, -.elfinder-cwd table td.ui-state-hover, -.elfinder-button-menu .ui-state-hover { background: #3875d7; color:#fff;} -/* disabled elfinder */ -.elfinder-disabled .elfinder-cwd-view-icons .elfinder-cwd-file .elfinder-cwd-filename.ui-state-hover, -.elfinder-disabled .elfinder-cwd table td.ui-state-hover { background:#dadada;} - -/* statusbar */ -.elfinder .elfinder-statusbar { color:#555; } -.elfinder .elfinder-statusbar a { text-decoration:none; color:#555;} - - -.std42-dialog .elfinder-help, .std42-dialog .elfinder-help .ui-widget-content { background:#fff;} - -/* contextmenu */ -.elfinder-contextmenu .ui-state-hover { background: #3875d7; color:#fff; } -/* .elfinder-contextmenu .ui-state-hover .elfinder-contextmenu-arrow { background-image:url('../img/arrows-active.png'); } */ - -/* jquery-ui overwrites */ -.ui-widget-header { - background: #cccccc; - border: none; -} - -.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { - border-bottom-right-radius: 0; -} -.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { - border-bottom-left-radius: 0; -} -.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { - border-top-right-radius: 0; -} -.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { - border-top-left-radius: 0; -} -.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { - background: #dadada; -} -.elfinder-navbar-root .ui-state-hover { - background: #3875d7!important; -} \ No newline at end of file diff --git a/resources/views/ckeditor4.blade.php b/resources/views/ckeditor4.blade.php deleted file mode 100644 index 0e47561..0000000 --- a/resources/views/ckeditor4.blade.php +++ /dev/null @@ -1,67 +0,0 @@ - - - - - @include('vendor.elfinder.common_scripts') - @include('vendor.elfinder.common_styles') - - - - - - - -
- - - diff --git a/resources/views/ckeditor4.php b/resources/views/ckeditor4.php deleted file mode 100644 index 5191c12..0000000 --- a/resources/views/ckeditor4.php +++ /dev/null @@ -1,83 +0,0 @@ - - - - - elFinder 2.0 - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/resources/views/columns/browse.blade.php b/resources/views/columns/browse.blade.php new file mode 100644 index 0000000..13fde85 --- /dev/null +++ b/resources/views/columns/browse.blade.php @@ -0,0 +1,4 @@ +@php + $column['disk'] = $column['disk'] ?? null; +@endphp +@include('crud::columns.upload') \ No newline at end of file diff --git a/resources/views/columns/browse_multiple.blade.php b/resources/views/columns/browse_multiple.blade.php new file mode 100644 index 0000000..95e1528 --- /dev/null +++ b/resources/views/columns/browse_multiple.blade.php @@ -0,0 +1,4 @@ +@php + $column['disk'] = $column['disk'] ?? null; +@endphp +@include('crud::columns.upload_multiple') \ No newline at end of file diff --git a/resources/views/common_scripts.blade.php b/resources/views/common_scripts.blade.php index 650218f..4fd8fa2 100644 --- a/resources/views/common_scripts.blade.php +++ b/resources/views/common_scripts.blade.php @@ -1,21 +1,27 @@ - {{-- jQuery (REQUIRED) --}} - @if (!isset ($jquery) || (isset($jquery) && $jquery == true)) - @basset('https://unpkg.com/jquery@3.6.1/dist/jquery.min.js') - @endif +{{-- jQuery (REQUIRED) --}} +@if (!isset ($jquery) || (isset($jquery) && $jquery == true)) + @basset('https://cdn.jsdelivr.net/npm/jquery@3.6.1/dist/jquery.min.js', true, [ + 'integrity' => 'sha384-i61gTtaoovXtAbKjo903+O55Jkn2+RtzHtvNez+yI49HAASvznhe9sZyjaSHTau9', + 'crossorigin' => 'anonymous' + ]) +@endif - {{-- jQuery UI and Smoothness theme --}} - @bassetArchive('https://github.com/jquery/jquery-ui/archive/refs/tags/1.13.2.tar.gz', 'jquery-ui-1.13.2') - @basset('jquery-ui-1.13.2/jquery-ui-1.13.2/dist/themes/smoothness/jquery-ui.min.css') - @basset('jquery-ui-1.13.2/jquery-ui-1.13.2/dist/jquery-ui.min.js') +{{-- jQuery UI and Smoothness theme --}} +@basset('https://raw.githubusercontent.com/jquery/jquery-ui/refs/tags/1.13.2/dist/jquery-ui.min.js', true, [ + 'integrity' => 'sha384-4D3G3GikQs6hLlLZGdz5wLFzuqE9v4yVGAcOH86y23JqBDPzj9viv0EqyfIa6YUL', + 'crossorigin' => 'anonymous' +]) - {{-- elFinder JS (REQUIRED) --}} - @bassetArchive('https://github.com/Studio-42/elFinder/archive/refs/tags/2.1.64.tar.gz', 'elfinder-2.1.64') - @basset('elfinder-2.1.64/elFinder-2.1.64/js/elfinder.min.js') +{{-- elFinder JS (REQUIRED) --}} +@basset('https://raw.githubusercontent.com/Studio-42/elFinder/refs/tags/2.1.64/js/elfinder.min.js', true, [ + 'integrity' => 'sha384-Ow1wKIUQLS9bOa23gn7yT91nyowDhk2zK1lO7G5Hnxlh3bvTPNH7c5uODf7/jIec', + 'crossorigin' => 'anonymous' +]) - {{-- elFinder translation (OPTIONAL) --}} - @if($locale) - @basset('https://cdnjs.cloudflare.com/ajax/libs/elfinder/2.1.64/js/i18n/elfinder.'.$locale.'.min.js') - @endif +{{-- elFinder translation (OPTIONAL) --}} +@if($locale) + @basset('bp-elfinder-i18n-'.$locale) +@endif - {{-- elFinder sounds --}} - @basset(base_path('vendor/studio-42/elfinder/sounds/rm.wav')) +{{-- elFinder sounds --}} +@basset(base_path('vendor/studio-42/elfinder/sounds/rm.wav')) diff --git a/resources/views/common_styles.blade.php b/resources/views/common_styles.blade.php index cabe921..fb0e5cc 100644 --- a/resources/views/common_styles.blade.php +++ b/resources/views/common_styles.blade.php @@ -1,28 +1,32 @@ File Manager {{-- elFinder CSS (REQUIRED) --}} -@php - $themeStylesheetVersion = '3.0.0'; -@endphp -@bassetArchive('https://github.com/Studio-42/elFinder/archive/refs/tags/2.1.64.tar.gz', 'elfinder-2.1.64') -@basset('elfinder-2.1.64/elFinder-2.1.64/css/elfinder.min.css') -@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@'.$themeStylesheetVersion.'/Material/css/theme.min.css') -@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@'.$themeStylesheetVersion.'/Material/images/loading.svg', false) -@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@'.$themeStylesheetVersion.'/Material/font/material.eot', false) -@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@'.$themeStylesheetVersion.'/Material/font/material.svg', false) -@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@'.$themeStylesheetVersion.'/Material/images/icons-big.svg', false) -@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@'.$themeStylesheetVersion.'/Material/images/icons-small.svg', false) -@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@'.$themeStylesheetVersion.'/Material/font/material.woff', false) -@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@'.$themeStylesheetVersion.'/Material/font/material.ttf', false) -@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@'.$themeStylesheetVersion.'/Material/font/material.woff2', false) - +@basset('https://raw.githubusercontent.com/Studio-42/elFinder/refs/tags/2.1.64/img/icons-big.svg', false, [ + 'integrity' => 'sha384-BWeb84E4ly6GgjPMWRpJNB+I8XpW+xqF9kezQR6PNqXP0pmjHi8iqlGZs0JRgHlu', + 'crossorigin' => 'anonymous' +]) +@basset('https://raw.githubusercontent.com/Studio-42/elFinder/refs/tags/2.1.64/img/logo.png', false, [ + 'integrity' => 'sha384-mAtths5Wl6rU0MrgaCz2bJRTIG8LhA1pLZ4ZX+Qo9fQRjlKFxb5eLWUO3pZ7Aioq', + 'crossorigin' => 'anonymous' +]) +@basset('https://raw.githubusercontent.com/Studio-42/elFinder/refs/tags/2.1.64/css/elfinder.min.css', true, [ + 'integrity' => 'sha384-O+x3Lv203m3W8SILSSf8xt2ryvN+CEx3s9tpGloi3D6UQ+1BkbXPuSxEj7uhKKCs', + 'crossorigin' => 'anonymous' +]) +@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@3.0.0/Material/css/theme.min.css') +@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@3.0.0/Material/images/loading.svg', false) +@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@3.0.0/Material/font/material.eot', false) +@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@3.0.0/Material/font/material.svg', false) +@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@3.0.0/Material/images/icons-big.svg', false) +@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@3.0.0/Material/images/icons-small.svg', false) +@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@3.0.0/Material/font/material.woff', false) +@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@3.0.0/Material/font/material.ttf', false) +@basset('https://cdn.jsdelivr.net/gh/RobiNN1/elFinder-Material-Theme@3.0.0/Material/font/material.woff2', false) @bassetBlock('elfinderThemeSwitcherScript.js') - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/resources/views/fields/browse.blade.php b/resources/views/fields/browse.blade.php new file mode 100644 index 0000000..2ecfba8 --- /dev/null +++ b/resources/views/fields/browse.blade.php @@ -0,0 +1,119 @@ +{{-- browse server input --}} +@php +$field['attributes']['data-elfinder-trigger-url'] = $field['attributes']['data-elfinder-trigger-url'] ?? url(config('elfinder.route.prefix').'/popup/'.$field['name']); +$field['attributes']['data-elfinder-trigger-url'] .= '?mimes='.urlencode(Crypt::encrypt($field['mime_types'] ?? '')); +@endphp +@include('crud::fields.inc.wrapper_start') + + @include('crud::fields.inc.translatable_icon') +
+ + + + +
+ @if (isset($field['hint'])) +

{!! $field['hint'] !!}

+ @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 --}} + + {{-- FIELD CSS - will be loaded in the after_styles section --}} + @push('crud_fields_styles') + {{-- include browse server css --}} + @basset('https://cdn.jsdelivr.net/npm/jquery-colorbox@1.6.4/example2/colorbox.css', true, [ + 'integrity' => 'sha384-HmslgkPwGM5TYgFgpe7Hz++h4HkDNZij42ObIXoXK771r/rs+kicv69E2lj0WIRq', + 'crossorigin' => 'anonymous' + ]) + @basset('https://cdn.jsdelivr.net/npm/jquery-colorbox@1.6.4/example2/images/loading.gif', false, [ + 'integrity' => 'sha256-ZG7zstGXrrtjO6k6MkhemyiZVml/jgZY1LZCwarlmX0=', + 'crossorigin' => 'anonymous' + ]) + @basset('https://cdn.jsdelivr.net/npm/jquery-colorbox@1.6.4/example2/images/controls.png', false, [ + 'integrity' => 'sha256-zTLuvjLgmphUaxZ/5gsLHyPz70A2wKH914uvqdG2xl0=', + 'crossorigin' => 'anonymous' + ]) + @bassetBlock('backpack/pro/fields/browse-field.css') + + @endBassetBlock + @endpush + + @push('crud_fields_scripts') + {{-- include browse server js --}} + @basset('https://cdn.jsdelivr.net/npm/jquery-colorbox@1.6.4/jquery.colorbox.min.js', true, [ + 'integrity' => 'sha384-nRGTVvv4Qn110QBA9rXeSIVNgDwYTg+ZqPaUquO44OQaVASFOVFo5beRb62KFOu/', + 'crossorigin' => 'anonymous' + ]) + @bassetBlock('backpack/pro/fields/browse-field.js') + + @endBassetBlock + @endpush + +{{-- End of Extra CSS and JS --}} +{{-- ########################################## --}} diff --git a/resources/views/fields/browse_multiple.blade.php b/resources/views/fields/browse_multiple.blade.php new file mode 100644 index 0000000..634d7e3 --- /dev/null +++ b/resources/views/fields/browse_multiple.blade.php @@ -0,0 +1,238 @@ +@php +$multiple = Arr::get($field, 'multiple', true); +$sortable = Arr::get($field, 'sortable', false); +$value = old_empty_or_null($field['name'], '') ?? $field['value'] ?? $field['default'] ?? ''; + +if (!$multiple && is_array($value)) { + $value = Arr::first($value); +} + +$field['wrapper'] = $field['wrapper'] ?? $field['wrapperAttributes'] ?? []; +$field['wrapper']['data-init-function'] = $field['wrapper']['data-init-function'] ?? 'bpFieldInitBrowseMultipleElement'; +$field['wrapper']['data-elfinder-trigger-url'] = $field['wrapper']['data-elfinder-trigger-url'] ?? url(config('elfinder.route.prefix').'/popup/'.$field['name'].'?multiple=1'); + +$field['wrapper']['data-elfinder-trigger-url'] .= '&mimes='.urlencode(Crypt::encrypt($field['mime_types'] ?? '')); + +if ($multiple) { + $field['wrapper']['data-multiple'] = "true"; +} else { + $field['wrapper']['data-multiple'] = "false"; +} + +if($sortable){ + $field['wrapper']['sortable'] = "true"; +} + +// make the field work either with casted attributes or plain json strings +$value = is_string($value) && $multiple ? json_decode($value) : $value; + +@endphp + +@include('crud::fields.inc.wrapper_start') + + + @include('crud::fields.inc.translatable_icon') +
+ @if ($multiple) + + @else + + @endif +
+
+ + +
+ + @if (isset($field['hint'])) +

{!! $field['hint'] !!}

+ @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 + + {{-- FIELD CSS - will be loaded in the after_styles section --}} + @push('crud_fields_styles') + @basset('https://cdn.jsdelivr.net/npm/jquery-colorbox@1.6.4/example2/colorbox.css', true, [ + 'integrity' => 'sha384-HmslgkPwGM5TYgFgpe7Hz++h4HkDNZij42ObIXoXK771r/rs+kicv69E2lj0WIRq', + 'crossorigin' => 'anonymous' + ]) + @bassetBlock('backpack/pro/fields/browse-multiple-field.css') + + @endBassetBlock + @endpush + + @push('crud_fields_scripts') + + @basset('https://cdn.jsdelivr.net/npm/jquery-colorbox@1.6.4/jquery.colorbox.min.js', true, [ + 'integrity' => 'sha384-nRGTVvv4Qn110QBA9rXeSIVNgDwYTg+ZqPaUquO44OQaVASFOVFo5beRb62KFOu/', + 'crossorigin' => 'anonymous' + ]) + @basset('https://raw.githubusercontent.com/jquery/jquery-ui/refs/tags/1.13.2/dist/jquery-ui.min.js', true, [ + 'integrity' => 'sha384-4D3G3GikQs6hLlLZGdz5wLFzuqE9v4yVGAcOH86y23JqBDPzj9viv0EqyfIa6YUL', + 'crossorigin' => 'anonymous' + ]) + @bassetBlock('backpack/pro/fields/browse-multiple-field.js') + + @endBassetBlock + @endpush +@endif + +{{-- End of Extra CSS and JS --}} +{{-- ########################################## --}} diff --git a/resources/views/filepicker.blade.php b/resources/views/filepicker.blade.php deleted file mode 100644 index d8a1698..0000000 --- a/resources/views/filepicker.blade.php +++ /dev/null @@ -1,88 +0,0 @@ - - - - - @include('vendor.elfinder.common_scripts') - @include('vendor.elfinder.common_styles') - - - - - - -
- - - diff --git a/resources/views/filepicker.php b/resources/views/filepicker.php deleted file mode 100644 index bf0dda0..0000000 --- a/resources/views/filepicker.php +++ /dev/null @@ -1,106 +0,0 @@ - - - - - elFinder 2.0 - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - diff --git a/resources/views/standalonepopup.blade.php b/resources/views/standalonepopup.blade.php index 37f3af4..fd1de79 100644 --- a/resources/views/standalonepopup.blade.php +++ b/resources/views/standalonepopup.blade.php @@ -2,8 +2,8 @@ - @include('vendor.elfinder.common_scripts') - @include('vendor.elfinder.common_styles', ['styleBodyElement' => true]) + @include('backpack.filemanager::common_scripts') + @include('backpack.filemanager::common_styles', ['styleBodyElement' => true])