laravel-6 support

This commit is contained in:
RafficMohammed
2023-01-08 01:17:22 +05:30
parent 1a5c16ae4b
commit 774eed8b0e
4962 changed files with 279380 additions and 297961 deletions

View File

@@ -1,7 +1,11 @@
CKEditor Package
=====================
p.s. Instead of using this package, I recommend just follow [the official CKEditor installation instructions with package managers](http://docs.ckeditor.com/#!/guide/dev_package_managers)
## Note
**This is NOT the official CKEDITOR package.**
[CKEDITOR officially has its own composer package since 2014](https://ckeditor.com/blog/CKEditor-Supports-Bower-and-Composer/). Instead of using this package, we recommend you follow [the official CKEditor installation instructions with package managers](https://docs.ckeditor.com/ckeditor4/latest/guide/dev_package_managers.html#composer)
## Installation
### Set up package
@@ -12,7 +16,9 @@ composer require unisharp/laravel-ckeditor
### Add ServiceProvider
Edit config/app.php, add the following file to `Application Service Providers` section.
For Laravel 5.5+ you can skip this step.
For Laravel 5.4 and earlier edit config/app.php, add the following file to `Application Service Providers` section.
```
Unisharp\Ckeditor\ServiceProvider::class,
```

View File

@@ -27,7 +27,14 @@
}
},
"require": {
"illuminate/support": "~5.0"
"illuminate/support": "~5.0|^6.0"
},
"minimum-stability": "dev"
"minimum-stability": "dev",
"extra": {
"laravel": {
"providers": [
"Unisharp\\Ckeditor\\ServiceProvider"
]
}
}
}

View File

@@ -2,7 +2,9 @@ Please check the following instructions before submitting a bug :
* Make sure you are using the latest version.
* Make sure you read [installation](http://unisharp.github.io/laravel-filemanager/installation), [integration](http://unisharp.github.io/laravel-filemanager/integration), and [upgrade](http://unisharp.github.io/laravel-filemanager/upgrade) document.
If your problem still remains, please do these steps :
* Run `php ./vendor/unisharp/laravel-filemanager/bin/debug` and paste the results here.
* Capture screenshots of your browser console and paste them here.
* Provide the steps to reproduce your issue, so we might solve it quicker.
And provide the followings :
* Operating system :
* Laravel version :
* Package version :
* Steps to reproduce your issue :
* Screenshots of browser console :

View File

@@ -0,0 +1,16 @@
---
name: Bug report
about: Create a report to help us improve
---
Please check the following instructions before submitting a bug :
* Make sure you are using the latest version.
* Make sure you read [installation](http://unisharp.github.io/laravel-filemanager/installation), [integration](http://unisharp.github.io/laravel-filemanager/integration), and [upgrade](http://unisharp.github.io/laravel-filemanager/upgrade) document.
And provide the followings :
* Operating system :
* Laravel version :
* Package version :
* Steps to reproduce your issue :
* Screenshots of browser console :

View File

@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -1 +1,6 @@
/vendor
composer.lock
/docs/Gemfile.lock
/docs/_site
.DS_Store
/.idea

View File

@@ -1,15 +1,15 @@
language: php
php:
- 5.5
- 8.0
- 7.4
- 5.6
- 7.0
- hhvm
matrix:
fast_finish: true
allow_failures:
- php: 7.0
- php: 7.4
- php: 5.6
before_script:
- travis_retry composer self-update

View File

@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at service@unisharp.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@@ -0,0 +1,13 @@
## Steps to contribute
1. Fork [unisharp/laravel-filemanager](https://github.com/UniSharp/laravel-filemanager) from GitHub.
1. Run commands below:
```
git clone git@github.com:UniSharp/laravel-filemanager-example-5.3.git
cd laravel-filemanager-example-5.3
composer require unisharp/laravel-filemanager:dev-master
make init
```
1. Edit codes in `vendor/unisharp/laravel-filemanager`
1. Push your changes to your fork.
1. Send a pull request to [unisharp/laravel-filemanager](https://github.com/UniSharp/laravel-filemanager).

View File

@@ -0,0 +1,3 @@
test:
vendor/bin/phpunit --coverage-text
vendor/bin/phpcs --version && echo && vendor/bin/phpcs -p --standard=PSR2 --ignore=src/lang/,src/views/ src tests

View File

@@ -0,0 +1,2 @@
#### (optional) Issue number:
#### Summary of the change:

View File

@@ -1,71 +1,85 @@
# Laravel Filemanager
[![Latest Stable Version](https://poser.pugx.org/unisharp/laravel-filemanager/v/stable)](https://packagist.org/packages/unisharp/laravel-filemanager)
[![Total Downloads](https://poser.pugx.org/unisharp/laravel-filemanager/downloads)](https://packagist.org/packages/unisharp/laravel-filemanager)
[![License](https://poser.pugx.org/unisharp/laravel-filemanager/license)](https://packagist.org/packages/unisharp/laravel-filemanager)
<p align="center"><img src="https://unisharp.github.io/laravel-filemanager/images/logo_vertical_colored.png"></p>
* Document : [unisharp.github.io/laravel-filemanager](http://unisharp.github.io/laravel-filemanager/)
* [Installation](http://unisharp.github.io/laravel-filemanager/installation)
* [Integration](http://unisharp.github.io/laravel-filemanager/integration)
* [Config](http://unisharp.github.io/laravel-filemanager/config)
* [Customization](http://unisharp.github.io/laravel-filemanager/customization)
* [Events](http://unisharp.github.io/laravel-filemanager/events)
* [Upgrade](http://unisharp.github.io/laravel-filemanager/upgrade)
* Demo : [Laravel Filemanager container](https://github.com/UniSharp/laravel-filemanager-example-5.3)
<p align="center">
<a target="_blank" href="https://packagist.org/packages/unisharp/laravel-filemanager"><img src="https://poser.pugx.org/unisharp/laravel-filemanager/downloads"></a>
<a target="_blank" href="https://packagist.org/packages/unisharp/laravel-filemanager"><img src="https://img.shields.io/packagist/dm/unisharp/laravel-filemanager.svg"></a>
<a target="_blank" href="https://packagist.org/packages/unisharp/laravel-filemanager"><img src="https://img.shields.io/badge/stable-2.4.1-blue.svg"></a>
<a target="_blank" href="https://packagist.org/packages/unisharp/laravel-filemanager"><img src="https://poser.pugx.org/unisharp/laravel-filemanager/license"></a>
<br>
<a href="https://github.styleci.io/repos/39873788?branch=master"><img src="https://github.styleci.io/repos/39873788/shield?branch=master" alt="StyleCI"></a>
<a target="_blank" href="https://scrutinizer-ci.com/g/UniSharp/laravel-filemanager/?branch=master"><img src="https://scrutinizer-ci.com/g/UniSharp/laravel-filemanager/badges/build.png?b=master"></a>
<a target="_blank" href="https://scrutinizer-ci.com/g/UniSharp/laravel-filemanager/"><img src="https://scrutinizer-ci.com/g/UniSharp/laravel-filemanager/badges/quality-score.png?b=master"></a>
<a target="_blank" href="https://codeclimate.com/github/UniSharp/laravel-filemanager/maintainability"><img src="https://api.codeclimate.com/v1/badges/e51f2ef8f4d9f97268db/maintainability" /></a>
</p>
## v1.8 released
* Please follow the intructions in [upgrade document](https://unisharp.github.io/laravel-filemanager/upgrade).
* Important changes :
* Fix Windows compatibility (utf-8 file names and folder names).
* New feature : Copy & Crop. Thanks [gwleuverink](https://github.com/gwleuverink).
* [Config document](https://unisharp.github.io/laravel-filemanager/config) is refactored.
<p align="center">
<a href="http://unisharp.github.io/laravel-filemanager/">Documents</a>
<a href="http://unisharp.github.io/laravel-filemanager/installation">Installation</a>
<a href="http://unisharp.github.io/laravel-filemanager/integration">Integration</a>
<a href="http://unisharp.github.io/laravel-filemanager/config">Config</a>
<a href="http://unisharp.github.io/laravel-filemanager/customization">Customization</a>
<a href="http://unisharp.github.io/laravel-filemanager/events">Events</a>
<a href="http://unisharp.github.io/laravel-filemanager/upgrade">Upgrade</a>
<a href="https://github.com/UniSharp/laravel-filemanager-example-5.3">Demo</a>
<a href="https://github.com/UniSharp/laravel-filemanager/wiki">FAQ</a>
</p>
## Security
## Features
* File upload and management
* Uploading validation
* Cropping and resizing of images
* RWD user interface, and can be entirely customized
* Supporting multiple files selection
* Supporting cloud storages integration(with Laravel file system)
* Multiple integration options:
* WYSIWYG editors integration (CKEditor, TinyMCE, Summernote)
* Standalone upload button
* Iframe
* Multi-user mode:
* Shared folders: all users can upload and manage files
* Private folders: dedicated folder for each user, only the owner can upload or manage files within
* Customizable routes, middlewares, views, and folder path
* Supports two categories: files and images. Each type works in different directory.
* Supported locales : ar, az, bg, cs, de, el, en, es, eu, fa, fr, he, hu, id, it, ka, nl, pl, pt, pt-BR, ro, rs, ru, sk, sv, tr, uk, vi, zh-CN, zh-TW
It is important to note that if you use your own routes **you must protect your routes to Laravel-Filemanager in order to prevent unauthorized uploads to your server**. Fortunately, Laravel makes this very easy.
## v2.0 backlogs
If, for example, you want to ensure that only logged in users have the ability to access the Laravel-Filemanager, simply wrap the routes in a group, perhaps like this:
There are still some thing we need to do make this package better:
* [x] Documents for v2.0.0
* [x] Add more events for files and folders manipulation
* [ ] Events should pass object instead of only file path
```php
Route::group(['middleware' => 'auth'], function () {
Route::get('/laravel-filemanager', '\UniSharp\LaravelFilemanager\controllers\LfmController@show');
Route::post('/laravel-filemanager/upload', '\UniSharp\LaravelFilemanager\controllers\UploadController@upload');
// list all lfm routes here...
});
```
We are also going to gain more integration like vue.js and Laravel Nova. Any PR is welcome!
This approach ensures that only authenticated users have access to the Laravel-Filemanager. If you are using Middleware or some other approach to enforce security, modify as needed.
![RWD demo](https://unisharp.github.io/laravel-filemanager/images/screenshots-v2.png)
**If you use the laravel-filemanager default route, make sure the `auth` middleware (set in config/lfm.php) is enabled and functional**.
## Maintainers
## v2.0 progress
* [x] (done) Unit test
* [x] (done) Integrate with Laravel Storage
* [x] (done) Multiple selection
* [ ] Configurable disk of storage
* [ ] (in progress) Responsive design
* [ ] (in progress) Config refactoring
* [x] (done) JSON APIs
* [ ] Move to folder function
* [ ] Applying MIME icon generator
* [x] (done) Bootstrap 4 support
* [Stream](https://github.com/streamtw)
* [Youchen Lee](https://github.com/youchenlee)
* [Willem Leuverink](https://github.com/gwleuverink)
## Contributors
## Contributors & Credits
### Developers / Maintainers
* [Stream](https://github.com/g0110280)
* [@gwleuverink](https://github.com/gwleuverink)
* All [@UniSharp](https://github.com/UniSharp) members
### Contributors
* Security contributors (sort by alphabet)
* Ayon Hasan (@lollipopl337)
* Nathan
* [@mdnazmulhasan27771](https://github.com/mdnazmulhasan27771) the designer of our logo. (Licensed CC BY 4.0)
* [All contibutors](https://github.com/UniSharp/laravel-filemanager/graphs/contributors) from GitHub. (issues / PR)
## Credits
* [@taswler](https://github.com/tsawler) the original author of this package.
* Nathan for providing security suggestions.
### Credits
* [@olivervogel](https://github.com/olivervogel) for the awesome [image library](https://github.com/Intervention/image).
* SVG Loaders by [Sam](http://samherbert.net/svg-loaders/) (Licensed MIT)
* Articles and videos which helped promoting this package.
* All users and you.

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env php
<?php
/*
* This file is part of laravel-filemanager.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$composerLock = file_get_contents('composer.lock');
$jsonComposerLock = json_decode($composerLock);
foreach ($jsonComposerLock->packages as $package) {
if ($package->name == 'unisharp/laravel-filemanager')
$lfmVersion = $package->version;
if ($package->name == 'laravel/framework')
$laravelVersion = $package->version;
if (isset($lfmVersion) && isset($laravelVersion))
break;
}
$imagickCheck = extension_loaded('imagick') ? 'Install' : 'Not Install';
$gfCheck = extension_loaded('gd') ? 'Install' : 'Not Install';
// show the basic information for debug message
echo 'OS System & Version: ' . php_uname() . PHP_EOL;
echo 'Laravel Version: ' . $laravelVersion . PHP_EOL;
echo 'File Manager Version: ' . $lfmVersion . PHP_EOL;
echo 'imagick Extension: ' . $imagickCheck . PHP_EOL;
echo 'gd Extension: ' . $gfCheck . PHP_EOL;

View File

@@ -1,6 +1,6 @@
{
"name": "unisharp/laravel-filemanager",
"description": "A file upload/editor intended for use with Laravel 5 and CKEditor / TinyMCE",
"description": "A file upload/editor intended for use with Laravel 5 to 6 and CKEditor / TinyMCE",
"license": "MIT",
"keywords": [
"filemanager",
@@ -19,20 +19,24 @@
},
{
"name": "UniSharp Ltd.",
"email": "unisharp-service@unisharp.com"
"email": "opensource@unisharp.com"
}
],
"require": {
"php": ">=5.4.0",
"php": ">=7.2.0",
"ext-exif": "*",
"ext-fileinfo": "*",
"illuminate/support": ">=4.2.0",
"intervention/image": "2.*"
"intervention/image": "2.*",
"illuminate/config": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0 || ^8.0 || ^9.0",
"illuminate/filesystem": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0 || ^8.0 || ^9.0",
"illuminate/support": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0 || ^8.0 || ^9.0",
"illuminate/http": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0 || ^8.0 || ^9.0",
"illuminate/container": "5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6.0 || ^7.0 || ^8.0 || ^9.0"
},
"require-dev": {
"orchestra/testbench": "~3.0",
"phpspec/phpspec": "~2.1",
"phpunit/phpunit": "~4.8"
"phpunit/phpunit": "^6.2",
"mockery/mockery": "^0.9.9",
"squizlabs/php_codesniffer": "^3.1"
},
"suggest": {
"ext-gd": "to use GD library based image processing.",
@@ -43,7 +47,11 @@
"UniSharp\\LaravelFilemanager\\": "src/"
}
},
"bin": ["bin/debug"],
"autoload-dev": {
"psr-4": {
"Tests\\": "tests"
}
},
"extra": {
"laravel": {
"providers": [

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
source 'https://rubygems.org'
gem 'github-pages', group: :jekyll_plugins

View File

@@ -2,7 +2,7 @@ theme: jekyll-theme-cayman
# Setup
title: Laravel File Manager
description: File manager/gallery with CKEditor, TinyMCE and Summernote support.
description: It's like Dropbox for your Laravel app.
google_analytics: UA-92410814-4
# About/contact

View File

@@ -8,6 +8,12 @@
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
<style>
h1.project-name {
margin-top: 100px;
}
h2.project-tagline {
margin-bottom: 5rem;
}
#nav > span > a {
color: #dddddd;
}
@@ -15,20 +21,86 @@
content: ' |';
color: #dddddd;
}
.button-group {
display: flex;
justify-content: center;
margin-bottom: 30px;
}
@media screen and (max-width: 42em) {
a.btn {
width: 50%;
margin: 0;
}
a.btn + a.btn {
margin-top: 0;
margin-left: 15px;
}
}
.main-content {
padding: 1rem !important;
}
#carbonads {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
overflow: hidden;
background-color: rgba(0, 0, 0, .05);
font-size: 14px;
padding: 15px 15px 15px 160px;
}
#carbonads a {
text-decoration: none;
}
#carbonads a:hover {
color: inherit;
}
.carbon-img {
float: left;
margin-left: -145px;
width: 130px;
height: 100px;
}
.carbon-img img {
width: 130px;
height: 100px;
}
.carbon-text {
color: #333;
}
.carbon-poweredby {
display: block;
color: #777;
}
@media only screen and (min-width: 400px) {
#carbonads {
max-width: 330px;
}
}
</style>
</head>
<body>
<section class="page-header">
<h1 class="project-name">{{ site.title | default: site.github.repository_name }}</h1>
<h2 class="project-tagline">{{ site.description | default: site.github.project_tagline }}</h2>
<a class="btn" href="https://github.com/UniSharp/laravel-filemanager-example-5.3" target="_blank">Demo</a>
{% if site.github.is_project_page %}
<div class="button-group">
<a class="btn" href="https://github.com/UniSharp/laravel-filemanager-example-5.3" target="_blank">Demo</a>
{% if site.github.is_project_page %}
<a href="{{ site.github.repository_url }}" class="btn">View on GitHub</a>
{% endif %}
{% if site.show_downloads %}
<a href="{{ site.github.zip_url }}" class="btn">Download .zip</a>
<a href="{{ site.github.tar_url }}" class="btn">Download .tar.gz</a>
{% endif %}
{% endif %}
{% if site.show_downloads %}
<a href="{{ site.github.zip_url }}" class="btn">Download .zip</a>
<a href="{{ site.github.tar_url }}" class="btn">Download .tar.gz</a>
{% endif %}
</div>
<nav id="nav">
<span><a href="/laravel-filemanager">Home</a></span>
<span><a href="installation">Installation</a></span>
@@ -38,10 +110,12 @@
<span><a href="events">Events</a></span>
<span><a href="upgrade">Upgrade</a></span>
<span><a href="contribution">Contribution</a></span>
<span><a href="security">Security</a></span>
</nav>
</section>
<section class="main-content">
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CK7DE2JL&placement=unisharpgithubio" id="_carbonads_js"></script>
{{ content }}
<footer class="site-footer">

View File

@@ -2,89 +2,261 @@
## Routing:
| Key | Type | Description |
|--------------------|---------|--------------------------------------------------------------------------------------------------------------|
| use\_package\_routes | boolean | Use routes from package or not. If false, you will need to define routes to all controllers of this package. |
| middlewares | array | Middlewares to be applied to default routes. For laravel 5.1 and before, remove 'web' from the array. |
| url_prefix | string | The url prefix to this package. Change it if necessary. |
### use\_package\_routes
* type: `boolean`
* default: `true`
Use default routes or not. You will need to define routes to all controllers of this package if this is set to `false`.
## Multi-User Mode:
| Key | Type | Description |
|--------------------|---------|------------------------------------------------------------------------------------------------|
| allow\_multi\_user | boolean | If true, private folders will be created for each signed-in user. |
| allow\_share\_folder | boolean | If true, share folder will be created. |
| user_field | string | Private folders will be named by this. Can receive column name of `users` table or class name. |
### allow\_private\_folder
### If you want to name private folders other than columns of users table, follow these steps:
1. Run `php artisan vendor:publish --tag=lfm_handler`.
2. Fill `App\Handler\ConfigHander::class` into `user_field`.
3. Edit `userField()` in the `App\Handler\ConfigHander`
* type: `boolean`
* default: `true`
Only the owner(each signed-in user) of the private can upload and manage files within. Set to `false` to turn this feature off.
### private\_folder\_name
* type: `string`
* default: user id
Privates folders for each user will be named by this config. Default to user id.
To change the behavior:
1. run `php artisan publish tag="lfm_handler"`
2. rewrite `userField` function in App\Handler\ConfigHandler class
3. set value of this config to App\Handler\ConfigHandler::class
### allow\_shared\_folder
* type: `boolean`
* default: `true`
### shared\_folder\_name
* type: `string`
* default: `"shares"`
Flexible way to customize client folders accessibility.
If you want to customize client folders:
1. run `php artisan publish tag="lfm_handler"`
2. rewrite `userField` function in `App\Handler\ConfigHandler` class
3. set value of this config to `App\Handler\ConfigHandler::class`
All users can upload and manage files within shared folders. Set to `false` to turn this feature off.
## Working Directory:
## Folder Categories
| Key | Type | Description |
|--------------------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| base_directory | string | Which folder to store files in project, fill in 'public', 'resources', 'storage' and so on. Does not support path relative path like `../public_html` or `public/upload/user/`. |
| images\_folder\_name | string | Does not support path relative path like `../public_html` or `public/upload/user/`. |
| files\_folder\_name | string | Does not support path relative path like `../public_html` or `public/upload/user/`. |
| shared\_folder\_name | string | Does not support path relative path like `../public_html` or `public/upload/user/`. |
| thumb\_folder\_name | string | Does not support path relative path like `../public_html` or `public/upload/user/`. |
### folder\_categories
* type: `array` (nested)
* default:
## Startup Views:
```
'folder_categories' => [
'file' => [
'folder_name' => 'files',
'startup_view' => 'list',
'max_size' => 50000, // size in KB
'valid_mime' => [
'image/jpeg',
'image/pjpeg',
'image/png',
'image/gif',
'application/pdf',
'text/plain',
],
],
'image' => [
'folder_name' => 'photos',
'startup_view' => 'grid',
'max_size' => 50000, // size in KB
'valid_mime' => [
'image/jpeg',
'image/pjpeg',
'image/png',
'image/gif',
],
],
],
```
| Key | Type | Description |
|---------------------|--------|-----------------------------------------------------------------|
| images\_startup\_view | string | The default display type for images. Supported: "grid", "list". |
| files\_startup\_view | string | The default display type for files. Supported: "grid", "list". |
The default config creates two folder categories, `file` and `image`, each operates independently. Files uploaded by users will be placed under one of these folder categories, depend on which is configured with your WYSIWYG editor or stand-alone upload button.
Detail options are explained here:
* `folder_name`: The folder name of the category. For example, if `folder_name` is set to `files2` then:
* directory path of the private folder will be: `/<path-to-laravel>/storage/app/public/files2/<user-id>/`
* directory path of the shared folder will be: `/<path-to-laravel>/storage/app/public/files2/shares/`
* `startup_view`: The default display mode. Available options: `list` & `grid`.
* `max_size`: The maximum size(in KB) of of a single file to be uploaded.
* `valid_mime`: Only files with mime types listed here are allowed to be uploaded. See [full mime types list](http://docs.w3cub.com/http/basics_of_http/mime_types/complete_list_of_mime_types/).
## Pagination:
### paginator
* type: `array`
* default:
```
'paginator' => [
'perPage' => 30,
],
```
## Upload / Validation:
| Key | Type | Description |
|-------------------------|---------|--------------------------------------------------------------------------|
| rename_file | string | If true, the uploaded file will be renamed to uniqid() + file extension. |
| alphanumeric_filename | string | If true, non-alphanumeric file name will be replaced with `_`. |
| alphanumeric_directory | boolean | If true, non-alphanumeric folder name will be rejected. |
| should\_validate\_size | boolean | If true, the size of uploading file will be verified. |
| max\_image\_size | int | Specify max size of uploading image. |
| max\_file\_size | int | Specify max size of uploading file. |
| should\_validate\_mime | boolean | If true, the mime type of uploading file will be verified. |
| valid\_image\_mimetypes | array | Array of mime types. Available since v1.3.0 . |
| should\_create\_thumbnails | boolean | If true, thumbnails will be created for faster loading. |
| raster\_mimetypes | array | Array of mime types. Thumbnails will be created only for these mimetypes. |
| create\_folder\_mode | int | Permission setting for folders created by this package. |
| create\_file\_mode | int | Permission setting for files uploaded to this package. |
| should\_change\_file\_mode | boolean | If true, it will attempt to chmod the file after upload |
| valid\_file\_mimetypes | array | Array of mime types. Available since v1.3.0 . |
### disk
* type: `string`
* default: `public`
## Thumbnail dimensions:
Disk name of Laravel File System. All files are placed in here. Choose one of the `disks` section in `config/filesystems.php`.
### rename\_file
* type: `boolean`
* default: `false`
If set to `true`, the uploaded file will be renamed using `uniqid()`.
### alphanumeric\_filename
* type: `boolean`
* default: `false`
If set to `true`, non-alphanumeric file name will be replaced with `_`.
### alphanumeric\_directory
* type: `boolean`
* default: `false`
If set to `true`, non-alphanumeric folder name will be rejected.
### should\_validate\_size
* type: `boolean`
* default: `false`
If set to `true`, the size of uploading file will be verified.
### should\_validate\_mime
* type: `boolean`
* default: `true`
If set to `true`, the mime type of uploading file will be verified.
### over\_write\_on_duplicate
* type: `int`
* default: `false`
Define behavior on files with identical name. Setting it to `true` cause old file replace with new one. Setting it to `false` show `error-file-exist` error and abort the upload process.
## Thumbnail
### should\_create\_thumbnails
* type: `boolean`
* default: `true`
If set to `true`, thumbnails will be created for faster loading.
### thumb\_folder\_name
* type: `string`
* default: `thumbs`
Folder name to place thumbnails.
### raster\_mimetypes
* type: `array`
* default:
```
'raster_mimetypes' => [
'image/jpeg',
'image/pjpeg',
'image/png',
],
```
Create thumbnails automatically only for listed types. See [full mime types list](http://docs.w3cub.com/http/basics_of_http/mime_types/complete_list_of_mime_types/).
### thumb_img_width
* type: `int`
* default: `200`
Thumbnail images width (in px).
### thumb_img_height
* type: `int`
* default: `200`
Thumbnail images height (in px).
Create thumbnails automatically only for listed types.
| Key | Type | Description |
|------------------|--------|--------------------------------------------------|
| thumb\_img\_width | string | Width of thumbnail made when image is uploaded. |
| thumb\_img\_height | string | Height of thumbnail made when image is uploaded. |
## File Extension Information
| Key | Type | Description |
|-----------------|-------|---------------------------------------------|
| file\_type\_array | array | Map file extension with display names. |
| file\_icon\_array | array | Map file extension with icons(font-awsome). |
### file\_type\_array
* type: `array`
* default:
```
'file_type_array' => [
'pdf' => 'Adobe Acrobat',
'doc' => 'Microsoft Word',
'docx' => 'Microsoft Word',
'xls' => 'Microsoft Excel',
'xlsx' => 'Microsoft Excel',
'zip' => 'Archive',
'gif' => 'GIF Image',
'jpg' => 'JPEG Image',
'jpeg' => 'JPEG Image',
'png' => 'PNG Image',
'ppt' => 'Microsoft PowerPoint',
'pptx' => 'Microsoft PowerPoint',
],
```
Gives description for listed file extensions.
## php.ini override
| Key | Type | Description |
|-------------------|-----------------|-----------------------------------------------------------------------------------------------------------------------------------|
| php\_ini\_overrides | array or boolean | These values override your php.ini settings before uploading files. Set these to false to ingnore and apply your php.ini settings |
### php\_ini\_overrides
### Caveats
* type: `array` or `boolean`
* default:
```
'php_ini_overrides' => [
'memory_limit' => '256M',
],
```
These values override your php.ini settings before uploading files. Set these to false to ingnore and apply your php.ini settings
⚠️ **Caveats**
The php\_ini\_overrides are applied on every request the filemanager does and are reset once the script has finished executing.
This has one drawback: any ini settings that you might want to change that apply to the request itself will not work.

View File

@@ -9,5 +9,6 @@
make init
```
1. Edit codes in `vendor/unisharp/laravel-filemanager`
1. Push your changes to your fork.
1. Commit and follow rules in [Conventional Commits](https://www.conventionalcommits.org/).
1. Push your changes to a new branch other than `master`. Good branch name might be like: `feature/add-pagination`, `fix/file-not-displayed`.
1. Send a pull request to [unisharp/laravel-filemanager](https://github.com/UniSharp/laravel-filemanager).

View File

@@ -1,5 +1,18 @@
## Routes
1. Copy the routes in `/vendor/unisharp/laravel-filemanager/src/routes.php`
1. Edit `routes/web.php` :
Create route group to wrap package routes.
```php
Route::group(['prefix' => 'laravel-filemanager', 'middleware' => ['web', 'auth']], function () {
\UniSharp\LaravelFilemanager\Lfm::routes();
});
```
Make sure `auth` middleware is present to :
1. prevent unauthorized uploads
1. work properly with multi-user mode
1. Make sure urls below is correspond to your route (remember to include type parameter `?type=Images` or `?type=Files`) :
* CKEditor
@@ -8,7 +21,7 @@
filebrowserImageBrowseUrl: '/your-custom-route?type=Images',
filebrowserBrowseUrl: '/your-custom-route?type=Files'
});
```
```
* TinyMCE
```javascript
...

View File

@@ -1,17 +1,34 @@
## List of events
* Unisharp\Laravelfilemanager\Events\ImageIsUploading
* Unisharp\Laravelfilemanager\Events\ImageWasUploaded
* Unisharp\Laravelfilemanager\Events\ImageIsRenaming
* Unisharp\Laravelfilemanager\Events\ImageWasRenamed
* Unisharp\Laravelfilemanager\Events\ImageIsDeleting
* Unisharp\Laravelfilemanager\Events\ImageWasDeleted
* Unisharp\Laravelfilemanager\Events\FolderIsRenaming
* Unisharp\Laravelfilemanager\Events\FolderWasRenamed
* Unisharp\Laravelfilemanager\Events\ImageIsResizing
* Unisharp\Laravelfilemanager\Events\ImageWasResized
* Unisharp\Laravelfilemanager\Events\ImageIsCropping
* Unisharp\Laravelfilemanager\Events\ImageWasCropped
* File
* UniSharp\LaravelFilemanager\Events\FileIsUploading
* UniSharp\LaravelFilemanager\Events\FileWasUploaded
* UniSharp\LaravelFilemanager\Events\FileIsRenaming
* UniSharp\LaravelFilemanager\Events\FileWasRenamed
* UniSharp\LaravelFilemanager\Events\FileIsMoving
* UniSharp\LaravelFilemanager\Events\FileWasMoving
* UniSharp\LaravelFilemanager\Events\FileIsDeleting
* UniSharp\LaravelFilemanager\Events\FileWasDeleted
* Image
* UniSharp\LaravelFilemanager\Events\ImageIsUploading
* UniSharp\LaravelFilemanager\Events\ImageWasUploaded
* UniSharp\LaravelFilemanager\Events\ImageIsRenaming
* UniSharp\LaravelFilemanager\Events\ImageWasRenamed
* UniSharp\LaravelFilemanager\Events\ImageIsResizing
* UniSharp\LaravelFilemanager\Events\ImageWasResized
* UniSharp\LaravelFilemanager\Events\ImageIsCropping
* UniSharp\LaravelFilemanager\Events\ImageWasCropped
* UniSharp\LaravelFilemanager\Events\ImageIsDeleting
* UniSharp\LaravelFilemanager\Events\ImageWasDeleted
* Folder
* UniSharp\LaravelFilemanager\Events\FolderIsCreating
* UniSharp\LaravelFilemanager\Events\FolderWasCreated
* UniSharp\LaravelFilemanager\Events\FolderIsRenaming
* UniSharp\LaravelFilemanager\Events\FolderWasRenamed
* UniSharp\LaravelFilemanager\Events\FolderIsMoving
* UniSharp\LaravelFilemanager\Events\FolderWasMoving
* UniSharp\LaravelFilemanager\Events\FolderIsDeleting
* UniSharp\LaravelFilemanager\Events\FolderWasDeleted
## How to use
* Sample code : [laravel-filemanager-demo-events](https://github.com/UniSharp/laravel-filemanager-demo-events)

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -2,28 +2,34 @@
[![Total Downloads](https://poser.pugx.org/unisharp/laravel-filemanager/downloads)](https://packagist.org/packages/unisharp/laravel-filemanager)
[![License](https://poser.pugx.org/unisharp/laravel-filemanager/license)](https://packagist.org/packages/unisharp/laravel-filemanager)
This is the document of v2 version, v1 document can be found here: [https://github.com/UniSharp/laravel-filemanager/tree/v1/docs](https://github.com/UniSharp/laravel-filemanager/tree/v1/docs)
## Features
* CKEditor and TinyMCE integration
* Standalone button
* File upload and management
* Uploading validation
* Cropping and resizing of images
* Public and private folders for multi users
* RWD user interface, and can be entirely customized
* Supporting multiple files selection
* Supporting cloud storages integration(with Laravel file system)
* Multiple integration options:
* WYSIWYG editors integration (CKEditor, TinyMCE, Summernote)
* Standalone upload button
* Iframe
* Multi-user mode:
* Shared folders: all users can upload and manage files
* Private folders: dedicated folder for each user, only the owner can upload or manage files within
* Customizable routes, middlewares, views, and folder path
* Supports two types : files and images. Each type works in different directory.
* Supported locales : ar, bg, de, el, en, es, fa, fr, he, hu, nl, pl, pt-BR, pt_PT, ro, ru, tr, zh-CN, zh-TW
* Supports two categories: files and images. Each type works in different directory.
* Supported locales : ar, az, bg, cs, de, el, en, es, eu, fa, fr, he, hu, id, it, ka, nl, pl, pt, pt-BR, ro, rs, ru, sk, sv, tr, uk, vi, zh-CN, zh-TW
PR is welcome!
PRs are welcome!
## Screenshots
> Standalone button :
![Standalone button demo](https://unisharp.github.io/laravel-filemanager/images/lfm01.png)
> Grid view :
> Responsive design :
![Grid view demo](https://unisharp.github.io/laravel-filemanager/images/lfm02.png)
> List view :
![List view demo](https://unisharp.github.io/laravel-filemanager/images/lfm03.png)
![RWD demo](https://unisharp.github.io/laravel-filemanager/images/screenshots-v2.png)

View File

@@ -6,16 +6,28 @@
* Laravel 5
* requires [intervention/image](https://github.com/Intervention/image) (to make thumbs, crop and resize images).
## Installation
1. Install package
## TL;DR
1. Run these lines
```bash
composer require unisharp/laravel-filemanager:~1.8
composer require unisharp/laravel-filemanager
php artisan vendor:publish --tag=lfm_config
php artisan vendor:publish --tag=lfm_public
php artisan storage:link
```
1. Edit `config/app.php` :
1. Edit `APP_URL` in `.env`.
\* *For Laravel 5.5 and up, skip to step 3. All service providers and facades are automatically discovered.*
## Full Installation Guide
1. Install package
```bash
composer require unisharp/laravel-filemanager
```
1. (optional) Edit `config/app.php` :
\* *For Laravel 5.5 and up, skip to step 3. All service providers and facades are automatically discovered.*
Add service providers
@@ -39,16 +51,46 @@
php artisan vendor:publish --tag=lfm_config
php artisan vendor:publish --tag=lfm_public
```
1. Run commands to clear cache :
1. (optional) Run commands to clear cache :
```bash
php artisan route:clear
php artisan config:clear
```
1. Ensure that the files & images directories (in `config/lfm.php`) are writable by your web server (run commands like `chown` or `chmod`).
1. Create symbolic link :
```bash
php artisan storage:link
```
1. Edit `APP_URL` in `.env`.
1. Edit `routes/web.php` :
Create route group to wrap package routes.
```php
Route::group(['prefix' => 'laravel-filemanager', 'middleware' => ['web', 'auth']], function () {
\UniSharp\LaravelFilemanager\Lfm::routes();
});
```
Make sure `auth` middleware is present to :
1. prevent unauthorized uploads
1. work properly with multi-user mode
1. make sure database exists
1. login and visit `/laravel-filemanager/demo`
## Installing alpha version
* Run `composer require unisharp/laravel-filemanager:dev-master` to get the latest developer version.
## What's next
1. Check the [integration document](http://unisharp.github.io/laravel-filemanager/integration) to see how to apply this package.

View File

@@ -34,8 +34,54 @@ Check `vendor/unisharp/laravel-filemanager/src/views/demo.blade.php`, which alre
$('textarea.my-editor').ckeditor(options);
</script>
```
### Option 2: TinyMCE5
### Option 2: TinyMCE4
```html
<script src="/path-to-your-tinymce/tinymce.min.js"></script>
<textarea name="content" class="form-control my-editor">{!! old('content', $content) !!}</textarea>
<script>
var editor_config = {
path_absolute : "/",
selector: 'textarea.my-editor',
relative_urls: false,
plugins: [
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
"searchreplace wordcount visualblocks visualchars code fullscreen",
"insertdatetime media nonbreaking save table directionality",
"emoticons template paste textpattern"
],
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media",
file_picker_callback : function(callback, value, meta) {
var x = window.innerWidth || document.documentElement.clientWidth || document.getElementsByTagName('body')[0].clientWidth;
var y = window.innerHeight|| document.documentElement.clientHeight|| document.getElementsByTagName('body')[0].clientHeight;
var cmsURL = editor_config.path_absolute + 'laravel-filemanager?editor=' + meta.fieldname;
if (meta.filetype == 'image') {
cmsURL = cmsURL + "&type=Images";
} else {
cmsURL = cmsURL + "&type=Files";
}
tinyMCE.activeEditor.windowManager.openUrl({
url : cmsURL,
title : 'Filemanager',
width : x * 0.8,
height : y * 0.8,
resizable : "yes",
close_previous : "no",
onMessage: (api, message) => {
callback(message.content);
}
});
}
};
tinymce.init(editor_config);
</script>
```
### Option 3: TinyMCE4
```html
<script src="//cdn.tinymce.com/4/tinymce.min.js"></script>
@@ -78,13 +124,13 @@ Check `vendor/unisharp/laravel-filemanager/src/views/demo.blade.php`, which alre
</script>
```
### Option 3: Summernote
### Option 4: Summernote
```html
<!-- dependencies (Summernote depends on Bootstrap & jQuery) -->
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.3/summernote.css" rel="stylesheet">
<script src="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.3/summernote.js"></script>
@@ -94,44 +140,45 @@ Check `vendor/unisharp/laravel-filemanager/src/views/demo.blade.php`, which alre
<!-- summernote config -->
<script>
$(document).ready(function(){
$(document).ready(function(){
// Define function to open filemanager window
var lfm = function(options, cb) {
var route_prefix = (options && options.prefix) ? options.prefix : '/laravel-filemanager';
window.open(route_prefix + '?type=' + options.type || 'file', 'FileManager', 'width=900,height=600');
window.SetUrl = cb;
var route_prefix = (options && options.prefix) ? options.prefix : '/laravel-filemanager';
window.open(route_prefix + '?type=' + options.type || 'file', 'FileManager', 'width=900,height=600');
window.SetUrl = cb;
};
// Define LFM summernote button
var LFMButton = function(context) {
var ui = $.summernote.ui;
var button = ui.button({
contents: '<i class="note-icon-picture"></i> ',
tooltip: 'Insert image with filemanager',
click: function() {
lfm({type: 'image', prefix: '/file-manager'}, function(url, path) {
context.invoke('insertImage', url);
});
var ui = $.summernote.ui;
var button = ui.button({
contents: '<i class="note-icon-picture"></i> ',
tooltip: 'Insert image with filemanager',
click: function() {
}
});
return button.render();
lfm({type: 'image', prefix: '/laravel-filemanager'}, function(lfmItems, path) {
lfmItems.forEach(function (lfmItem) {
context.invoke('insertImage', lfmItem.url);
});
});
}
});
return button.render();
};
// Initialize summernote with LFM button in the popover button group
// Please note that you can add this button to any other button group you'd like
$('#summernote-editor').summernote({
toolbar: [
['popovers', ['lfm']],
],
buttons: {
lfm: LFMButton
}
toolbar: [
['popovers', ['lfm']],
],
buttons: {
lfm: LFMButton
}
})
});
});
</script>
```
@@ -151,11 +198,11 @@ If you are going to use filemanager independently, meaning set the value of an i
<input id="thumbnail" class="form-control" type="text" name="filepath">
</div>
<img id="holder" style="margin-top:15px;max-height:100px;">
```
```
1. Import lfm.js(run `php artisan vendor:publish` if you need).
```html
<script src="/vendor/laravel-filemanager/js/lfm.js"></script>
<script src="/vendor/laravel-filemanager/js/stand-alone-button.js"></script>
```
1. Init filemanager with type. (requires jQuery)
@@ -171,32 +218,61 @@ If you are going to use filemanager independently, meaning set the value of an i
Domain can be specified in the second parameter(optional, but will be required when developing on Windows mechines) :
```javascript
var domain = "{{ url() }}";
$('#lfm').filemanager('image', {prefix: domain});
var route_prefix = "url-to-filemanager";
$('#lfm').filemanager('image', {prefix: route_prefix});
```
## JavaScript integration
In case you are developing javascript application and you want dynamically to trigger filemanager popup, you can create function like this. It doesn't rely on jQuery.
```javascript
var lfm = function(options, cb) {
var lfm = function(id, type, options) {
let button = document.getElementById(id);
var route_prefix = (options && options.prefix) ? options.prefix : '/laravel-filemanager';
button.addEventListener('click', function () {
var route_prefix = (options && options.prefix) ? options.prefix : '/laravel-filemanager';
var target_input = document.getElementById(button.getAttribute('data-input'));
var target_preview = document.getElementById(button.getAttribute('data-preview'));
window.open(route_prefix + '?type=' + options.type || 'file', 'FileManager', 'width=900,height=600');
window.SetUrl = cb;
}
window.open(route_prefix + '?type=' + options.type || 'file', 'FileManager', 'width=900,height=600');
window.SetUrl = function (items) {
var file_path = items.map(function (item) {
return item.url;
}).join(',');
// set the value of the desired input to image url
target_input.value = file_path;
target_input.dispatchEvent(new Event('change'));
// clear previous preview
target_preview.innerHtml = '';
// set or change the preview image src
items.forEach(function (item) {
let img = document.createElement('img')
img.setAttribute('style', 'height: 5rem')
img.setAttribute('src', item.thumb_url)
target_preview.appendChild(img);
});
// trigger change event
target_preview.dispatchEvent(new Event('change'));
};
});
};
```
And use it like this:
```javascript
lfm({type: 'image', prefix: 'prefix'}, function(url, path) {
});
var route_prefix = "url-to-filemanager";
lfm('lfm', 'image', {prefix: route_prefix});
lfm('lfm2', 'file', {prefix: route_prefix});
```
The first parameter is id, the second parameter is the type of laravel filemanager(which ).
## Embed file manager
```html

View File

@@ -0,0 +1,15 @@
## Security
It is important to note that if you use your own routes **you must protect your routes to Laravel-Filemanager in order to prevent unauthorized uploads to your server**. Fortunately, Laravel makes this very easy.
If, for example, you want to ensure that only logged in users have the ability to access the Laravel-Filemanager, simply wrap the routes in a group, perhaps like this:
```php
Route::group(['middleware' => 'auth'], function () { // auth middleware is important!
\UniSharp\LaravelFilemanager\Lfm::routes();
});
```
This approach ensures that only authenticated users have access to the Laravel-Filemanager. If you are using Middleware or some other approach to enforce security, modify as needed.
**If you use the laravel-filemanager default route, make sure the `auth` middleware (set in config/lfm.php) is enabled and functional**.

View File

@@ -1,19 +1,23 @@
## Upgrade instructions
1. Please backup your own `config/lfm.php` before upgrading.
1. Run commands:
```bash
composer update unisharp/laravel-filemanager
php artisan vendor:publish --tag=lfm_view --force
php artisan vendor:publish --tag=lfm_public --force
php artisan vendor:publish --tag=lfm_config --force
php artisan route:clear
php artisan config:clear
```
1. Clear browser cache if page is broken after upgrading.
## Errors with namespace
We have changed namespace from `Unisharp` to `UniSharp`, and change the first character of every namespace into capital.
If you are updating this package and encounter any errors like `Class not found`, please remove this package entirely and reinstall again.

File diff suppressed because one or more lines are too long

View File

@@ -1,119 +1,149 @@
@media screen and (max-width: 768px) {
#main {
padding: 0px;
}
#nav {
margin-bottom: -1px;
}
#content > .row {
margin: 0px;
}
}
/* General */
@media screen and (min-width: 768px) {
#main {
border-left: 1px solid silver;
}
}
#wrapper {
padding: 0px;
}
#wrapper > .panel {
border-radius: 0;
}
#wrapper > .panel > .panel-heading {
border-radius: 0;
}
#wrapper > .panel > .panel-heading > .panel-title {
padding: 10px 0;
}
#wrapper > .row {
margin: 0px;
}
#fab a:hover, #fab a:focus{
color: white;
}
.item_name {
width: 120px;
overflow:hidden;
white-space:nowrap;
text-overflow: ellipsis;
}
.clickable {
a {
color: #333844;
text-decoration: none !important;
cursor: pointer;
}
.img-preview {
background-color: #f7f7f7;
overflow: hidden;
width: 100%;
text-align: center;
height: 200px;
#nav a, #fab a {
color: white;
}
.hidden {
display: none;
#nav, #nav .dropdown-menu, .bg-main {
background-color: #333844;
}
.square {
width: 100%;
padding-bottom: 100%;
position: relative;
border: 1px solid rgb(221, 221, 221);
border-radius: 3px;
// max-width: 210px;
max-height: 210px;
#nav .dropdown-menu > a:hover {
color: #333844;
}
.visible-xs .square {
width: 60px;
#actions {
display: flex;
}
.square > img {
padding: 5px;
position: absolute;
max-width: 100%;
max-height: 100%;
margin: 0 auto;
#actions > a {
display: inline-block;
vertical-align: middle;
}
.square > i {
font-size: 80px;
padding: 5px;
position: absolute;
top: calc(50% - 40px);
left: calc(50% - 40px);
}
.visible-xs .square > i {
font-size: 50px;
padding: 0px auto;
padding-top: 5px;
top: calc(50% - 25px);
left: calc(50% - 25px);
line-height: 4rem;
text-align: center;
width: 100%;
font-size: 1.25rem;
}
.caption {
margin-top: 10px;
margin-bottom: 20px;
#actions > a > i {
margin-right: .25rem;
}
.caption > .btn-group {
#actions > a + a {
border-left: 1px solid #dee2e6;
}
#multi_selection_toggle > i {
font-size: 20px;
}
.breadcrumb-item:not(.active) {
transition: .2s color;
}
.breadcrumb-item:not(.active):hover {
cursor: pointer;
color: #75C7C3;
}
#main {
width: 100%;
}
.caption > .btn-group > .item_name {
width: calc(100% - 25px);
}
.caption > .btn-group > .dropdown-toggle {
width: 25px;
@media screen and (min-width: 992px) {
#main {
width: calc(100% - 300px);
/*margin-left: 1rem;*/
padding: 1rem;
}
.invisible-lg {
visibility: hidden;
}
}
#lfm-loader{
#tree {
background-color: white;
width: 300px;
}
@media screen and (max-width: 991px) {
#tree {
position: absolute;
z-index: 999;
left: 0;
transform: translateX(-100%);
transition: 1s transform;
}
#tree.in {
transform: translateX(0);
}
}
#empty {
height: 60vh;
color: #333844;
}
#empty:not(.d-none) {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#empty > i {
font-size: 10rem;
}
.carousel-image {
height: 50vh;
background-position: center;
background-size: contain;
background-repeat: no-repeat;
margin: 0 auto;
}
.carousel-indicators {
bottom: 0;
}
.carousel-label, .carousel-label:hover {
position: absolute;
bottom: 0;
background: linear-gradient(transparent 10px, rgba(0, 0, 0, .4), rgba(0, 0, 0, .5));
padding: 40px 20px 30px;
width: 100%;
color: white;
word-break: break-word;
text-align: center;
}
.carousel-control-background {
border-radius: 50%;
width: 25px;
height: 25px;
box-shadow: 0 0 10px #666;
background-color: #666;
}
#uploadForm > .dz-default.dz-message {
border: 2px dashed #ccc;
border-radius: 5px;
color: #aaa;
margin: 0;
padding: 3rem 0;
}
/* Loader */
#lfm-loader {
display: none;
position: fixed;
top: 0;
@@ -131,19 +161,227 @@
vertical-align: middle;
height: 100%;
}
#lfm-loader img{
#lfm-loader img {
width: 100px;
margin: 0 auto;
display: inline-block;
vertical-align: middle;
}
.table-list-view{
margin-bottom: 120px;
/* Sidebar */
.nav-pills > .nav-item > .nav-link {
height: 5rem;
display: flex;
align-items: center;
}
.table-list-view .actions{
.nav-pills > .sub-item > .nav-link {
height: 3rem;
padding-left: 3rem;
}
.nav-pills > li.active > a, .nav-pills > li:hover > a {
background-color: #ddd;
border-radius: 0;
color: #333844;
}
/* Items */
#pagination > ul.pagination {
justify-content: center;
}
#pagination.preserve_actions_space {
padding-top: 1em;
padding-bottom: 4rem; /* preserve space for main actions */
}
.square {
cursor: pointer;
position: relative;
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
}
.grid {
display: flex;
flex-wrap: wrap;
padding: .5rem;
justify-content: center;
}
.grid a {
margin: .5rem;
display: flex;
flex-direction: column;
}
.list a {
border-top: 1px solid rgb(221, 221, 221);
padding: 5px;
margin-top: 0;
display: flex;
flex-direction: row;
}
.list a:last-child {
border-bottom: 1px solid rgb(221, 221, 221);
}
.grid .square {
border: 1px solid rgb(221, 221, 221);
width: 135px;
height: 135px;
}
.list .square {
margin-right: 1rem;
width: 70px;
height: 70px;
}
.square > div {
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.square > i {
color: #333844;
}
.grid .square > i {
padding: 20px;
font-size: 80px;
}
.list .square > i {
padding: 10px;
font-size: 50px;
}
.grid .square.selected {
border: 5px solid #75C7C3;
}
.list .square.selected {
border: 4px solid #75C7C3;
}
.square.selected {
padding: 1px;
}
.grid .item_name {
border: 1px solid rgb(221, 221, 221);
border-top: none;
margin-top: -1px;
padding: 10px;
text-align: center;
max-width: calc(135px);
}
.list .item_name {
font-size: 1.25rem;
padding: 5px 0 5px;
}
time {
font-size: .9rem;
}
.grid time {
display: none;
}
.info > * {
max-width: calc(100vw - 70px - 60px);
}
/* Mime icon generator overwrite */
.grid .mime-icon:before {
top: calc(45% - 1rem);
font-size: 2rem;
}
.list .mime-icon .ico:before {
top: calc(45% - .5rem);
font-size: 1rem;
}
.mime-icon .ico {
height: 100%;
display: inline-flex;
align-items: center;
width: 100%;
justify-content: center;
}
/* Floating action buttons */
.fab-wrapper {
margin: 1.5rem;
right: 0;
bottom: 0;
position: fixed;
}
.fab-wrapper .fab-button {
position: relative;
background-color: #333844;
width: 3.5rem;
height: 3.5rem;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.14), 0 4px 8px rgba(0, 0, 0, 0.28);
}
.fab-wrapper .fab-toggle {
z-index: 1;
}
.fab-wrapper .fab-toggle i {
-webkit-transform: scale(1) rotate(0deg);
transform: scale(1) rotate(0deg);
-webkit-transition: -webkit-transform 350ms;
transition: transform 350ms;
}
.fab-wrapper.fab-expand .fab-toggle i {
-webkit-transform: scale(1) rotate(-225deg);
transform: scale(1) rotate(-225deg);
-webkit-transition: -webkit-transform 350ms;
transition: transform 350ms;
}
.fab-wrapper .fab-action {
z-index: -1;
margin-bottom: -3.5rem;
opacity: 0;
transition: margin-bottom 350ms, opacity 350ms;
}
.fab-wrapper.fab-expand .fab-action {
margin-bottom: 1rem;
opacity: 1;
transition: margin-bottom 350ms, opacity 350ms;
}
.fab-wrapper .fab-action:before {
position: absolute;
right: 4rem;
padding: .15rem .75rem;
border-radius: .25rem;
background-color: rgba(0, 0, 0, .4);
color: rgba(255, 255, 255, .8);
text-align: right;
font-size: .9rem;
white-space: nowrap;
content: attr(data-label);
}
.table-list-view .actions a:hover{
text-decoration: none;
}

View File

@@ -1,671 +0,0 @@
/**
* CONTENTS
*
* #Introduction........Naming conventions used throughout the code.
*
* #SETTINGS
* Variables............Globally-available variables and config.
*
* #TOOLS
* Mixins...............Useful mixins.
*
* #GENERIC
* Demo styles..........Styles for demo only (consider removing these).
*
* #BASE
* Raw styles...........The very basic component wrapper.
* Modifiers............The basic styles dependant on component placement.
* Debuggers............The basic styles dependant on component placement.
*
* #BUTTONS
* Base..................Wrapping and constraining every button.
* Modifiers.............Styles that depends on state and settings.
* Animations............Main animations of the component.
* Debuggers.............Styles for development.
*
* #LABELS
* Base..................Wrapping and constraining every label.
* Modifiers.............Styles that depends on state and settings.
* Debuggers.............Styles for development.
*
* #DEVELOPMENT
* In development........These styles are in development and not yet finalised
* Debuggers.............Helper styles and flags for development.
*/
/*------------------------------------*\
#Introduction
\*------------------------------------*/
/**
* The code AND the comments use naming conventions to refer to each part of
* the UI put in place by this component. If you see that somewhere they are
* not followed please consider a Pull Request. The naming conventions are:
*
* "Component" : the widget itself as a whole. This is the last time it will be
* called anything different than "component". So, stay away from
* "widget", "button" or anything else when referring to the
* Component in general.
*
* "Main Button" : the button that is always in view. Hovering or clicking on it
* will reveal the child buttons.
*
* "Child buttons" : if you've read the previous point you know what they are.
* Did you read the previous point? :)
*
* "Label(s)" : the tooltip that fades in when hovering over a button.
/*------------------------------------*\
#SETTINGS | Variables
\*------------------------------------*/
/**
* These variables are the default styles that serve as fallback and can be
* easily customised at compile time.
* Consider overriding them in your own style sheets rather than editing them
* here. Refer to the docs for more info.
*/
/* COLORS ----------------------------*/
/* EFFECTS ---------------------------*/
/* SPEEDS ----------------------------*/
/* SIZES -----------------------------*/
/* SPACING ---------------------------*/
/* OTHER VARIABLES -------------------*/
/*------------------------------------*\
#BASE | Raw styles
\*------------------------------------*/
/**
* The very core styling of the button.
* These styles are shared by every instance of the button.
* Styles placed here should NOT care about placement in the screen,
* options chosen by the user or state of the button.
*/
.mfb-component--tl, .mfb-component--tr, .mfb-component--bl, .mfb-component--br {
box-sizing: border-box;
margin: 25px;
position: fixed;
white-space: nowrap;
z-index: 30;
padding-left: 0;
list-style: none; }
.mfb-component--tl *, .mfb-component--tr *, .mfb-component--bl *, .mfb-component--br *, .mfb-component--tl *:before, .mfb-component--tr *:before, .mfb-component--bl *:before, .mfb-component--br *:before, .mfb-component--tl *:after, .mfb-component--tr *:after, .mfb-component--bl *:after, .mfb-component--br *:after {
box-sizing: inherit; }
/*------------------------------------*\
#BASE | Modifiers
\*------------------------------------*/
/**
* These styles depends on the placement of the button.
* Styles can be:
* 1. Top-left: modified by the " --tl " suffix.
* 2. Top-right: modified by the " --tr " suffix.
* 3. Bottom-left: modified by the " --bl " suffix.
* 4. Bottom-right: modified by the " --br " suffix.
*/
.mfb-component--tl {
left: 0;
top: 0; }
.mfb-component--tr {
right: 0;
top: 0; }
.mfb-component--bl {
left: 0;
bottom: 0; }
.mfb-component--br {
right: 0;
bottom: 0; }
/*------------------------------------*\
#BUTTONS | Base
\*------------------------------------*/
.mfb-component__button--main, .mfb-component__button--child {
background-color: #75C7C3;
display: inline-block;
position: relative;
border: none;
border-radius: 50%;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.14), 0 4px 8px rgba(0, 0, 0, 0.28);
cursor: pointer;
outline: none;
padding: 0;
position: relative;
-webkit-user-drag: none;
color: #f1f1f1; }
/**
* This is the unordered list for the list items that contain
* the child buttons.
*
*/
.mfb-component__list {
list-style: none;
margin: 0;
padding: 0; }
.mfb-component__list > li {
display: block;
position: absolute;
top: 0;
right: 1px;
padding: 10px 0;
margin: -10px 0; }
/**
* These are the basic styles for all the icons inside the main button
*/
.mfb-component__icon, .mfb-component__main-icon--active,
.mfb-component__main-icon--resting, .mfb-component__child-icon {
position: absolute;
font-size: 18px;
text-align: center;
line-height: 56px;
width: 100%; }
.mfb-component__wrap {
padding: 25px;
margin: -25px; }
[data-mfb-toggle="hover"]:hover .mfb-component__icon, [data-mfb-toggle="hover"]:hover .mfb-component__main-icon--active,
[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--resting, [data-mfb-toggle="hover"]:hover .mfb-component__child-icon,
[data-mfb-state="open"] .mfb-component__icon,
[data-mfb-state="open"] .mfb-component__main-icon--active,
[data-mfb-state="open"] .mfb-component__main-icon--resting,
[data-mfb-state="open"] .mfb-component__child-icon {
-webkit-transform: scale(1) rotate(0deg);
transform: scale(1) rotate(0deg); }
/*------------------------------------*\
#BUTTONS | Modifiers
\*------------------------------------*/
.mfb-component__button--main {
height: 56px;
width: 56px;
z-index: 20; }
.mfb-component__button--child {
height: 56px;
width: 56px; }
.mfb-component__main-icon--active,
.mfb-component__main-icon--resting {
-webkit-transform: scale(1) rotate(360deg);
transform: scale(1) rotate(360deg);
-webkit-transition: -webkit-transform 150ms cubic-bezier(0.4, 0, 1, 1);
transition: transform 150ms cubic-bezier(0.4, 0, 1, 1); }
.mfb-component__child-icon,
.mfb-component__child-icon {
line-height: 56px;
font-size: 18px; }
.mfb-component__main-icon--active {
opacity: 0; }
[data-mfb-toggle="hover"]:hover .mfb-component__main-icon,
[data-mfb-state="open"] .mfb-component__main-icon {
-webkit-transform: scale(1) rotate(0deg);
transform: scale(1) rotate(0deg); }
[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--resting,
[data-mfb-state="open"] .mfb-component__main-icon--resting {
opacity: 0;
position: absolute !important; }
[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--active,
[data-mfb-state="open"] .mfb-component__main-icon--active {
opacity: 1; }
/*------------------------------------*\
#BUTTONS | Animations
\*------------------------------------*/
/**
* SLIDE IN + FADE
* When hovering the main button, the child buttons slide out from beneath
* the main button while transitioning from transparent to opaque.
*
*/
.mfb-component--tl.mfb-slidein .mfb-component__list li,
.mfb-component--tr.mfb-slidein .mfb-component__list li {
opacity: 0;
transition: all 0.5s; }
.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li, .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li,
.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li,
.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li {
opacity: 1; }
.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(70px);
transform: translateY(70px); }
.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(140px);
transform: translateY(140px); }
.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(210px);
transform: translateY(210px); }
.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(280px);
transform: translateY(280px); }
.mfb-component--bl.mfb-slidein .mfb-component__list li,
.mfb-component--br.mfb-slidein .mfb-component__list li {
opacity: 0;
transition: all 0.5s; }
.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li, .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li,
.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li,
.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li {
opacity: 1; }
.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(-70px);
transform: translateY(-70px); }
.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(-140px);
transform: translateY(-140px); }
.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(-210px);
transform: translateY(-210px); }
.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(-280px);
transform: translateY(-280px); }
/**
* SLIDE IN SPRING
* Same as slide-in but with a springy animation.
*
*/
.mfb-component--tl.mfb-slidein-spring .mfb-component__list li,
.mfb-component--tr.mfb-slidein-spring .mfb-component__list li {
opacity: 0;
transition: all 0.5s;
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); }
.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child(1) {
transition-delay: 0.05s; }
.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child(2) {
transition-delay: 0.1s; }
.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child(3) {
transition-delay: 0.15s; }
.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child(4) {
transition-delay: 0.2s; }
.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li, .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li,
.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li,
.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li {
opacity: 1; }
.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(1) {
transition-delay: 0.05s;
-webkit-transform: translateY(70px);
transform: translateY(70px); }
.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(2) {
transition-delay: 0.1s;
-webkit-transform: translateY(140px);
transform: translateY(140px); }
.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(3) {
transition-delay: 0.15s;
-webkit-transform: translateY(210px);
transform: translateY(210px); }
.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(4) {
transition-delay: 0.2s;
-webkit-transform: translateY(280px);
transform: translateY(280px); }
.mfb-component--bl.mfb-slidein-spring .mfb-component__list li,
.mfb-component--br.mfb-slidein-spring .mfb-component__list li {
opacity: 0;
transition: all 0.5s;
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); }
.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child(1) {
transition-delay: 0.05s; }
.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child(2) {
transition-delay: 0.1s; }
.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child(3) {
transition-delay: 0.15s; }
.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child(4) {
transition-delay: 0.2s; }
.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li, .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li,
.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li,
.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li {
opacity: 1; }
.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(1) {
transition-delay: 0.05s;
-webkit-transform: translateY(-70px);
transform: translateY(-70px); }
.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(2) {
transition-delay: 0.1s;
-webkit-transform: translateY(-140px);
transform: translateY(-140px); }
.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(3) {
transition-delay: 0.15s;
-webkit-transform: translateY(-210px);
transform: translateY(-210px); }
.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(4) {
transition-delay: 0.2s;
-webkit-transform: translateY(-280px);
transform: translateY(-280px); }
/**
* ZOOM-IN
* When hovering the main button, the child buttons grow
* from zero to normal size.
*
*/
.mfb-component--tl.mfb-zoomin .mfb-component__list li,
.mfb-component--tr.mfb-zoomin .mfb-component__list li {
-webkit-transform: scale(0);
transform: scale(0); }
.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(70px) scale(0);
transform: translateY(70px) scale(0);
transition: all 0.5s;
transition-delay: 0.15s; }
.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(140px) scale(0);
transform: translateY(140px) scale(0);
transition: all 0.5s;
transition-delay: 0.1s; }
.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(210px) scale(0);
transform: translateY(210px) scale(0);
transition: all 0.5s;
transition-delay: 0.05s; }
.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(280px) scale(0);
transform: translateY(280px) scale(0);
transition: all 0.5s;
transition-delay: 0s; }
.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(70px) scale(1);
transform: translateY(70px) scale(1);
transition-delay: 0.05s; }
.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(140px) scale(1);
transform: translateY(140px) scale(1);
transition-delay: 0.1s; }
.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(210px) scale(1);
transform: translateY(210px) scale(1);
transition-delay: 0.15s; }
.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(280px) scale(1);
transform: translateY(280px) scale(1);
transition-delay: 0.2s; }
.mfb-component--bl.mfb-zoomin .mfb-component__list li,
.mfb-component--br.mfb-zoomin .mfb-component__list li {
-webkit-transform: scale(0);
transform: scale(0); }
.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(-70px) scale(0);
transform: translateY(-70px) scale(0);
transition: all 0.5s;
transition-delay: 0.15s; }
.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(-140px) scale(0);
transform: translateY(-140px) scale(0);
transition: all 0.5s;
transition-delay: 0.1s; }
.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(-210px) scale(0);
transform: translateY(-210px) scale(0);
transition: all 0.5s;
transition-delay: 0.05s; }
.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(-280px) scale(0);
transform: translateY(-280px) scale(0);
transition: all 0.5s;
transition-delay: 0s; }
.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(-70px) scale(1);
transform: translateY(-70px) scale(1);
transition-delay: 0.05s; }
.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(-140px) scale(1);
transform: translateY(-140px) scale(1);
transition-delay: 0.1s; }
.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(-210px) scale(1);
transform: translateY(-210px) scale(1);
transition-delay: 0.15s; }
.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(-280px) scale(1);
transform: translateY(-280px) scale(1);
transition-delay: 0.2s; }
/**
* FOUNTAIN
* When hovering the main button the child buttons
* jump into view from outside the viewport
*/
.mfb-component--tl.mfb-fountain .mfb-component__list li,
.mfb-component--tr.mfb-fountain .mfb-component__list li {
-webkit-transform: scale(0);
transform: scale(0); }
.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(-70px) scale(0);
transform: translateY(-70px) scale(0);
transition: all 0.5s;
transition-delay: 0.15s; }
.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(-140px) scale(0);
transform: translateY(-140px) scale(0);
transition: all 0.5s;
transition-delay: 0.1s; }
.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(-210px) scale(0);
transform: translateY(-210px) scale(0);
transition: all 0.5s;
transition-delay: 0.05s; }
.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(-280px) scale(0);
transform: translateY(-280px) scale(0);
transition: all 0.5s;
transition-delay: 0s; }
.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1),
.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(70px) scale(1);
transform: translateY(70px) scale(1);
transition-delay: 0.05s; }
.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2),
.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(140px) scale(1);
transform: translateY(140px) scale(1);
transition-delay: 0.1s; }
.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3),
.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(210px) scale(1);
transform: translateY(210px) scale(1);
transition-delay: 0.15s; }
.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4),
.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(280px) scale(1);
transform: translateY(280px) scale(1);
transition-delay: 0.2s; }
.mfb-component--bl.mfb-fountain .mfb-component__list li,
.mfb-component--br.mfb-fountain .mfb-component__list li {
-webkit-transform: scale(0);
transform: scale(0); }
.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(70px) scale(0);
transform: translateY(70px) scale(0);
transition: all 0.5s;
transition-delay: 0.15s; }
.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(140px) scale(0);
transform: translateY(140px) scale(0);
transition: all 0.5s;
transition-delay: 0.1s; }
.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(210px) scale(0);
transform: translateY(210px) scale(0);
transition: all 0.5s;
transition-delay: 0.05s; }
.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(280px) scale(0);
transform: translateY(280px) scale(0);
transition: all 0.5s;
transition-delay: 0s; }
.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1),
.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(1) {
-webkit-transform: translateY(-70px) scale(1);
transform: translateY(-70px) scale(1);
transition-delay: 0.05s; }
.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2),
.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(2) {
-webkit-transform: translateY(-140px) scale(1);
transform: translateY(-140px) scale(1);
transition-delay: 0.1s; }
.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3),
.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(3) {
-webkit-transform: translateY(-210px) scale(1);
transform: translateY(-210px) scale(1);
transition-delay: 0.15s; }
.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4),
.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(4) {
-webkit-transform: translateY(-280px) scale(1);
transform: translateY(-280px) scale(1);
transition-delay: 0.2s; }
/*------------------------------------*\
#LABELS | base
\*------------------------------------*/
/**
* These are the labels associated to each button,
* exposed only when hovering the related button.
* They are called labels but are in fact data-attributes of
* each button (an anchor tag).
*/
[data-mfb-label]:after {
content: attr(data-mfb-label);
opacity: 0;
transition: all 0.5s;
background: rgba(0, 0, 0, 0.4);
padding: 4px 10px;
border-radius: 3px;
color: rgba(255, 255, 255, 0.8);
font-size: 14px;
font-weight: normal;
pointer-events: none;
line-height: normal;
position: absolute;
top: 50%;
margin-top: -11px;
transition: all 0.5s; }
[data-mfb-toggle="hover"] [data-mfb-label]:hover:after,
[data-mfb-state="open"] [data-mfb-label]:after {
content: attr(data-mfb-label);
opacity: 1;
transition: all 0.3s; }
/*------------------------------------*\
#LABELS | Modifiers
\*------------------------------------*/
.mfb-component--br [data-mfb-label]:after, .mfb-component--tr [data-mfb-label]:after {
content: attr(data-mfb-label);
right: 70px; }
.mfb-component--br .mfb-component__list [data-mfb-label]:after, .mfb-component--tr .mfb-component__list [data-mfb-label]:after {
content: attr(data-mfb-label);
right: 70px; }
.mfb-component--tl [data-mfb-label]:after, .mfb-component--bl [data-mfb-label]:after {
content: attr(data-mfb-label);
left: 70px; }
.mfb-component--tl .mfb-component__list [data-mfb-label]:after, .mfb-component--bl .mfb-component__list [data-mfb-label]:after {
content: attr(data-mfb-label);
left: 70px; }
/*------------------------------------*\
#DEVELOPMENT | In development
\*------------------------------------*/
/**
* This part is where unfinished code should stay.
* When a feature is ready(sh) move these styles to their proper place.
*/
/*------------------------------------*\
#DEVELOPMENT | Debuggers
\*------------------------------------*/
/**
* These are mainly helpers for development. They do not have to end up
* in production but it's handy to keep them when developing.
*/
/**
* Apply this class to the html tag when developing the slide-in button
*/
/*# sourceMappingURL=mfb.css.map */

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,22 @@
/**
* Open file manager and return selected files.
* Promise is never resolved if window is closed.
*
* @returns Promise<array> Array of selected files with properties:
* icon string
* is_file bool
* is_image bool
* name string
* thumb_url string|null
* time int
* url string
*/
window.filemanager = function filemanager() {
var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '/filemanager';
var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'FileManager';
var features = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'width=900,height=600';
return new Promise(function (resolve) {
window.open(url, target, features);
window.SetUrl = resolve;
});
};

View File

@@ -0,0 +1 @@
window.filemanager=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"/filemanager",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"FileManager",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"width=900,height=600";return new Promise(function(o){window.open(n,e,i),window.SetUrl=o})};

File diff suppressed because one or more lines are too long

View File

@@ -1,24 +0,0 @@
(function( $ ){
$.fn.filemanager = function(type, options) {
type = type || 'file';
this.on('click', function(e) {
var route_prefix = (options && options.prefix) ? options.prefix : '/laravel-filemanager';
localStorage.setItem('target_input', $(this).data('input'));
localStorage.setItem('target_preview', $(this).data('preview'));
window.open(route_prefix + '?type=' + type, 'FileManager', 'width=900,height=600');
window.SetUrl = function (url, file_path) {
//set the value of the desired input to image url
var target_input = $('#' + localStorage.getItem('target_input'));
target_input.val(file_path).trigger('change');
//set or change the preview image src
var target_preview = $('#' + localStorage.getItem('target_preview'));
target_preview.attr('src', url).trigger('change');
};
return false;
});
}
})(jQuery);

View File

@@ -1,98 +0,0 @@
/**
* Material floating button
* By: Nobita
* Repo and docs: https://github.com/nobitagit/material-floating-button
*
* License: MIT
*/
// build script hook - don't remove
;(function ( window, document, undefined ) {
'use strict';
/**
* Some defaults
*/
var clickOpt = 'click',
hoverOpt = 'hover',
toggleMethod = 'data-mfb-toggle',
menuState = 'data-mfb-state',
isOpen = 'open',
isClosed = 'closed',
mainButtonClass = 'mfb-component__button--main';
/**
* Internal references
*/
var elemsToClick,
elemsToHover,
mainButton,
target,
currentState;
/**
* For every menu we need to get the main button and attach the appropriate evt.
*/
function attachEvt( elems, evt ){
for( var i = 0, len = elems.length; i < len; i++ ){
mainButton = elems[i].querySelector('.' + mainButtonClass);
mainButton.addEventListener( evt , toggleButton, false);
}
}
/**
* Remove the hover option, set a click toggle and a default,
* initial state of 'closed' to menu that's been targeted.
*/
function replaceAttrs( elems ){
for( var i = 0, len = elems.length; i < len; i++ ){
elems[i].setAttribute( toggleMethod, clickOpt );
elems[i].setAttribute( menuState, isClosed );
}
}
function getElemsByToggleMethod( selector ){
return document.querySelectorAll('[' + toggleMethod + '="' + selector + '"]');
}
/**
* The open/close action is performed by toggling an attribute
* on the menu main element.
*
* First, check if the target is the menu itself. If it's a child
* keep walking up the tree until we found the main element
* where we can toggle the state.
*/
function toggleButton( evt ){
target = evt.target;
while ( target && !target.getAttribute( toggleMethod ) ){
target = target.parentNode;
if(!target) { return; }
}
currentState = target.getAttribute( menuState ) === isOpen ? isClosed : isOpen;
target.setAttribute(menuState, currentState);
}
/**
* On touch enabled devices we assume that no hover state is possible.
* So, we get the menu with hover action configured and we set it up
* in order to make it usable with tap/click.
**/
if ( window.Modernizr && Modernizr.touch ){
elemsToHover = getElemsByToggleMethod( hoverOpt );
replaceAttrs( elemsToHover );
}
elemsToClick = getElemsByToggleMethod( clickOpt );
attachEvt( elemsToClick, 'click' );
// build script hook - don't remove
})( window, document );

View File

@@ -1,32 +1,111 @@
var lfm_route = location.origin + location.pathname;
var show_list;
var sort_type = 'alphabetic';
var multi_selection_enabled = false;
var selected = [];
var items = [];
$.fn.fab = function (options) {
var menu = this;
menu.addClass('fab-wrapper');
var toggler = $('<a>')
.addClass('fab-button fab-toggle')
.append($('<i>').addClass('fas fa-plus'))
.click(function () {
menu.toggleClass('fab-expand');
});
menu.append(toggler);
options.buttons.forEach(function (button) {
toggler.before(
$('<a>').addClass('fab-button fab-action')
.attr('data-label', button.label)
.attr('id', button.attrs.id)
.append($('<i>').addClass(button.icon))
.click(function () {
menu.removeClass('fab-expand');
})
);
});
};
$(document).ready(function () {
bootbox.setDefaults({locale:lang['locale-bootbox']});
$('#fab').fab({
buttons: [
{
icon: 'fas fa-upload',
label: lang['nav-upload'],
attrs: {id: 'upload'}
},
{
icon: 'fas fa-folder',
label: lang['nav-new'],
attrs: {id: 'add-folder'}
}
]
});
actions.reverse().forEach(function (action) {
$('#nav-buttons > ul').prepend(
$('<li>').addClass('nav-item').append(
$('<a>').addClass('nav-link d-none')
.attr('data-action', action.name)
.attr('data-multiple', action.multiple)
.append($('<i>').addClass('fas fa-fw fa-' + action.icon))
.append($('<span>').text(action.label))
)
);
});
sortings.forEach(function (sort) {
$('#nav-buttons .dropdown-menu').append(
$('<a>').addClass('dropdown-item').attr('data-sortby', sort.by)
.append($('<i>').addClass('fas fa-fw fa-' + sort.icon))
.append($('<span>').text(sort.label))
.click(function() {
sort_type = sort.by;
loadItems();
})
);
});
loadFolders();
performLfmRequest('errors')
.done(function (data) {
var response = JSON.parse(data);
for (var i = 0; i < response.length; i++) {
.done(function (response) {
JSON.parse(response).forEach(function (message) {
$('#alerts').append(
$('<div>').addClass('alert alert-warning')
.append($('<i>').addClass('fa fa-exclamation-circle'))
.append(' ' + response[i])
.append($('<i>').addClass('fas fa-exclamation-circle'))
.append(' ' + message)
);
}
});
});
$(window).on('dragenter', function(){
$('#uploadModal').modal('show');
});
$(window).on('dragenter', function(){
$('#uploadModal').modal('show');
});
if (usingWysiwygEditor()) {
$('#multi_selection_toggle').hide();
}
});
// ======================
// == Navbar actions ==
// ======================
$('#nav-buttons a').click(function (e) {
e.preventDefault();
$('#multi_selection_toggle').click(function () {
multi_selection_enabled = !multi_selection_enabled;
$('#multi_selection_toggle i')
.toggleClass('fa-times', multi_selection_enabled)
.toggleClass('fa-check-double', !multi_selection_enabled);
if (!multi_selection_enabled) {
clearSelected();
}
});
$('#to-previous').click(function () {
@@ -35,72 +114,120 @@ $('#to-previous').click(function () {
goTo(previous_dir);
});
$('#add-folder').click(function () {
bootbox.prompt(lang['message-name'], function (result) {
if (result == null) return;
createFolder(result);
});
function toggleMobileTree(should_display) {
if (should_display === undefined) {
should_display = !$('#tree').hasClass('in');
}
$('#tree').toggleClass('in', should_display);
}
$('#show_tree').click(function (e) {
toggleMobileTree();
});
$('#upload').click(function () {
$('#main').click(function (e) {
if ($('#tree').hasClass('in')) {
toggleMobileTree(false);
}
});
$(document).on('click', '#add-folder', function () {
dialog(lang['message-name'], '', createFolder);
});
$(document).on('click', '#upload', function () {
$('#uploadModal').modal('show');
});
$('#upload-btn').click(function () {
$(this).html('')
.append($('<i>').addClass('fa fa-refresh fa-spin'))
.append(" " + lang['btn-uploading'])
.addClass('disabled');
$(document).on('click', '[data-display]', function() {
show_list = $(this).data('display');
loadItems();
});
function resetUploadForm() {
$('#uploadModal').modal('hide');
$('#upload-btn').html(lang['btn-upload']).removeClass('disabled');
$('input#upload').val('');
$(document).on('click', '[data-action]', function() {
window[$(this).data('action')]($(this).data('multiple') ? getSelectedItems() : getOneSelectedElement());
});
// ==========================
// == Multiple Selection ==
// ==========================
function toggleSelected (e) {
if (!multi_selection_enabled) {
selected = [];
}
$('#uploadForm').ajaxSubmit({
success: function (data, statusText, xhr, $form) {
resetUploadForm();
refreshFoldersAndItems(data);
displaySuccessMessage(data);
},
error: function (jqXHR, textStatus, errorThrown) {
displayErrorResponse(jqXHR);
resetUploadForm();
}
var sequence = $(e.target).closest('a').data('id');
var element_index = selected.indexOf(sequence);
if (element_index === -1) {
selected.push(sequence);
} else {
selected.splice(element_index, 1);
}
updateSelectedStyle();
}
function clearSelected () {
selected = [];
multi_selection_enabled = false;
updateSelectedStyle();
}
function updateSelectedStyle() {
items.forEach(function (item, index) {
$('[data-id=' + index + ']')
.find('.square')
.toggleClass('selected', selected.indexOf(index) > -1);
});
});
toggleActions();
}
$('#thumbnail-display').click(function () {
show_list = 0;
loadItems();
});
function getOneSelectedElement(orderOfItem) {
var index = orderOfItem !== undefined ? orderOfItem : selected[0];
return items[index];
}
$('#list-display').click(function () {
show_list = 1;
loadItems();
});
function getSelectedItems() {
return selected.reduce(function (arr_objects, id) {
arr_objects.push(getOneSelectedElement(id));
return arr_objects
}, []);
}
$('#list-sort-alphabetic').click(function() {
sort_type = 'alphabetic';
loadItems();
});
function toggleActions() {
var one_selected = selected.length === 1;
var many_selected = selected.length >= 1;
var only_image = getSelectedItems()
.filter(function (item) { return !item.is_image; })
.length === 0;
var only_file = getSelectedItems()
.filter(function (item) { return !item.is_file; })
.length === 0;
$('#list-sort-time').click(function() {
sort_type = 'time';
loadItems();
});
$('[data-action=use]').toggleClass('d-none', !(many_selected && only_file));
$('[data-action=rename]').toggleClass('d-none', !one_selected);
$('[data-action=preview]').toggleClass('d-none', !(many_selected && only_file));
$('[data-action=move]').toggleClass('d-none', !many_selected);
$('[data-action=download]').toggleClass('d-none', !(many_selected && only_file));
$('[data-action=resize]').toggleClass('d-none', !(one_selected && only_image));
$('[data-action=crop]').toggleClass('d-none', !(one_selected && only_image));
$('[data-action=trash]').toggleClass('d-none', !many_selected);
$('[data-action=open]').toggleClass('d-none', !one_selected || only_file);
$('#multi_selection_toggle').toggleClass('d-none', usingWysiwygEditor() || !many_selected);
$('#actions').toggleClass('d-none', selected.length === 0);
$('#fab').toggleClass('d-none', selected.length !== 0);
}
// ======================
// == Folder actions ==
// ======================
$(document).on('click', '.file-item', function (e) {
useFile($(this).data('id'));
});
$(document).on('click', '.folder-item', function (e) {
goTo($(this).data('id'));
$(document).on('click', '#tree a', function (e) {
goTo($(e.target).closest('a').data('path'));
toggleMobileTree(false);
});
function goTo(new_dir) {
@@ -109,28 +236,21 @@ function goTo(new_dir) {
}
function getPreviousDir() {
var ds = '/';
var working_dir = $('#working_dir').val();
var last_ds = working_dir.lastIndexOf(ds);
var previous_dir = working_dir.substring(0, last_ds);
return previous_dir;
}
function dir_starts_with(str) {
return $('#working_dir').val().indexOf(str) === 0;
return working_dir.substring(0, working_dir.lastIndexOf('/'));
}
function setOpenFolders() {
var folders = $('.folder-item');
for (var i = folders.length - 1; i >= 0; i--) {
$('#tree [data-path]').each(function (index, folder) {
// close folders that are not parent
if (! dir_starts_with($(folders[i]).data('id'))) {
$(folders[i]).children('i').removeClass('fa-folder-open').addClass('fa-folder');
} else {
$(folders[i]).children('i').removeClass('fa-folder').addClass('fa-folder-open');
}
}
var should_open = ($('#working_dir').val() + '/').startsWith($(folder).data('path') + '/');
$(folder).children('i')
.toggleClass('fa-folder-open', should_open)
.toggleClass('fa-folder', !should_open);
});
$('#tree .nav-item').removeClass('active');
$('#tree [data-path="' + $('#working_dir').val() + '"]').parent('.nav-item').addClass('active');
}
// ====================
@@ -148,6 +268,12 @@ function performLfmRequest(url, parameter, type) {
return $.ajax({
type: 'GET',
beforeSend: function(request) {
var token = getUrlParam('token');
if (token !== null) {
request.setRequestHeader("Authorization", 'Bearer ' + token);
}
},
dataType: type || 'text',
url: lfm_route + '/' + url,
data: data,
@@ -161,18 +287,6 @@ function displayErrorResponse(jqXHR) {
notify('<div style="max-height:50vh;overflow: scroll;">' + jqXHR.responseText + '</div>');
}
function displaySuccessMessage(data){
if(data == 'OK'){
var success = $('<div>').addClass('alert alert-success')
.append($('<i>').addClass('fa fa-check'))
.append(' File Uploaded Successfully.');
$('#alerts').append(success);
setTimeout(function () {
success.remove();
}, 2000);
}
}
var refreshFoldersAndItems = function (data) {
loadFolders();
if (data != 'OK') {
@@ -182,8 +296,10 @@ var refreshFoldersAndItems = function (data) {
};
var hideNavAndShowEditor = function (data) {
$('#nav-buttons > ul').addClass('hidden');
$('#nav-buttons > ul').addClass('d-none');
$('#content').html(data);
$('#pagination').removeClass('preserve_actions_space')
clearSelected();
}
function loadFolders() {
@@ -194,85 +310,349 @@ function loadFolders() {
});
}
function loadItems() {
$('#lfm-loader').show();
performLfmRequest('jsonitems', {show_list: show_list, sort_type: sort_type}, 'html')
.done(function (data) {
var response = JSON.parse(data);
$('#content').html(response.html);
$('#nav-buttons > ul').removeClass('hidden');
$('#working_dir').val(response.working_dir);
$('#current_dir').text(response.working_dir);
console.log('Current working_dir : ' + $('#working_dir').val());
if (getPreviousDir() == '') {
$('#to-previous').addClass('hide');
} else {
$('#to-previous').removeClass('hide');
function generatePaginationHTML(el, args) {
var template = '<li class="page-item"><\/li>';
var linkTemplate = '<a class="page-link"><\/a>';
var currentPage = args.currentPage;
var totalPage = args.totalPage;
var rangeStart = args.rangeStart;
var rangeEnd = args.rangeEnd;
var i;
// Disable page range, display all the pages
if (args.pageRange === null) {
for (i = 1; i <= totalPage; i++) {
var button = $(template)
.attr('data-num', i)
.append($(linkTemplate).html(i));
if (i == currentPage) {
button.addClass('active');
}
el.append(button);
}
return;
}
if (rangeStart <= 3) {
for (i = 1; i < rangeStart; i++) {
var button = $(template)
.attr('data-num', i)
.append($(linkTemplate).html(i));
if (i == currentPage) {
button.addClass('active');
}
el.append(button);
}
} else {
var button = $(template)
.attr('data-num', 1)
.append($(linkTemplate).html(1));
el.append(button);
var button = $(template)
.addClass('disabled')
.append($(linkTemplate).html('...'));
el.append(button);
}
for (i = rangeStart; i <= rangeEnd; i++) {
var button = $(template)
.attr('data-num', i)
.append($(linkTemplate).html(i));
if (i == currentPage) {
button.addClass('active');
}
el.append(button);
}
if (rangeEnd >= totalPage - 2) {
for (i = rangeEnd + 1; i <= totalPage; i++) {
var button = $(template)
.attr('data-num', i)
.append($(linkTemplate).html(i));
el.append(button);
}
} else {
var button = $(template)
.addClass('disabled')
.append($(linkTemplate).html('...'));
el.append(button);
var button = $(template)
.attr('data-num', totalPage)
.append($(linkTemplate).html(totalPage));
el.append(button);
}
}
function createPagination(paginationSetting) {
var el = $('<ul class="pagination" role="navigation"></ul>');
var currentPage = paginationSetting.current_page;
var pageRange = 5;
var totalPage = Math.ceil(paginationSetting.total / paginationSetting.per_page);
var rangeStart = currentPage - pageRange;
var rangeEnd = currentPage + pageRange;
if (rangeEnd > totalPage) {
rangeEnd = totalPage;
rangeStart = totalPage - pageRange * 2;
rangeStart = rangeStart < 1 ? 1 : rangeStart;
}
if (rangeStart <= 1) {
rangeStart = 1;
rangeEnd = Math.min(pageRange * 2 + 1, totalPage);
}
generatePaginationHTML(el, {
totalPage: totalPage,
currentPage: currentPage,
pageRange: pageRange,
rangeStart: rangeStart,
rangeEnd: rangeEnd
});
$('#pagination').append(el);
}
function loadItems(page) {
loading(true);
performLfmRequest('jsonitems', {show_list: show_list, sort_type: sort_type, page: page || 1}, 'html')
.done(function (data) {
selected = [];
var response = JSON.parse(data);
var working_dir = response.working_dir;
items = response.items;
var hasItems = items.length !== 0;
var hasPaginator = !!response.paginator;
$('#empty').toggleClass('d-none', hasItems);
$('#content').html('').removeAttr('class');
$('#pagination').html('').removeAttr('class');
if (hasItems) {
$('#content').addClass(response.display);
$('#pagination').addClass('preserve_actions_space');
items.forEach(function (item, index) {
var template = $('#item-template').clone()
.removeAttr('id class')
.attr('data-id', index)
.click(toggleSelected)
.dblclick(function (e) {
if (item.is_file) {
use(getSelectedItems());
} else {
goTo(item.url);
}
});
if (item.thumb_url) {
var image = $('<div>').css('background-image', 'url("' + item.thumb_url + '?timestamp=' + item.time + '")');
} else {
var icon = $('<div>').addClass('ico');
var image = $('<div>').addClass('mime-icon ico-' + item.icon).append(icon);
}
template.find('.square').append(image);
template.find('.item_name').text(item.name);
template.find('time').text((new Date(item.time * 1000)).toLocaleString());
$('#content').append(template);
});
}
if (hasPaginator) {
createPagination(response.paginator);
$('#pagination a').on('click', function(event) {
event.preventDefault();
loadItems($(this).closest('li')[0].getAttribute('data-num'));
return false;
});
}
$('#nav-buttons > ul').removeClass('d-none');
$('#working_dir').val(working_dir);
console.log('Current working_dir : ' + working_dir);
var breadcrumbs = [];
var validSegments = working_dir.split('/').filter(function (e) { return e; });
validSegments.forEach(function (segment, index) {
if (index === 0) {
// set root folder name as the first breadcrumb
breadcrumbs.push($("[data-path='/" + segment + "']").text());
} else {
breadcrumbs.push(segment);
}
});
$('#current_folder').text(breadcrumbs[breadcrumbs.length - 1]);
$('#breadcrumbs > ol').html('');
breadcrumbs.forEach(function (breadcrumb, index) {
var li = $('<li>').addClass('breadcrumb-item').text(breadcrumb);
if (index === breadcrumbs.length - 1) {
li.addClass('active').attr('aria-current', 'page');
} else {
li.click(function () {
// go to corresponding path
goTo('/' + validSegments.slice(0, 1 + index).join('/'));
});
}
$('#breadcrumbs > ol').append(li);
});
var atRootFolder = getPreviousDir() == '';
$('#to-previous').toggleClass('d-none invisible-lg', atRootFolder);
$('#show_tree').toggleClass('d-none', !atRootFolder).toggleClass('d-block', atRootFolder);
setOpenFolders();
})
.always(function(){
$('#lfm-loader').hide();
loading(false);
toggleActions();
});
}
function loading(show_loading) {
$('#loading').toggleClass('d-none', !show_loading);
}
function createFolder(folder_name) {
performLfmRequest('newfolder', {name: folder_name})
.done(refreshFoldersAndItems);
}
function rename(item_name) {
bootbox.prompt({
title: lang['message-rename'],
value: item_name,
callback: function (result) {
if (result == null) return;
performLfmRequest('rename', {
file: item_name,
new_name: result
}).done(refreshFoldersAndItems);
}
// ==================================
// == File Actions ==
// ==================================
function rename(item) {
dialog(lang['message-rename'], item.name, function (new_name) {
performLfmRequest('rename', {
file: item.name,
new_name: new_name
}).done(refreshFoldersAndItems);
});
}
function trash(item_name) {
bootbox.confirm(lang['message-delete'], function (result) {
if (result == true) {
performLfmRequest('delete', {items: item_name})
.done(refreshFoldersAndItems);
}
function trash(items) {
notify(lang['message-delete'], function () {
performLfmRequest('delete', {
items: items.map(function (item) { return item.name; })
}).done(refreshFoldersAndItems)
});
}
function cropImage(image_name) {
performLfmRequest('crop', {img: image_name})
function crop(item) {
performLfmRequest('crop', {img: item.name})
.done(hideNavAndShowEditor);
}
function resizeImage(image_name) {
performLfmRequest('resize', {img: image_name})
function resize(item) {
performLfmRequest('resize', {img: item.name})
.done(hideNavAndShowEditor);
}
function download(file_name) {
var data = defaultParameters();
data['file'] = file_name;
location.href = lfm_route + '/download?' + $.param(data);
function download(items) {
items.forEach(function (item, index) {
var data = defaultParameters();
data['file'] = item.name;
var token = getUrlParam('token');
if (token) {
data['token'] = token;
}
setTimeout(function () {
location.href = lfm_route + '/download?' + $.param(data);
}, index * 100);
});
}
// ==================================
// == Ckeditor, Bootbox, preview ==
// ==================================
function open(item) {
goTo(item.url);
}
function useFile(file_url) {
function preview(items) {
var carousel = $('#carouselTemplate').clone().attr('id', 'previewCarousel').removeClass('d-none');
var imageTemplate = carousel.find('.carousel-item').clone().removeClass('active');
var indicatorTemplate = carousel.find('.carousel-indicators > li').clone().removeClass('active');
carousel.children('.carousel-inner').html('');
carousel.children('.carousel-indicators').html('');
carousel.children('.carousel-indicators,.carousel-control-prev,.carousel-control-next').toggle(items.length > 1);
function getUrlParam(paramName) {
var reParam = new RegExp('(?:[\?&]|&)' + paramName + '=([^&]+)', 'i');
var match = window.location.search.match(reParam);
return ( match && match.length > 1 ) ? match[1] : null;
}
items.forEach(function (item, index) {
var carouselItem = imageTemplate.clone()
.addClass(index === 0 ? 'active' : '');
if (item.thumb_url) {
carouselItem.find('.carousel-image').css('background-image', 'url(\'' + item.url + '?timestamp=' + item.time + '\')');
} else {
carouselItem.find('.carousel-image').css('width', '50vh').append($('<div>').addClass('mime-icon ico-' + item.icon));
}
carouselItem.find('.carousel-label').attr('target', '_blank').attr('href', item.url)
.append(item.name)
.append($('<i class="fas fa-external-link-alt ml-2"></i>'));
carousel.children('.carousel-inner').append(carouselItem);
var carouselIndicator = indicatorTemplate.clone()
.addClass(index === 0 ? 'active' : '')
.attr('data-slide-to', index);
carousel.children('.carousel-indicators').append(carouselIndicator);
});
// carousel swipe control
var touchStartX = null;
carousel.on('touchstart', function (event) {
var e = event.originalEvent;
if (e.touches.length == 1) {
var touch = e.touches[0];
touchStartX = touch.pageX;
}
}).on('touchmove', function (event) {
var e = event.originalEvent;
if (touchStartX != null) {
var touchCurrentX = e.changedTouches[0].pageX;
if ((touchCurrentX - touchStartX) > 60) {
touchStartX = null;
carousel.carousel('prev');
} else if ((touchStartX - touchCurrentX) > 60) {
touchStartX = null;
carousel.carousel('next');
}
}
}).on('touchend', function () {
touchStartX = null;
});
// end carousel swipe control
notify(carousel);
}
function move(items) {
performLfmRequest('move', { items: items.map(function (item) { return item.name; }) })
.done(refreshFoldersAndItems);
}
function getUrlParam(paramName) {
var reParam = new RegExp('(?:[\?&]|&)' + paramName + '=([^&]+)', 'i');
var match = window.location.search.match(reParam);
return ( match && match.length > 1 ) ? match[1] : null;
}
function use(items) {
function useTinymce3(url) {
if (!usingTinymce3()) { return; }
var win = tinyMCEPopup.getWindowArg("window");
win.document.getElementById(tinyMCEPopup.getWindowArg("input")).value = url;
if (typeof(win.ImageDialog) != "undefined") {
@@ -289,8 +669,10 @@ function useFile(file_url) {
tinyMCEPopup.close();
}
function useTinymce4AndColorbox(url, field_name) {
parent.document.getElementById(field_name).value = url;
function useTinymce4AndColorbox(url) {
if (!usingTinymce4AndColorbox()) { return; }
parent.document.getElementById(getUrlParam('field_name')).value = url;
if(typeof parent.tinyMCE !== "undefined") {
parent.tinyMCE.activeEditor.windowManager.close();
@@ -300,7 +682,20 @@ function useFile(file_url) {
}
}
function useTinymce5(url){
if (!usingTinymce5()) { return; }
parent.postMessage({
mceAction: 'insert',
content: url
});
parent.postMessage({ mceAction: 'close' });
}
function useCkeditor3(url) {
if (!usingCkeditor3()) { return; }
if (window.opener) {
// Popup
window.opener.CKEDITOR.tools.callFunction(getUrlParam('CKEditorFuncNum'), url);
@@ -312,41 +707,82 @@ function useFile(file_url) {
}
function useFckeditor2(url) {
if (!usingFckeditor2()) { return; }
var p = url;
var w = data['Properties']['Width'];
var h = data['Properties']['Height'];
window.opener.SetUrl(p,w,h);
}
var url = file_url;
var field_name = getUrlParam('field_name');
var is_ckeditor = getUrlParam('CKEditor');
var is_fcke = typeof data != 'undefined' && data['Properties']['Width'] != '';
var file_path = url.replace(route_prefix, '');
var url = items[0].url;
var callback = getUrlParam('callback');
var useFileSucceeded = true;
if (window.opener || window.tinyMCEPopup || field_name || getUrlParam('CKEditorCleanUpFuncNum') || is_ckeditor) {
if (window.tinyMCEPopup) { // use TinyMCE > 3.0 integration method
useTinymce3(url);
} else if (field_name) { // tinymce 4 and colorbox
useTinymce4AndColorbox(url, field_name);
} else if(is_ckeditor) { // use CKEditor 3.0 + integration method
useCkeditor3(url);
} else if (is_fcke) { // use FCKEditor 2.0 integration method
useFckeditor2(url);
} else { // standalone button or other situations
window.opener.SetUrl(url, file_path);
}
if (usingWysiwygEditor()) {
useTinymce3(url);
useTinymce4AndColorbox(url);
useTinymce5(url);
useCkeditor3(url);
useFckeditor2(url);
} else if (callback && window[callback]) {
window[callback](getSelectedItems());
} else if (callback && parent[callback]) {
parent[callback](getSelectedItems());
} else if (window.opener) { // standalone button or other situations
window.opener.SetUrl(getSelectedItems());
} else {
useFileSucceeded = false;
}
if (useFileSucceeded) {
if (window.opener) {
window.close();
}
} else {
console.log('window.opener not found');
// No editor found, open/download file using browser's default method
window.open(url);
}
}
//end useFile
// ==================================
// == WYSIWYG Editors Check ==
// ==================================
function usingTinymce3() {
return !!window.tinyMCEPopup;
}
function usingTinymce4AndColorbox() {
return !!getUrlParam('field_name');
}
function usingTinymce5(){
return !!getUrlParam('editor');
}
function usingCkeditor3() {
return !!getUrlParam('CKEditor') || !!getUrlParam('CKEditorCleanUpFuncNum');
}
function usingFckeditor2() {
return window.opener && typeof data != 'undefined' && data['Properties']['Width'] != '';
}
function usingWysiwygEditor() {
return usingTinymce3() || usingTinymce4AndColorbox() || usingTinymce5() || usingCkeditor3() || usingFckeditor2();
}
// ==================================
// == Others ==
// ==================================
function defaultParameters() {
return {
working_dir: $('#working_dir').val(),
@@ -358,18 +794,19 @@ function notImp() {
notify('Not yet implemented!');
}
function notify(message) {
bootbox.alert(message);
function notify(body, callback) {
$('#notify').find('.btn-primary').toggle(callback !== undefined);
$('#notify').find('.btn-primary').unbind().click(callback);
$('#notify').modal('show').find('.modal-body').html(body);
}
function fileView(file_url, timestamp) {
bootbox.dialog({
title: lang['title-view'],
message: $('<img>')
.addClass('img img-responsive center-block')
.attr('src', file_url + '?timestamp=' + timestamp),
size: 'large',
onEscape: true,
backdrop: true
function dialog(title, value, callback) {
$('#dialog').find('input').val(value);
$('#dialog').on('shown.bs.modal', function () {
$('#dialog').find('input').focus();
});
}
$('#dialog').find('.btn-primary').unbind().click(function (e) {
callback($('#dialog').find('input').val());
});
$('#dialog').modal('show').find('.modal-title').text(title);
}

View File

@@ -0,0 +1,36 @@
(function( $ ){
$.fn.filemanager = function(type, options) {
type = type || 'file';
this.on('click', function(e) {
var route_prefix = (options && options.prefix) ? options.prefix : '/filemanager';
var target_input = $('#' + $(this).data('input'));
var target_preview = $('#' + $(this).data('preview'));
window.open(route_prefix + '?type=' + type, 'FileManager', 'width=900,height=600');
window.SetUrl = function (items) {
var file_path = items.map(function (item) {
return item.url;
}).join(',');
// set the value of the desired input to image url
target_input.val('').val(file_path).trigger('change');
// clear previous preview
target_preview.html('');
// set or change the preview image src
items.forEach(function (item) {
target_preview.append(
$('<img>').css('height', '5rem').attr('src', item.thumb_url)
);
});
// trigger change event
target_preview.trigger('change');
};
return false;
});
}
})(jQuery);

View File

@@ -6,9 +6,6 @@ use Intervention\Image\Facades\Image;
use UniSharp\LaravelFilemanager\Events\ImageIsCropping;
use UniSharp\LaravelFilemanager\Events\ImageWasCropped;
/**
* Class CropController.
*/
class CropController extends LfmController
{
/**
@@ -18,11 +15,11 @@ class CropController extends LfmController
*/
public function getCrop()
{
$working_dir = request('working_dir');
$img = parent::objectPresenter(parent::getCurrentPath(request('img')));
return view('laravel-filemanager::crop')
->with(compact('working_dir', 'img'));
->with([
'working_dir' => request('working_dir'),
'img' => $this->lfm->pretty(request('img'))
]);
}
/**
@@ -30,34 +27,27 @@ class CropController extends LfmController
*/
public function getCropimage($overWrite = true)
{
$dataX = request('dataX');
$dataY = request('dataY');
$dataHeight = request('dataHeight');
$dataWidth = request('dataWidth');
$image_path = parent::getCurrentPath(request('img'));
$image_name = request('img');
$image_path = $this->lfm->setName($image_name)->path('absolute');
$crop_path = $image_path;
if (! $overWrite) {
$fileParts = explode('.', request('img'));
$fileParts = explode('.', $image_name);
$fileParts[count($fileParts) - 2] = $fileParts[count($fileParts) - 2] . '_cropped_' . time();
$crop_path = parent::getCurrentPath(implode('.', $fileParts));
$crop_path = $this->lfm->setName(implode('.', $fileParts))->path('absolute');
}
event(new ImageIsCropping($image_path));
$crop_info = request()->only('dataWidth', 'dataHeight', 'dataX', 'dataY');
// crop image
Image::make($image_path)
->crop($dataWidth, $dataHeight, $dataX, $dataY)
->crop(...array_values($crop_info))
->save($crop_path);
if (config('lfm.should_create_thumbnails', true)) {
// create thumb folder
parent::createFolderByPath(parent::getThumbPath());
// make new thumbnail
Image::make($crop_path)
->fit(config('lfm.thumb_img_width', 200), config('lfm.thumb_img_height', 200))
->save(parent::getThumbPath(parent::getName($crop_path)));
}
// make new thumbnail
$this->lfm->generateThumbnail($image_name);
event(new ImageWasCropped($image_path));
}

View File

@@ -2,13 +2,14 @@
namespace UniSharp\LaravelFilemanager\Controllers;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use UniSharp\LaravelFilemanager\Events\FileIsDeleting;
use UniSharp\LaravelFilemanager\Events\FileWasDeleted;
use UniSharp\LaravelFilemanager\Events\FolderIsDeleting;
use UniSharp\LaravelFilemanager\Events\FolderWasDeleted;
use UniSharp\LaravelFilemanager\Events\ImageIsDeleting;
use UniSharp\LaravelFilemanager\Events\ImageWasDeleted;
/**
* Class CropController.
*/
class DeleteController extends LfmController
{
/**
@@ -18,39 +19,61 @@ class DeleteController extends LfmController
*/
public function getDelete()
{
$name_to_delete = request('items');
$item_names = request('items');
$errors = [];
$file_to_delete = parent::getCurrentPath($name_to_delete);
$thumb_to_delete = parent::getThumbPath($name_to_delete);
foreach ($item_names as $name_to_delete) {
$file = $this->lfm->setName($name_to_delete);
event(new ImageIsDeleting($file_to_delete));
if (is_null($name_to_delete)) {
return parent::error('folder-name');
}
if (! File::exists($file_to_delete)) {
return parent::error('folder-not-found', ['folder' => $file_to_delete]);
}
if (File::isDirectory($file_to_delete)) {
if (! parent::directoryIsEmpty($file_to_delete)) {
return parent::error('delete-folder');
if ($file->isDirectory()) {
event(new FolderIsDeleting($file->path('absolute')));
} else {
event(new FileIsDeleting($file->path('absolute')));
event(new ImageIsDeleting($file->path('absolute')));
}
File::deleteDirectory($file_to_delete);
if (!Storage::disk($this->helper->config('disk'))->exists($file->path('storage'))) {
abort(404);
}
return parent::$success_response;
$file_to_delete = $this->lfm->pretty($name_to_delete);
$file_path = $file_to_delete->path('absolute');
if (is_null($name_to_delete)) {
array_push($errors, parent::error('folder-name'));
continue;
}
if (! $this->lfm->setName($name_to_delete)->exists()) {
array_push($errors, parent::error('folder-not-found', ['folder' => $file_path]));
continue;
}
if ($this->lfm->setName($name_to_delete)->isDirectory()) {
if (! $this->lfm->setName($name_to_delete)->directoryIsEmpty()) {
array_push($errors, parent::error('delete-folder'));
continue;
}
$this->lfm->setName($name_to_delete)->delete();
event(new FolderWasDeleted($file_path));
} else {
if ($file_to_delete->isImage()) {
$this->lfm->setName($name_to_delete)->thumb()->delete();
}
$this->lfm->setName($name_to_delete)->delete();
event(new FileWasDeleted($file_path));
event(new ImageWasDeleted($file_path));
}
}
if (parent::fileIsImage($file_to_delete)) {
File::delete($thumb_to_delete);
if (count($errors) > 0) {
return $errors;
}
File::delete($file_to_delete);
event(new ImageWasDeleted($file_to_delete));
return parent::$success_response;
}
}

View File

@@ -2,14 +2,8 @@
namespace UniSharp\LaravelFilemanager\Controllers;
/**
* Class DemoController.
*/
class DemoController extends LfmController
{
/**
* @return mixed
*/
public function index()
{
return view('laravel-filemanager::demo');

View File

@@ -2,18 +2,18 @@
namespace UniSharp\LaravelFilemanager\Controllers;
/**
* Class DownloadController.
*/
use Illuminate\Support\Facades\Storage;
class DownloadController extends LfmController
{
/**
* Download a file.
*
* @return mixed
*/
public function getDownload()
{
return response()->download(parent::getCurrentPath(request('file')));
$file = $this->lfm->setName(request('file'));
if (!Storage::disk($this->helper->config('disk'))->exists($file->path('storage'))) {
abort(404);
}
return response()->download($file->path('absolute'));
}
}

View File

@@ -2,11 +2,9 @@
namespace UniSharp\LaravelFilemanager\Controllers;
use Illuminate\Support\Facades\File;
use UniSharp\LaravelFilemanager\Events\FolderIsCreating;
use UniSharp\LaravelFilemanager\Events\FolderWasCreated;
/**
* Class FolderController.
*/
class FolderController extends LfmController
{
/**
@@ -16,35 +14,23 @@ class FolderController extends LfmController
*/
public function getFolders()
{
$folder_types = [];
$root_folders = [];
if (parent::allowMultiUser()) {
$folder_types['user'] = 'root';
}
if (parent::allowShareFolder()) {
$folder_types['share'] = 'shares';
}
foreach ($folder_types as $folder_type => $lang_key) {
$root_folder_path = parent::getRootFolderPath($folder_type);
$children = parent::getDirectories($root_folder_path);
usort($children, function ($a, $b) {
return strcmp($a->name, $b->name);
});
array_push($root_folders, (object) [
'name' => trans('laravel-filemanager::lfm.title-' . $lang_key),
'path' => parent::getInternalPath($root_folder_path),
'children' => $children,
'has_next' => ! ($lang_key == end($folder_types)),
]);
}
$folder_types = array_filter(['user', 'share'], function ($type) {
return $this->helper->allowFolderType($type);
});
return view('laravel-filemanager::tree')
->with(compact('root_folders'));
->with([
'root_folders' => array_map(function ($type) use ($folder_types) {
$path = $this->lfm->dir($this->helper->getRootFolder($type));
return (object) [
'name' => trans('laravel-filemanager::lfm.title-' . $type),
'url' => $path->path('working_dir'),
'children' => $path->folders(),
'has_next' => ! ($type == end($folder_types)),
];
}, $folder_types),
]);
}
/**
@@ -54,22 +40,28 @@ class FolderController extends LfmController
*/
public function getAddfolder()
{
$folder_name = parent::translateFromUtf8(trim(request('name')));
$path = parent::getCurrentPath($folder_name);
$folder_name = $this->helper->input('name');
if (empty($folder_name)) {
return parent::error('folder-name');
$new_path = $this->lfm->setName($folder_name)->path('absolute');
event(new FolderIsCreating($new_path));
try {
if ($folder_name === null || $folder_name == '') {
return $this->helper->error('folder-name');
} elseif ($this->lfm->setName($folder_name)->exists()) {
return $this->helper->error('folder-exist');
} elseif (config('lfm.alphanumeric_directory') && preg_match('/[^\w-]/i', $folder_name)) {
return $this->helper->error('folder-alnum');
} else {
$this->lfm->setName($folder_name)->createFolder();
}
} catch (\Exception $e) {
return $e->getMessage();
}
if (File::exists($path)) {
return parent::error('folder-exist');
}
event(new FolderWasCreated($new_path));
if (config('lfm.alphanumeric_directory') && preg_match('/[^\w-]/i', $folder_name)) {
return parent::error('folder-alnum');
}
parent::createFolderByPath($path);
return parent::$success_response;
}
}

View File

@@ -2,9 +2,12 @@
namespace UniSharp\LaravelFilemanager\Controllers;
/**
* Class ItemsController.
*/
use Illuminate\Support\Facades\Storage;
use UniSharp\LaravelFilemanager\Events\FileIsMoving;
use UniSharp\LaravelFilemanager\Events\FileWasMoving;
use UniSharp\LaravelFilemanager\Events\FolderIsMoving;
use UniSharp\LaravelFilemanager\Events\FolderWasMoving;
class ItemsController extends LfmController
{
/**
@@ -14,47 +17,90 @@ class ItemsController extends LfmController
*/
public function getItems()
{
$path = parent::getCurrentPath();
$sort_type = request('sort_type');
$currentPage = self::getCurrentPageFromRequest();
$files = parent::sortFilesAndDirectories(parent::getFilesWithInfo($path), $sort_type);
$directories = parent::sortFilesAndDirectories(parent::getDirectories($path), $sort_type);
$perPage = $this->helper->getPaginationPerPage();
$items = array_merge($this->lfm->folders(), $this->lfm->files());
return [
'html' => (string) view($this->getView())->with([
'files' => $files,
'directories' => $directories,
'items' => array_merge($directories, $files),
]),
'working_dir' => parent::getInternalPath($path),
'items' => array_map(function ($item) {
return $item->fill()->attributes;
}, array_slice($items, ($currentPage - 1) * $perPage, $perPage)),
'paginator' => [
'current_page' => $currentPage,
'total' => count($items),
'per_page' => $perPage,
],
'display' => $this->helper->getDisplayMode(),
'working_dir' => $this->lfm->path('working_dir'),
];
}
private function getView()
public function move()
{
$view_type = request('show_list');
$items = request('items');
$folder_types = array_filter(['user', 'share'], function ($type) {
return $this->helper->allowFolderType($type);
});
return view('laravel-filemanager::move')
->with([
'root_folders' => array_map(function ($type) use ($folder_types) {
$path = $this->lfm->dir($this->helper->getRootFolder($type));
if (null === $view_type) {
return $this->composeViewName($this->getStartupViewFromConfig());
}
$view_mapping = [
'0' => 'grid',
'1' => 'list'
];
return $this->composeViewName($view_mapping[$view_type]);
return (object) [
'name' => trans('laravel-filemanager::lfm.title-' . $type),
'url' => $path->path('working_dir'),
'children' => $path->folders(),
'has_next' => ! ($type == end($folder_types)),
];
}, $folder_types),
])
->with('items', $items);
}
private function composeViewName($view_type = 'grid')
public function domove()
{
return "laravel-filemanager::$view_type-view";
$target = $this->helper->input('goToFolder');
$items = $this->helper->input('items');
foreach ($items as $item) {
$old_file = $this->lfm->pretty($item);
$is_directory = $old_file->isDirectory();
$file = $this->lfm->setName($item);
if (!Storage::disk($this->helper->config('disk'))->exists($file->path('storage'))) {
abort(404);
}
$old_path = $old_file->path();
if ($old_file->hasThumb()) {
$new_file = $this->lfm->setName($item)->thumb()->dir($target);
if ($is_directory) {
event(new FolderIsMoving($old_file->path(), $new_file->path()));
} else {
event(new FileIsMoving($old_file->path(), $new_file->path()));
}
$this->lfm->setName($item)->thumb()->move($new_file);
}
$new_file = $this->lfm->setName($item)->dir($target);
$this->lfm->setName($item)->move($new_file);
if ($is_directory) {
event(new FolderWasMoving($old_path, $new_file->path()));
} else {
event(new FileWasMoving($old_path, $new_file->path()));
}
};
return parent::$success_response;
}
private function getStartupViewFromConfig($default = 'grid')
private static function getCurrentPageFromRequest()
{
$type_key = parent::currentLfmType();
$startup_view = config('lfm.' . $type_key . 's_startup_view', $default);
return $startup_view;
$currentPage = (int) request()->get('page', 1);
$currentPage = $currentPage < 1 ? 1 : $currentPage;
return $currentPage;
}
}

View File

@@ -2,15 +2,11 @@
namespace UniSharp\LaravelFilemanager\Controllers;
use UniSharp\LaravelFilemanager\Traits\LfmHelpers;
use UniSharp\LaravelFilemanager\Lfm;
use UniSharp\LaravelFilemanager\LfmPath;
/**
* Class LfmController.
*/
class LfmController extends Controller
{
use LfmHelpers;
protected static $success_response = 'OK';
public function __construct()
@@ -18,6 +14,20 @@ class LfmController extends Controller
$this->applyIniOverrides();
}
/**
* Set up needed functions.
*
* @return object|null
*/
public function __get($var_name)
{
if ($var_name === 'lfm') {
return app(LfmPath::class);
} elseif ($var_name === 'helper') {
return app(Lfm::class);
}
}
/**
* Show the filemanager.
*
@@ -25,9 +35,15 @@ class LfmController extends Controller
*/
public function show()
{
return view('laravel-filemanager::index');
return view('laravel-filemanager::index')
->withHelper($this->helper);
}
/**
* Check if any extension or config is missing.
*
* @return array
*/
public function getErrors()
{
$arr_errors = [];
@@ -36,14 +52,42 @@ class LfmController extends Controller
array_push($arr_errors, trans('laravel-filemanager::lfm.message-extension_not_found'));
}
$type_key = $this->currentLfmType();
$mine_config = 'lfm.valid_' . $type_key . '_mimetypes';
$config_error = null;
if (! extension_loaded('exif')) {
array_push($arr_errors, 'EXIF extension not found.');
}
if (! is_array(config($mine_config))) {
array_push($arr_errors, 'Config : ' . $mine_config . ' is not a valid array.');
if (! extension_loaded('fileinfo')) {
array_push($arr_errors, 'Fileinfo extension not found.');
}
$mine_config_key = 'lfm.folder_categories.'
. $this->helper->currentLfmType()
. '.valid_mime';
if (! is_array(config($mine_config_key))) {
array_push($arr_errors, 'Config : ' . $mine_config_key . ' is not a valid array.');
}
return $arr_errors;
}
/**
* Overrides settings in php.ini.
*
* @return null
*/
public function applyIniOverrides()
{
$overrides = config('lfm.php_ini_overrides', []);
if ($overrides && is_array($overrides) && count($overrides) === 0) {
return;
}
foreach ($overrides as $key => $value) {
if ($value && $value != 'false') {
ini_set($key, $value);
}
}
}
}

View File

@@ -2,64 +2,19 @@
namespace UniSharp\LaravelFilemanager\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
/**
* Class RedirectController.
*/
class RedirectController extends LfmController
{
private $file_path;
public function __construct()
public function showFile($file_path)
{
$delimiter = config('lfm.url_prefix', config('lfm.prefix')). '/';
$url = urldecode(request()->url());
$external_path = substr($url, strpos($url, $delimiter) + strlen($delimiter));
$storage = Storage::disk($this->helper->config('disk'));
$this->file_path = base_path(config('lfm.base_directory', 'public') . '/' . $external_path);
}
/**
* Get image from custom directory by route.
*
* @param string $image_path
* @return string
*/
public function getImage($base_path, $image_name)
{
return $this->responseImageOrFile();
}
/**
* Get file from custom directory by route.
*
* @param string $file_name
* @return string
*/
public function getFile(Request $request, $base_path, $file_name)
{
$request->request->add(['type' => 'Files']);
return $this->responseImageOrFile();
}
private function responseImageOrFile()
{
$file_path = $this->file_path;
if (! File::exists($file_path)) {
if (! $storage->exists($file_path)) {
abort(404);
}
$file = File::get($file_path);
$type = parent::getFileType($file_path);
$response = Response::make($file);
$response->header('Content-Type', $type);
return $response;
return response($storage->get($file_path))
->header('Content-Type', $storage->mimeType($file_path));
}
}

View File

@@ -2,86 +2,79 @@
namespace UniSharp\LaravelFilemanager\Controllers;
use Illuminate\Support\Facades\File;
use UniSharp\LaravelFilemanager\Events\ImageIsRenaming;
use UniSharp\LaravelFilemanager\Events\ImageWasRenamed;
use Illuminate\Support\Facades\Storage;
use UniSharp\LaravelFilemanager\Events\FolderIsRenaming;
use UniSharp\LaravelFilemanager\Events\FolderWasRenamed;
use UniSharp\LaravelFilemanager\Events\FileIsRenaming;
use UniSharp\LaravelFilemanager\Events\FileWasRenamed;
use UniSharp\LaravelFilemanager\Events\ImageIsRenaming;
use UniSharp\LaravelFilemanager\Events\ImageWasRenamed;
/**
* Class RenameController.
*/
class RenameController extends LfmController
{
/**
* @return string
*/
public function getRename()
{
$old_name = parent::translateFromUtf8(request('file'));
$new_name = parent::translateFromUtf8(trim(request('new_name')));
$old_name = $this->helper->input('file');
$new_name = $this->helper->input('new_name');
$old_file = parent::getCurrentPath($old_name);
if (File::isDirectory($old_file)) {
return $this->renameDirectory($old_name, $new_name);
} else {
return $this->renameFile($old_name, $new_name);
$file = $this->lfm->setName($old_name);
if (!Storage::disk($this->helper->config('disk'))->exists($file->path('storage'))) {
abort(404);
}
}
protected function renameDirectory($old_name, $new_name)
{
$old_file = $this->lfm->pretty($old_name);
$is_directory = $file->isDirectory();
if (empty($new_name)) {
return parent::error('folder-name');
if ($is_directory) {
return parent::error('folder-name');
} else {
return parent::error('file-name');
}
}
$old_file = parent::getCurrentPath($old_name);
$new_file = parent::getCurrentPath($new_name);
event(new FolderIsRenaming($old_file, $new_file));
if (config('lfm.alphanumeric_directory') && preg_match('/[^\w-]/i', $new_name)) {
if ($is_directory && config('lfm.alphanumeric_directory') && preg_match('/[^\w-]/i', $new_name)) {
return parent::error('folder-alnum');
}
if (File::exists($new_file)) {
return parent::error('rename');
}
File::move($old_file, $new_file);
event(new FolderWasRenamed($old_file, $new_file));
return parent::$success_response;
}
protected function renameFile($old_name, $new_name)
{
if (empty($new_name)) {
return parent::error('file-name');
}
$old_file = parent::getCurrentPath($old_name);
$extension = File::extension($old_file);
$new_file = parent::getCurrentPath(basename($new_name, ".$extension") . ".$extension");
if (config('lfm.alphanumeric_filename') && preg_match('/[^\w-.]/i', $new_name)) {
} elseif (config('lfm.alphanumeric_filename') && preg_match('/[^.\w-]/i', $new_name)) {
return parent::error('file-alnum');
}
// TODO Should be "FileIsRenaming"
event(new ImageIsRenaming($old_file, $new_file));
if (File::exists($new_file)) {
} elseif ($this->lfm->setName($new_name)->exists()) {
return parent::error('rename');
}
if (parent::fileIsImage($old_file) && File::exists(parent::getThumbPath($old_name))) {
File::move(parent::getThumbPath($old_name), parent::getThumbPath($new_name));
if (! $is_directory) {
$extension = $old_file->extension();
if ($extension) {
$new_name = str_replace('.' . $extension, '', $new_name) . '.' . $extension;
}
}
File::move($old_file, $new_file);
// TODO Should be "FileWasRenamed"
event(new ImageWasRenamed($old_file, $new_file));
$new_path = $this->lfm->setName($new_name)->path('absolute');
if ($is_directory) {
event(new FolderIsRenaming($old_file->path(), $new_path));
} else {
event(new FileIsRenaming($old_file->path(), $new_path));
event(new ImageIsRenaming($old_file->path(), $new_path));
}
$old_path = $old_file->path();
if ($old_file->hasThumb()) {
$this->lfm->setName($old_name)->thumb()
->move($this->lfm->setName($new_name)->thumb());
}
$this->lfm->setName($old_name)
->move($this->lfm->setName($new_name));
if ($is_directory) {
event(new FolderWasRenamed($old_path, $new_path));
} else {
event(new FileWasRenamed($old_path, $new_path));
event(new ImageWasRenamed($old_path, $new_path));
}
return parent::$success_response;
}

View File

@@ -6,9 +6,6 @@ use Intervention\Image\Facades\Image;
use UniSharp\LaravelFilemanager\Events\ImageIsResizing;
use UniSharp\LaravelFilemanager\Events\ImageWasResized;
/**
* Class ResizeController.
*/
class ResizeController extends LfmController
{
/**
@@ -21,7 +18,7 @@ class ResizeController extends LfmController
$ratio = 1.0;
$image = request('img');
$original_image = Image::make(parent::getCurrentPath($image));
$original_image = Image::make($this->lfm->setName($image)->path('absolute'));
$original_width = $original_image->width();
$original_height = $original_image->height();
@@ -46,7 +43,7 @@ class ResizeController extends LfmController
}
return view('laravel-filemanager::resize')
->with('img', parent::objectPresenter(parent::getCurrentPath($image)))
->with('img', $this->lfm->pretty($image))
->with('height', number_format($height, 0))
->with('width', $width)
->with('original_height', $original_height)
@@ -57,14 +54,10 @@ class ResizeController extends LfmController
public function performResize()
{
$dataX = request('dataX');
$dataY = request('dataY');
$height = request('dataHeight');
$width = request('dataWidth');
$image_path = parent::getCurrentPath(request('img'));
$image_path = $this->lfm->setName(request('img'))->path('absolute');
event(new ImageIsResizing($image_path));
Image::make($image_path)->resize($width, $height)->save();
Image::make($image_path)->resize(request('dataWidth'), request('dataHeight'))->save();
event(new ImageWasResized($image_path));
return parent::$success_response;

View File

@@ -2,16 +2,10 @@
namespace UniSharp\LaravelFilemanager\Controllers;
use Illuminate\Support\Facades\File;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Intervention\Image\Facades\Image;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use UniSharp\LaravelFilemanager\Events\ImageIsUploading;
use UniSharp\LaravelFilemanager\Events\ImageWasUploaded;
use UniSharp\LaravelFilemanager\Lfm;
/**
* Class UploadController.
*/
class UploadController extends LfmController
{
protected $errors;
@@ -26,211 +20,47 @@ class UploadController extends LfmController
* Upload files
*
* @param void
* @return string
*
* @return JsonResponse
*/
public function upload()
{
$files = request()->file('upload');
$uploaded_files = request()->file('upload');
$error_bag = [];
$new_filename = null;
// single file
if (!is_array($files)) {
$file = $files;
if (!$this->fileIsValid($file)) {
return $this->errors;
foreach (is_array($uploaded_files) ? $uploaded_files : [$uploaded_files] as $file) {
try {
$this->lfm->validateUploadedFile($file);
$new_filename = $this->lfm->upload($file);
} catch (\Exception $e) {
Log::error($e->getMessage(), [
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString()
]);
array_push($error_bag, $e->getMessage());
}
$filename = $this->proceedSingleUpload($file);
if ($filename === false) {
return $this->errors;
}
// upload via ckeditor 'Upload' tab
return $this->useFile($filename);
}
// Multiple files
foreach ($files as $file) {
if (!$this->fileIsValid($file)) {
continue;
}
$this->proceedSingleUpload($file);
}
return count($this->errors) > 0 ? $this->errors : parent::$success_response;
}
private function proceedSingleUpload($file)
{
$new_filename = $this->getNewName($file);
$new_file_path = parent::getCurrentPath($new_filename);
event(new ImageIsUploading($new_file_path));
try {
if (parent::fileIsImage($file) && !in_array($file->getMimeType(), ['image/gif', 'image/svg+xml'])) {
// Handle image rotation
Image::make($file->getRealPath())
->orientate() //Apply orientation from exif data
->save($new_file_path);
// Generate a thumbnail
if (parent::imageShouldHaveThumb($file)) {
$this->makeThumb($new_filename);
}
if (is_array($uploaded_files)) {
$response = count($error_bag) > 0 ? $error_bag : parent::$success_response;
} else { // upload via ckeditor5 expects json responses
if (is_null($new_filename)) {
$response = [
'error' => [ 'message' => $error_bag[0] ]
];
} else {
// Create (move) the file
File::move($file->getRealPath(), $new_file_path);
}
if (config('lfm.should_change_file_mode', true)) {
chmod($new_file_path, config('lfm.create_file_mode', 0644));
}
} catch (\Exception $e) {
array_push($this->errors, parent::error('invalid'));
$url = $this->lfm->setName($new_filename)->url();
Log::error($e->getMessage(), [
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString()
]);
return false;
}
// TODO should be "FileWasUploaded"
event(new ImageWasUploaded(realpath($new_file_path)));
return $new_filename;
}
private function fileIsValid($file)
{
if (empty($file)) {
array_push($this->errors, parent::error('file-empty'));
return false;
}
if (! $file instanceof UploadedFile) {
array_push($this->errors, parent::error('instance'));
return false;
}
if ($file->getError() == UPLOAD_ERR_INI_SIZE) {
$max_size = ini_get('upload_max_filesize');
array_push($this->errors, parent::error('file-size', ['max' => $max_size]));
return false;
}
if ($file->getError() != UPLOAD_ERR_OK) {
$msg = 'File failed to upload. Error code: ' . $file->getError();
array_push($this->errors, $msg);
return false;
}
$new_filename = $this->getNewName($file);
if (File::exists(parent::getCurrentPath($new_filename))) {
array_push($this->errors, parent::error('file-exist'));
return false;
}
$mimetype = $file->getMimeType();
// Bytes to KB
$file_size = $file->getSize() / 1024;
$type_key = parent::currentLfmType();
if (config('lfm.should_validate_mime', false)) {
$mine_config = 'lfm.valid_' . $type_key . '_mimetypes';
$valid_mimetypes = config($mine_config, []);
if (false === in_array($mimetype, $valid_mimetypes)) {
array_push($this->errors, parent::error('mime') . $mimetype);
return false;
$response = [
'url' => $url,
'uploaded' => $url
];
}
}
if (config('lfm.should_validate_size', false)) {
$max_size = config('lfm.max_' . $type_key . '_size', 0);
if ($file_size > $max_size) {
array_push($this->errors, parent::error('size'));
return false;
}
}
return true;
}
protected function replaceInsecureSuffix($name)
{
return preg_replace("/\.php$/i", '', $name);
}
private function getNewName($file)
{
$new_filename = parent::translateFromUtf8(trim($this->pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME)));
if (config('lfm.rename_file') === true) {
$new_filename = uniqid();
} elseif (config('lfm.alphanumeric_filename') === true) {
$new_filename = preg_replace('/[^A-Za-z0-9\-\']/', '_', $new_filename);
}
return $new_filename . $this->replaceInsecureSuffix('.' . $file->getClientOriginalExtension());
}
private function makeThumb($new_filename)
{
// create thumb folder
parent::createFolderByPath(parent::getThumbPath());
// create thumb image
Image::make(parent::getCurrentPath($new_filename))
->fit(config('lfm.thumb_img_width', 200), config('lfm.thumb_img_height', 200))
->save(parent::getThumbPath($new_filename));
}
private function useFile($new_filename)
{
$file = parent::getFileUrl($new_filename);
$responseType = request()->input('responseType');
if ($responseType && $responseType == 'json') {
return [
"uploaded" => 1,
"fileName" => $new_filename,
"url" => $file,
];
}
return "<script type='text/javascript'>
function getUrlParam(paramName) {
var reParam = new RegExp('(?:[\?&]|&)' + paramName + '=([^&]+)', 'i');
var match = window.location.search.match(reParam);
return ( match && match.length > 1 ) ? match[1] : null;
}
var funcNum = getUrlParam('CKEditorFuncNum');
var par = window.parent,
op = window.opener,
o = (par && par.CKEDITOR) ? par : ((op && op.CKEDITOR) ? op : false);
if (op) window.close();
if (o !== false) o.CKEDITOR.tools.callFunction(funcNum, '$file');
</script>";
}
private function pathinfo($path, $options = null)
{
$path = urlencode($path);
$parts = is_null($options) ? pathinfo($path) : pathinfo($path, $options);
if (is_array($parts)) {
foreach ($parts as $field => $value) {
$parts[$field] = urldecode($value);
}
} else {
$parts = urldecode($parts);
}
return $parts;
return response()->json($response);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FileIsDeleting
{
private $path;
public function __construct($path)
{
$this->path = $path;
}
/**
* @return string
*/
public function path()
{
return $this->path;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FileIsMoving
{
private $old_path;
private $new_path;
public function __construct($old_path, $new_path)
{
$this->old_path = $old_path;
$this->new_path = $new_path;
}
/**
* @return string
*/
public function oldPath()
{
return $this->old_path;
}
public function newPath()
{
return $this->new_path;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FileIsRenaming
{
private $old_path;
private $new_path;
public function __construct($old_path, $new_path)
{
$this->old_path = $old_path;
$this->new_path = $new_path;
}
/**
* @return string
*/
public function oldPath()
{
return $this->old_path;
}
public function newPath()
{
return $this->new_path;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FileIsUploading
{
private $path;
public function __construct($path)
{
$this->path = $path;
}
/**
* @return string
*/
public function path()
{
return $this->path;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FileWasDeleted
{
private $path;
public function __construct($path)
{
$this->path = $path;
}
/**
* @return string
*/
public function path()
{
return $this->path;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FileWasMoving
{
private $old_path;
private $new_path;
public function __construct($old_path, $new_path)
{
$this->old_path = $old_path;
$this->new_path = $new_path;
}
/**
* @return string
*/
public function oldPath()
{
return $this->old_path;
}
public function newPath()
{
return $this->new_path;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FileWasRenamed
{
private $old_path;
private $new_path;
public function __construct($old_path, $new_path)
{
$this->old_path = $old_path;
$this->new_path = $new_path;
}
/**
* @return string
*/
public function oldPath()
{
return $this->old_path;
}
public function newPath()
{
return $this->new_path;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FileWasUploaded
{
private $path;
public function __construct($path)
{
$this->path = $path;
}
/**
* @return string
*/
public function path()
{
return $this->path;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FolderIsCreating
{
private $path;
public function __construct($path)
{
$this->path = $path;
}
/**
* @return string
*/
public function path()
{
return $this->path;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FolderIsDeleting
{
private $path;
public function __construct($path)
{
$this->path = $path;
}
/**
* @return string
*/
public function path()
{
return $this->path;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FolderIsMoving
{
private $old_path;
private $new_path;
public function __construct($old_path, $new_path)
{
$this->old_path = $old_path;
$this->new_path = $new_path;
}
/**
* @return string
*/
public function oldPath()
{
return $this->old_path;
}
public function newPath()
{
return $this->new_path;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FolderWasCreated
{
private $path;
public function __construct($path)
{
$this->path = $path;
}
/**
* @return string
*/
public function path()
{
return $this->path;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FolderWasDeleted
{
private $path;
public function __construct($path)
{
$this->path = $path;
}
/**
* @return string
*/
public function path()
{
return $this->path;
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace UniSharp\LaravelFilemanager\Events;
class FolderWasMoving
{
private $old_path;
private $new_path;
public function __construct($old_path, $new_path)
{
$this->old_path = $old_path;
$this->new_path = $new_path;
}
/**
* @return string
*/
public function oldPath()
{
return $this->old_path;
}
public function newPath()
{
return $this->new_path;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace UniSharp\LaravelFilemanager\Exceptions;
class DuplicateFileNameException extends \Exception
{
public function __construct()
{
$this->message = trans('laravel-filemanager::lfm.error-file-exist');
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace UniSharp\LaravelFilemanager\Exceptions;
class EmptyFileException extends \Exception
{
public function __construct()
{
$this->message = trans('laravel-filemanager::lfm.error-file-empty');
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace UniSharp\LaravelFilemanager\Exceptions;
class ExcutableFileException extends \Exception
{
public function __construct()
{
$this->message = 'Invalid file detected';
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace UniSharp\LaravelFilemanager\Exceptions;
class FileFailedToUploadException extends \Exception
{
public function __construct($error_code)
{
$this->message = 'File failed to upload. Error code: ' . $error_code;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace UniSharp\LaravelFilemanager\Exceptions;
class FileSizeExceedConfigurationMaximumException extends \Exception
{
public function __construct($file_size)
{
$this->message = trans('laravel-filemanager::lfm.error-size') . $file_size;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace UniSharp\LaravelFilemanager\Exceptions;
class FileSizeExceedIniMaximumException extends \Exception
{
public function __construct()
{
$this->message = trans('laravel-filemanager::lfm.error-file-size', ['max' => ini_get('upload_max_filesize')]);
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace UniSharp\LaravelFilemanager\Exceptions;
class InvalidMimeTypeException extends \Exception
{
public function __construct($mimetype)
{
$this->message = trans('laravel-filemanager::lfm.error-mime') . $mimetype;
}
}

View File

@@ -6,6 +6,6 @@ class ConfigHandler
{
public function userField()
{
return auth()->user()->id;
return auth()->id();
}
}

View File

@@ -2,7 +2,7 @@
namespace UniSharp\LaravelFilemanager;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
/**
@@ -17,10 +17,6 @@ class LaravelFilemanagerServiceProvider extends ServiceProvider
*/
public function boot()
{
if (Config::get('lfm.use_package_routes')) {
include __DIR__ . '/routes.php';
}
$this->loadTranslationsFrom(__DIR__.'/lang', 'laravel-filemanager');
$this->loadViewsFrom(__DIR__.'/views', 'laravel-filemanager');
@@ -40,6 +36,12 @@ class LaravelFilemanagerServiceProvider extends ServiceProvider
$this->publishes([
__DIR__.'/Handlers/LfmConfigHandler.php' => base_path('app/Handlers/LfmConfigHandler.php'),
], 'lfm_handler');
if (config('lfm.use_package_routes')) {
Route::group(['prefix' => 'filemanager', 'middleware' => ['web', 'auth']], function () {
\UniSharp\LaravelFilemanager\Lfm::routes();
});
}
}
/**
@@ -49,6 +51,8 @@ class LaravelFilemanagerServiceProvider extends ServiceProvider
*/
public function register()
{
$this->mergeConfigFrom(__DIR__ . '/config/lfm.php', 'lfm-config');
$this->app->singleton('laravel-filemanager', function () {
return true;
});

View File

@@ -0,0 +1,384 @@
<?php
namespace UniSharp\LaravelFilemanager;
use Illuminate\Contracts\Config\Repository as Config;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use UniSharp\LaravelFilemanager\Middlewares\CreateDefaultFolder;
use UniSharp\LaravelFilemanager\Middlewares\MultiUser;
class Lfm
{
const PACKAGE_NAME = 'laravel-filemanager';
const DS = '/';
protected $config;
protected $request;
public function __construct(Config $config = null, Request $request = null)
{
$this->config = $config;
$this->request = $request;
}
public function getStorage($storage_path)
{
return new LfmStorageRepository($storage_path, $this);
}
public function input($key)
{
return $this->translateFromUtf8($this->request->input($key));
}
public function config($key)
{
return $this->config->get('lfm.' . $key);
}
/**
* Get only the file name.
*
* @param string $path Real path of a file.
* @return string
*/
public function getNameFromPath($path)
{
return $this->utf8Pathinfo($path, 'basename');
}
public function utf8Pathinfo($path, $part_name)
{
// XXX: all locale work-around for issue: utf8 file name got emptified
// if there's no '/', we're probably dealing with just a filename
// so just put an 'a' in front of it
if (strpos($path, '/') === false) {
$path_parts = pathinfo('a' . $path);
} else {
$path = str_replace('/', '/a', $path);
$path_parts = pathinfo($path);
}
return substr($path_parts[$part_name], 1);
}
public function allowFolderType($type)
{
if ($type == 'user') {
return $this->allowMultiUser();
} else {
return $this->allowShareFolder();
}
}
public function getCategoryName()
{
$type = $this->currentLfmType();
return $this->config->get('lfm.folder_categories.' . $type . '.folder_name', 'files');
}
/**
* Get current lfm type.
*
* @return string
*/
public function currentLfmType()
{
$lfm_type = 'file';
$request_type = lcfirst(Str::singular($this->input('type') ?: ''));
$available_types = array_keys($this->config->get('lfm.folder_categories') ?: []);
if (in_array($request_type, $available_types)) {
$lfm_type = $request_type;
}
return $lfm_type;
}
public function getDisplayMode()
{
$type_key = $this->currentLfmType();
$startup_view = $this->config->get('lfm.folder_categories.' . $type_key . '.startup_view');
$view_type = 'grid';
$target_display_type = $this->input('show_list') ?: $startup_view;
if (in_array($target_display_type, ['list', 'grid'])) {
$view_type = $target_display_type;
}
return $view_type;
}
public function getUserSlug()
{
$config = $this->config->get('lfm.private_folder_name');
if (is_callable($config)) {
return call_user_func($config);
}
if (class_exists($config)) {
return app()->make($config)->userField();
}
return empty(auth()->user()) ? '' : auth()->user()->$config;
}
public function getRootFolder($type = null)
{
if (is_null($type)) {
$type = 'share';
if ($this->allowFolderType('user')) {
$type = 'user';
}
}
if ($type === 'user') {
$folder = $this->getUserSlug();
} else {
$folder = $this->config->get('lfm.shared_folder_name');
}
// the slash is for url, dont replace it with directory seperator
return '/' . $folder;
}
public function getThumbFolderName()
{
return $this->config->get('lfm.thumb_folder_name');
}
public function getFileType($ext)
{
return $this->config->get("lfm.file_type_array.{$ext}", 'File');
}
public function availableMimeTypes()
{
return $this->config->get('lfm.folder_categories.' . $this->currentLfmType() . '.valid_mime');
}
public function shouldCreateCategoryThumb()
{
return $this->config->get('lfm.folder_categories.' . $this->currentLfmType() . '.thumb');
}
public function categoryThumbWidth()
{
return $this->config->get('lfm.folder_categories.' . $this->currentLfmType() . '.thumb_width');
}
public function categoryThumbHeight()
{
return $this->config->get('lfm.folder_categories.' . $this->currentLfmType() . '.thumb_height');
}
public function maxUploadSize()
{
return $this->config->get('lfm.folder_categories.' . $this->currentLfmType() . '.max_size');
}
public function getPaginationPerPage()
{
return $this->config->get("lfm.paginator.perPage", 30);
}
/**
* Check if users are allowed to use their private folders.
*
* @return bool
*/
public function allowMultiUser()
{
$type_key = $this->currentLfmType();
if ($this->config->has('lfm.folder_categories.' . $type_key . '.allow_private_folder')) {
return $this->config->get('lfm.folder_categories.' . $type_key . '.allow_private_folder') === true;
}
return $this->config->get('lfm.allow_private_folder') === true;
}
/**
* Check if users are allowed to use the shared folder.
* This can be disabled only when allowMultiUser() is true.
*
* @return bool
*/
public function allowShareFolder()
{
if (! $this->allowMultiUser()) {
return true;
}
$type_key = $this->currentLfmType();
if ($this->config->has('lfm.folder_categories.' . $type_key . '.allow_shared_folder')) {
return $this->config->get('lfm.folder_categories.' . $type_key . '.allow_shared_folder') === true;
}
return $this->config->get('lfm.allow_shared_folder') === true;
}
/**
* Translate file name to make it compatible on Windows.
*
* @param string $input Any string.
* @return string
*/
public function translateFromUtf8($input)
{
if ($this->isRunningOnWindows()) {
$input = iconv('UTF-8', mb_detect_encoding($input), $input);
}
return $input;
}
/**
* Get directory seperator of current operating system.
*
* @return string
*/
public function ds()
{
$ds = Lfm::DS;
if ($this->isRunningOnWindows()) {
$ds = '\\';
}
return $ds;
}
/**
* Check current operating system is Windows or not.
*
* @return bool
*/
public function isRunningOnWindows()
{
return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
}
/**
* Shorter function of getting localized error message..
*
* @param mixed $error_type Key of message in lang file.
* @param mixed $variables Variables the message needs.
* @return string
*/
public function error($error_type, $variables = [])
{
throw new \Exception(trans(self::PACKAGE_NAME . '::lfm.error-' . $error_type, $variables));
}
/**
* Generates routes of this package.
*
* @return void
*/
public static function routes()
{
$middleware = [ CreateDefaultFolder::class, MultiUser::class ];
$as = 'unisharp.lfm.';
$namespace = '\\UniSharp\\LaravelFilemanager\\Controllers\\';
Route::group(compact('middleware', 'as', 'namespace'), function () {
// display main layout
Route::get('/', [
'uses' => 'LfmController@show',
'as' => 'show',
]);
// display integration error messages
Route::get('/errors', [
'uses' => 'LfmController@getErrors',
'as' => 'getErrors',
]);
// upload
Route::any('/upload', [
'uses' => 'UploadController@upload',
'as' => 'upload',
]);
// list images & files
Route::get('/jsonitems', [
'uses' => 'ItemsController@getItems',
'as' => 'getItems',
]);
Route::get('/move', [
'uses' => 'ItemsController@move',
'as' => 'move',
]);
Route::get('/domove', [
'uses' => 'ItemsController@domove',
'as' => 'domove'
]);
// folders
Route::get('/newfolder', [
'uses' => 'FolderController@getAddfolder',
'as' => 'getAddfolder',
]);
// list folders
Route::get('/folders', [
'uses' => 'FolderController@getFolders',
'as' => 'getFolders',
]);
// crop
Route::get('/crop', [
'uses' => 'CropController@getCrop',
'as' => 'getCrop',
]);
Route::get('/cropimage', [
'uses' => 'CropController@getCropimage',
'as' => 'getCropimage',
]);
Route::get('/cropnewimage', [
'uses' => 'CropController@getNewCropimage',
'as' => 'getCropnewimage',
]);
// rename
Route::get('/rename', [
'uses' => 'RenameController@getRename',
'as' => 'getRename',
]);
// scale/resize
Route::get('/resize', [
'uses' => 'ResizeController@getResize',
'as' => 'getResize',
]);
Route::get('/doresize', [
'uses' => 'ResizeController@performResize',
'as' => 'performResize',
]);
// download
Route::get('/download', [
'uses' => 'DownloadController@getDownload',
'as' => 'getDownload',
]);
// delete
Route::get('/delete', [
'uses' => 'DeleteController@getDelete',
'as' => 'getDelete',
]);
Route::get('/demo', 'DemoController@index');
});
}
}

View File

@@ -0,0 +1,204 @@
<?php
namespace UniSharp\LaravelFilemanager;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class LfmItem
{
private $lfm;
private $helper;
private $isDirectory;
private $mimeType = null;
private $columns = [];
public $attributes = [];
public function __construct(LfmPath $lfm, Lfm $helper, $isDirectory = false)
{
$this->lfm = $lfm->thumb(false);
$this->helper = $helper;
$this->isDirectory = $isDirectory;
$this->columns = $helper->config('item_columns') ?:
['name', 'url', 'time', 'icon', 'is_file', 'is_image', 'thumb_url'];
}
public function __get($var_name)
{
if (!array_key_exists($var_name, $this->attributes)) {
$function_name = Str::camel($var_name);
$this->attributes[$var_name] = $this->$function_name();
}
return $this->attributes[$var_name];
}
public function fill()
{
foreach ($this->columns as $column) {
$this->__get($column);
}
return $this;
}
public function name()
{
return $this->lfm->getName();
}
public function path($type = 'absolute')
{
return $this->lfm->path($type);
}
public function isDirectory()
{
return $this->isDirectory;
}
public function isFile()
{
return ! $this->isDirectory();
}
/**
* Check a file is image or not.
*
* @param mixed $file Real path of a file or instance of UploadedFile.
* @return bool
*/
public function isImage()
{
return $this->isFile() && Str::startsWith($this->mimeType(), 'image');
}
/**
* Get mime type of a file.
*
* @param mixed $file Real path of a file or instance of UploadedFile.
* @return string
*/
public function mimeType()
{
if (is_null($this->mimeType)) {
$this->mimeType = $this->lfm->mimeType();
}
return $this->mimeType;
}
public function extension()
{
return $this->lfm->extension();
}
public function url()
{
if ($this->isDirectory()) {
return $this->lfm->path('working_dir');
}
return $this->lfm->url();
}
public function size()
{
return $this->isFile() ? $this->humanFilesize($this->lfm->size()) : '';
}
public function time()
{
return $this->lfm->lastModified();
}
public function thumbUrl()
{
if ($this->isDirectory()) {
return asset('vendor/' . Lfm::PACKAGE_NAME . '/img/folder.png');
}
if ($this->isImage()) {
return $this->lfm->thumb($this->hasThumb())->url(true);
}
return null;
}
public function icon()
{
if ($this->isDirectory()) {
return 'fa-folder-o';
}
if ($this->isImage()) {
return 'fa-image';
}
return $this->extension();
}
public function type()
{
if ($this->isDirectory()) {
return trans(Lfm::PACKAGE_NAME . '::lfm.type-folder');
}
if ($this->isImage()) {
return $this->mimeType();
}
return $this->helper->getFileType($this->extension());
}
public function hasThumb()
{
if (!$this->isImage()) {
return false;
}
if (!$this->lfm->thumb()->exists()) {
return false;
}
return true;
}
public function shouldCreateThumb()
{
if (!$this->helper->config('should_create_thumbnails')) {
return false;
}
if (!$this->isImage()) {
return false;
}
if (in_array($this->mimeType(), ['image/gif', 'image/svg+xml'])) {
return false;
}
return true;
}
public function get()
{
return $this->lfm->get();
}
/**
* Make file size readable.
*
* @param int $bytes File size in bytes.
* @param int $decimals Decimals.
* @return string
*/
public function humanFilesize($bytes, $decimals = 2)
{
$size = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$decimals}f %s", $bytes / pow(1024, $factor), @$size[$factor]);
}
}

View File

@@ -0,0 +1,328 @@
<?php
namespace UniSharp\LaravelFilemanager;
use Illuminate\Container\Container;
use Intervention\Image\Facades\Image;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use UniSharp\LaravelFilemanager\Events\FileIsUploading;
use UniSharp\LaravelFilemanager\Events\FileWasUploaded;
use UniSharp\LaravelFilemanager\Events\ImageIsUploading;
use UniSharp\LaravelFilemanager\Events\ImageWasUploaded;
use UniSharp\LaravelFilemanager\LfmUploadValidator;
class LfmPath
{
private $working_dir;
private $item_name;
private $is_thumb = false;
private $helper;
public function __construct(Lfm $lfm = null)
{
$this->helper = $lfm;
}
public function __get($var_name)
{
if ($var_name == 'storage') {
return $this->helper->getStorage($this->path('url'));
}
}
public function __call($function_name, $arguments)
{
return $this->storage->$function_name(...$arguments);
}
public function dir($working_dir)
{
$this->working_dir = $working_dir;
return $this;
}
public function thumb($is_thumb = true)
{
$this->is_thumb = $is_thumb;
return $this;
}
public function setName($item_name)
{
$this->item_name = $item_name;
return $this;
}
public function getName()
{
return $this->item_name;
}
public function path($type = 'storage')
{
if ($type == 'working_dir') {
// working directory: /{user_slug}
return $this->translateToLfmPath($this->normalizeWorkingDir());
} elseif ($type == 'url') {
// storage: files/{user_slug}
// storage without folder: {user_slug}
return $this->helper->getCategoryName() === '.'
? ltrim($this->path('working_dir'), '/')
: $this->helper->getCategoryName() . $this->path('working_dir');
} elseif ($type == 'storage') {
// storage: files/{user_slug}
// storage on windows: files\{user_slug}
return str_replace(Lfm::DS, $this->helper->ds(), $this->path('url'));
} else {
// absolute: /var/www/html/project/storage/app/files/{user_slug}
// absolute on windows: C:\project\storage\app\files\{user_slug}
return $this->storage->rootPath() . $this->path('storage');
}
}
public function translateToLfmPath($path)
{
return str_replace($this->helper->ds(), Lfm::DS, $path);
}
public function url()
{
return $this->storage->url($this->path('url'));
}
public function folders()
{
$all_folders = array_map(function ($directory_path) {
return $this->pretty($directory_path, true);
}, $this->storage->directories());
$folders = array_filter($all_folders, function ($directory) {
return $directory->name !== $this->helper->getThumbFolderName();
});
return $this->sortByColumn($folders);
}
public function files()
{
$files = array_map(function ($file_path) {
return $this->pretty($file_path);
}, $this->storage->files());
return $this->sortByColumn($files);
}
public function pretty($item_path, $isDirectory = false)
{
return Container::getInstance()->makeWith(LfmItem::class, [
'lfm' => (clone $this)->setName($this->helper->getNameFromPath($item_path)),
'helper' => $this->helper,
'isDirectory' => $isDirectory
]);
}
public function delete()
{
if ($this->isDirectory()) {
return $this->storage->deleteDirectory();
} else {
return $this->storage->delete();
}
}
/**
* Create folder if not exist.
*
* @param string $path Real path of a directory.
* @return bool
*/
public function createFolder()
{
if ($this->storage->exists($this)) {
return false;
}
$this->storage->makeDirectory(0777, true, true);
}
public function isDirectory()
{
$working_dir = $this->path('working_dir');
$parent_dir = substr($working_dir, 0, strrpos($working_dir, '/'));
$parent_directories = array_map(function ($directory_path) {
return app(static::class)->translateToLfmPath($directory_path);
}, app(static::class)->dir($parent_dir)->directories());
return in_array($this->path('url'), $parent_directories);
}
/**
* Check a folder and its subfolders is empty or not.
*
* @param string $directory_path Real path of a directory.
* @return bool
*/
public function directoryIsEmpty()
{
return count($this->storage->allFiles()) == 0;
}
public function normalizeWorkingDir()
{
$path = $this->working_dir
?: $this->helper->input('working_dir')
?: $this->helper->getRootFolder();
if ($this->is_thumb) {
// Prevent if working dir is "/" normalizeWorkingDir will add double "//" that breaks S3 functionality
$path = rtrim($path, Lfm::DS) . Lfm::DS . $this->helper->getThumbFolderName();
}
if ($this->getName()) {
// Prevent if working dir is "/" normalizeWorkingDir will add double "//" that breaks S3 functionality
$path = rtrim($path, Lfm::DS) . Lfm::DS . $this->getName();
}
return $path;
}
/**
* Sort files and directories.
*
* @param mixed $arr_items Array of files or folders or both.
* @return array of object
*/
public function sortByColumn($arr_items)
{
$sort_by = $this->helper->input('sort_type');
if (in_array($sort_by, ['name', 'time'])) {
$key_to_sort = $sort_by;
} else {
$key_to_sort = 'name';
}
uasort($arr_items, function ($a, $b) use ($key_to_sort) {
return strcasecmp($a->{$key_to_sort}, $b->{$key_to_sort});
});
return $arr_items;
}
public function error($error_type, $variables = [])
{
throw new \Exception($this->helper->error($error_type, $variables));
}
// Upload section
public function upload($file)
{
$new_file_name = $this->getNewName($file);
$new_file_path = $this->setName($new_file_name)->path('absolute');
event(new FileIsUploading($new_file_path));
event(new ImageIsUploading($new_file_path));
try {
$this->setName($new_file_name)->storage->save($file);
$this->generateThumbnail($new_file_name);
} catch (\Exception $e) {
\Log::info($e);
return $this->error('invalid');
}
// TODO should be "FileWasUploaded"
event(new FileWasUploaded($new_file_path));
event(new ImageWasUploaded($new_file_path));
return $new_file_name;
}
public function validateUploadedFile($file)
{
$validator = new LfmUploadValidator($file);
$validator->sizeLowerThanIniMaximum();
$validator->uploadWasSuccessful();
if (!config('lfm.over_write_on_duplicate')) {
$validator->nameIsNotDuplicate($this->getNewName($file), $this);
}
$validator->isNotExcutable(config('lfm.disallowed_mimetypes', ['text/x-php', 'text/html', 'text/plain']));
if (config('lfm.should_validate_mime', false)) {
$validator->mimeTypeIsValid($this->helper->availableMimeTypes());
}
if (config('lfm.should_validate_size', false)) {
$validator->sizeIsLowerThanConfiguredMaximum($this->helper->maxUploadSize());
}
return true;
}
private function getNewName($file)
{
$new_file_name = $this->helper->translateFromUtf8(
trim($this->helper->utf8Pathinfo($file->getClientOriginalName(), "filename"))
);
$extension = $file->getClientOriginalExtension();
if (config('lfm.rename_file') === true) {
$new_file_name = uniqid();
} elseif (config('lfm.alphanumeric_filename') === true) {
$new_file_name = preg_replace('/[^A-Za-z0-9\-\']/', '_', $new_file_name);
}
if ($extension) {
$new_file_name_with_extention = $new_file_name . '.' . $extension;
}
if (config('lfm.rename_duplicates') === true) {
$counter = 1;
$file_name_without_extentions = $new_file_name;
while ($this->setName(($extension) ? $new_file_name_with_extention : $new_file_name)->exists()) {
if (config('lfm.alphanumeric_filename') === true) {
$suffix = '_'.$counter;
} else {
$suffix = " ({$counter})";
}
$new_file_name = $file_name_without_extentions.$suffix;
if ($extension) {
$new_file_name_with_extention = $new_file_name . '.' . $extension;
}
$counter++;
}
}
return ($extension) ? $new_file_name_with_extention : $new_file_name;
}
public function generateThumbnail($file_name)
{
$original_image = $this->pretty($file_name);
if (!$original_image->shouldCreateThumb()) {
return;
}
// create folder for thumbnails
$this->setName(null)->thumb(true)->createFolder();
// generate cropped image content
$this->setName($file_name)->thumb(true);
$thumbWidth = $this->helper->shouldCreateCategoryThumb() && $this->helper->categoryThumbWidth() ? $this->helper->categoryThumbWidth() : config('lfm.thumb_img_width', 200);
$thumbHeight = $this->helper->shouldCreateCategoryThumb() && $this->helper->categoryThumbHeight() ? $this->helper->categoryThumbHeight() : config('lfm.thumb_img_height', 200);
$image = Image::make($original_image->get())
->fit($thumbWidth, $thumbHeight);
$this->storage->put($image->stream()->detach(), 'public');
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace UniSharp\LaravelFilemanager;
use Illuminate\Support\Facades\Storage;
class LfmStorageRepository
{
private $disk;
private $path;
private $helper;
public function __construct($storage_path, $helper)
{
$this->helper = $helper;
$this->disk = Storage::disk($this->helper->config('disk'));
$this->path = $storage_path;
}
public function __call($function_name, $arguments)
{
// TODO: check function exists
return $this->disk->$function_name($this->path, ...$arguments);
}
public function rootPath()
{
return $this->disk->path('');
}
public function move($new_lfm_path)
{
return $this->disk->move($this->path, $new_lfm_path->path('storage'));
}
public function save($file)
{
$nameint = strripos($this->path, "/");
$nameclean = substr($this->path, $nameint + 1);
$pathclean = substr_replace($this->path, "", $nameint);
$this->disk->putFileAs($pathclean, $file, $nameclean);
}
public function url($path)
{
return $this->disk->url($path);
}
public function makeDirectory()
{
$this->disk->makeDirectory($this->path, ...func_get_args());
// some filesystems (e.g. Google Storage, S3?) don't let you set ACLs on directories (because they don't exist)
// https://cloud.google.com/storage/docs/naming#object-considerations
if ($this->disk->has($this->path)) {
$this->disk->setVisibility($this->path, 'public');
}
}
public function extension()
{
setlocale(LC_ALL, 'en_US.UTF-8');
return pathinfo($this->path, PATHINFO_EXTENSION);
}
}

View File

@@ -0,0 +1,97 @@
<?php
namespace UniSharp\LaravelFilemanager;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use UniSharp\LaravelFilemanager\Exceptions\DuplicateFileNameException;
use UniSharp\LaravelFilemanager\Exceptions\EmptyFileException;
use UniSharp\LaravelFilemanager\Exceptions\ExcutableFileException;
use UniSharp\LaravelFilemanager\Exceptions\FileFailedToUploadException;
use UniSharp\LaravelFilemanager\Exceptions\FileSizeExceedConfigurationMaximumException;
use UniSharp\LaravelFilemanager\Exceptions\FileSizeExceedIniMaximumException;
use UniSharp\LaravelFilemanager\Exceptions\InvalidMimeTypeException;
use UniSharp\LaravelFilemanager\LfmPath;
class LfmUploadValidator
{
private $file;
public function __construct(UploadedFile $file)
{
// if (! $file instanceof UploadedFile) {
// throw new \Exception(trans(self::PACKAGE_NAME . '::lfm.error-instance'));
// }
$this->file = $file;
}
// public function hasContent()
// {
// if (empty($this->file)) {
// throw new EmptyFileException();
// }
// return $this;
// }
public function sizeLowerThanIniMaximum()
{
if ($this->file->getError() == UPLOAD_ERR_INI_SIZE) {
throw new FileSizeExceedIniMaximumException();
}
return $this;
}
public function uploadWasSuccessful()
{
if ($this->file->getError() != UPLOAD_ERR_OK) {
throw new FileFailedToUploadException($this->file->getError());
}
return $this;
}
public function nameIsNotDuplicate($new_file_name, LfmPath $lfm_path)
{
if ($lfm_path->setName($new_file_name)->exists()) {
throw new DuplicateFileNameException();
}
return $this;
}
public function isNotExcutable($excutable_mimetypes)
{
$mimetype = $this->file->getMimeType();
if (in_array($mimetype, $excutable_mimetypes)) {
throw new ExcutableFileException();
}
return $this;
}
public function mimeTypeIsValid($available_mime_types)
{
$mimetype = $this->file->getMimeType();
if (false === in_array($mimetype, $available_mime_types)) {
throw new InvalidMimeTypeException($mimetype);
}
return $this;
}
public function sizeIsLowerThanConfiguredMaximum($max_size_in_kb)
{
// size to kb unit is needed
$file_size_in_kb = $this->file->getSize() / 1000;
if ($file_size_in_kb > $max_size_in_kb) {
throw new FileSizeExceedConfigurationMaximumException($file_size_in_kb);
}
return $this;
}
}

View File

@@ -3,11 +3,19 @@
namespace UniSharp\LaravelFilemanager\Middlewares;
use Closure;
use UniSharp\LaravelFilemanager\Traits\LfmHelpers;
use UniSharp\LaravelFilemanager\Lfm;
use UniSharp\LaravelFilemanager\LfmPath;
class CreateDefaultFolder
{
use LfmHelpers;
private $lfm;
private $helper;
public function __construct()
{
$this->lfm = app(LfmPath::class);
$this->helper = app(Lfm::class);
}
public function handle($request, Closure $next)
{
@@ -19,16 +27,10 @@ class CreateDefaultFolder
private function checkDefaultFolderExists($type = 'share')
{
if ($type === 'user' && ! $this->allowMultiUser()) {
if (! $this->helper->allowFolderType($type)) {
return;
}
if ($type === 'share' && ! $this->allowShareFolder()) {
return;
}
$path = $this->getRootFolderPath($type);
$this->createFolderByPath($path);
$this->lfm->dir($this->helper->getRootFolder($type))->createFolder();
}
}

View File

@@ -3,17 +3,23 @@
namespace UniSharp\LaravelFilemanager\Middlewares;
use Closure;
use UniSharp\LaravelFilemanager\Traits\LfmHelpers;
use Illuminate\Support\Str;
use UniSharp\LaravelFilemanager\Lfm;
class MultiUser
{
use LfmHelpers;
private $helper;
public function __construct()
{
$this->helper = app(Lfm::class);
}
public function handle($request, Closure $next)
{
if ($this->allowMultiUser()) {
if ($this->helper->allowFolderType('user')) {
$previous_dir = $request->input('working_dir');
$working_dir = $this->rootFolder('user');
$working_dir = $this->helper->getRootFolder('user');
if ($previous_dir == null) {
$request->merge(compact('working_dir'));
@@ -27,11 +33,11 @@ class MultiUser
private function validDir($previous_dir)
{
if (starts_with($previous_dir, $this->rootFolder('share'))) {
if (Str::startsWith($previous_dir, $this->helper->getRootFolder('share'))) {
return true;
}
if (starts_with($previous_dir, $this->rootFolder('user'))) {
if (Str::startsWith($previous_dir, $this->helper->getRootFolder('user'))) {
return true;
}

View File

@@ -1,645 +0,0 @@
<?php
namespace UniSharp\LaravelFilemanager\Traits;
use Illuminate\Support\Facades\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
trait LfmHelpers
{
/*****************************
*** Path / Url ***
*****************************/
/**
* Directory separator for url.
*
* @var string|null
*/
private $ds = '/';
/**
* Get real path of a thumbnail on the operating system.
*
* @param string|null $image_name File name of original image
* @return string|null
*/
public function getThumbPath($image_name = null)
{
return $this->getCurrentPath($image_name, 'thumb');
}
/**
* Get real path of a file, image, or current working directory on the operating system.
*
* @param string|null $file_name File name of image or file
* @return string|null
*/
public function getCurrentPath($file_name = null, $is_thumb = null)
{
$path = $this->composeSegments('dir', $is_thumb, $file_name);
$path = $this->translateToOsPath($path);
return base_path($path);
}
/**
* Get url of a thumbnail.
*
* @param string|null $image_name File name of original image
* @return string|null
*/
public function getThumbUrl($image_name = null)
{
return $this->getFileUrl($image_name, 'thumb');
}
/**
* Get url of a original image.
*
* @param string|null $image_name File name of original image
* @return string|null
*/
public function getFileUrl($image_name = null, $is_thumb = null)
{
return url($this->composeSegments('url', $is_thumb, $image_name));
}
/**
* Assemble needed config or input to form url or real path of a file, image, or current working directory.
*
* @param string $type Url or dir
* @param bollean $is_thumb Image is a thumbnail or not
* @param string|null $file_name File name of image or file
* @return string|null
*/
private function composeSegments($type, $is_thumb, $file_name)
{
$full_path = implode($this->ds, [
$this->getPathPrefix($type),
$this->getFormatedWorkingDir(),
$this->appendThumbFolderPath($is_thumb),
$file_name,
]);
$full_path = $this->removeDuplicateSlash($full_path);
$full_path = $this->translateToLfmPath($full_path);
return $this->removeLastSlash($full_path);
}
/**
* Assemble base_directory and route prefix config.
*
* @param string $type Url or dir
* @return string
*/
public function getPathPrefix($type)
{
$default_folder_name = 'files';
if ($this->isProcessingImages()) {
$default_folder_name = 'photos';
}
$prefix = config('lfm.' . $this->currentLfmType() . 's_folder_name', $default_folder_name);
$base_directory = config('lfm.base_directory', 'public');
if ($type === 'dir') {
$prefix = $base_directory . '/' . $prefix;
}
if ($type === 'url' && $base_directory !== 'public') {
$prefix = config('lfm.url_prefix', config('lfm.prefix', 'laravel-filemanager')) . '/' . $prefix;
}
return $prefix;
}
/**
* Get current or default working directory.
*
* @return string
*/
private function getFormatedWorkingDir()
{
$working_dir = request('working_dir');
if (empty($working_dir)) {
$default_folder_type = 'share';
if ($this->allowMultiUser()) {
$default_folder_type = 'user';
}
$working_dir = $this->rootFolder($default_folder_type);
}
return $this->removeFirstSlash($working_dir);
}
/**
* Get thumbnail folder name.
*
* @return string|null
*/
private function appendThumbFolderPath($is_thumb)
{
if (! $is_thumb) {
return;
}
$thumb_folder_name = config('lfm.thumb_folder_name');
// if user is inside thumbs folder, there is no need
// to add thumbs substring to the end of url
$in_thumb_folder = str_contains($this->getFormatedWorkingDir(), $this->ds . $thumb_folder_name);
if (! $in_thumb_folder) {
return $thumb_folder_name . $this->ds;
}
}
/**
* Get root working directory.
*
* @param string $type User or share.
* @return string
*/
public function rootFolder($type)
{
if ($type === 'user') {
$folder_name = $this->getUserSlug();
} else {
$folder_name = config('lfm.shared_folder_name');
}
return $this->ds . $folder_name;
}
/**
* Get real path of root working directory on the operating system.
*
* @param string|null $type User or share
* @return string|null
*/
public function getRootFolderPath($type)
{
return base_path($this->getPathPrefix('dir') . $this->rootFolder($type));
}
/**
* Get only the file name.
*
* @param string $file Real path of a file.
* @return string
*/
public function getName($file)
{
$lfm_file_path = $this->getInternalPath($file);
$arr_dir = explode($this->ds, $lfm_file_path);
$file_name = end($arr_dir);
return $file_name;
}
/**
* Get url with only working directory and file name.
*
* @param string $full_path Real path of a file.
* @return string
*/
public function getInternalPath($full_path)
{
$full_path = $this->translateToLfmPath($full_path);
$full_path = $this->translateToUtf8($full_path);
$lfm_dir_start = strpos($full_path, $this->getPathPrefix('dir'));
$working_dir_start = $lfm_dir_start + strlen($this->getPathPrefix('dir'));
$lfm_file_path = $this->ds . substr($full_path, $working_dir_start);
return $this->removeDuplicateSlash($lfm_file_path);
}
/**
* Change directiry separator, from url one to one on current operating system.
*
* @param string $path Url of a file.
* @return string
*/
private function translateToOsPath($path)
{
if ($this->isRunningOnWindows()) {
$path = str_replace($this->ds, '\\', $path);
}
return $path;
}
/**
* Change directiry separator, from one on current operating system to url one.
*
* @param string $path Real path of a file.
* @return string
*/
private function translateToLfmPath($path)
{
if ($this->isRunningOnWindows()) {
$path = str_replace('\\', $this->ds, $path);
}
return $path;
}
/**
* Strip duplicate slashes from url.
*
* @param string $path Any url.
* @return string
*/
private function removeDuplicateSlash($path)
{
return preg_replace('/\\'.$this->ds.'{2,}/', $this->ds, $path);
}
/**
* Strip first slash from url.
*
* @param string $path Any url.
* @return string
*/
private function removeFirstSlash($path)
{
if (starts_with($path, $this->ds)) {
$path = substr($path, 1);
}
return $path;
}
/**
* Strip last slash from url.
*
* @param string $path Any url.
* @return string
*/
private function removeLastSlash($path)
{
// remove last slash
if (ends_with($path, $this->ds)) {
$path = substr($path, 0, -1);
}
return $path;
}
/**
* Translate file name to make it compatible on Windows.
*
* @param string $input Any string.
* @return string
*/
public function translateFromUtf8($input)
{
if ($this->isRunningOnWindows()) {
$input = iconv('UTF-8', mb_detect_encoding($input), $input);
}
return $input;
}
/**
* Translate file name from Windows.
*
* @param string $input Any string.
* @return string
*/
public function translateToUtf8($input)
{
if ($this->isRunningOnWindows()) {
$input = iconv(mb_detect_encoding($input), 'UTF-8', $input);
}
return $input;
}
/****************************
*** Config / Settings ***
****************************/
/**
* Check current lfm type is image or not.
*
* @return bool
*/
public function isProcessingImages()
{
return lcfirst(str_singular(request('type', '') ?: '')) === 'image';
}
/**
* Check current lfm type is file or not.
*
* @return bool
*/
public function isProcessingFiles()
{
return ! $this->isProcessingImages();
}
/**
* Get current lfm type..
*
* @return string
*/
public function currentLfmType()
{
$file_type = 'file';
if ($this->isProcessingImages()) {
$file_type = 'image';
}
return $file_type;
}
/**
* Check if users are allowed to use their private folders.
*
* @return bool
*/
public function allowMultiUser()
{
return config('lfm.allow_multi_user') === true;
}
/**
* Check if users are allowed to use the shared folder.
* This can be disabled only when allowMultiUser() is true.
*
* @return bool
*/
public function allowShareFolder()
{
if (! $this->allowMultiUser()) {
return true;
}
return config('lfm.allow_share_folder') === true;
}
/**
* Overrides settings in php.ini.
*
* @return null
*/
public function applyIniOverrides()
{
if (count(config('lfm.php_ini_overrides')) == 0) {
return;
}
foreach (config('lfm.php_ini_overrides') as $key => $value) {
if ($value && $value != 'false') {
ini_set($key, $value);
}
}
}
/****************************
*** File System ***
****************************/
/**
* Get folders by the given directory.
*
* @param string $path Real path of a directory.
* @return array of objects
*/
public function getDirectories($path)
{
return array_map(function ($directory) {
return $this->objectPresenter($directory);
}, array_filter(File::directories($path), function ($directory) {
return $this->getName($directory) !== config('lfm.thumb_folder_name');
}));
}
/**
* Get files by the given directory.
*
* @param string $path Real path of a directory.
* @return array of objects
*/
public function getFilesWithInfo($path)
{
return array_map(function ($file) {
return $this->objectPresenter($file);
}, File::files($path));
}
/**
* Format a file or folder to object.
*
* @param string $item Real path of a file or directory.
* @return object
*/
public function objectPresenter($item)
{
$item_name = $this->getName($item);
$is_file = is_file($item);
if (! $is_file) {
$file_type = trans('laravel-filemanager::lfm.type-folder');
$icon = 'fa-folder-o';
$thumb_url = asset('vendor/laravel-filemanager/img/folder.png');
} elseif ($this->fileIsImage($item)) {
$file_type = $this->getFileType($item);
$icon = 'fa-image';
$thumb_path = $this->getThumbPath($item_name);
$file_path = $this->getCurrentPath($item_name);
if (! $this->imageShouldHaveThumb($file_path)) {
$thumb_url = $this->getFileUrl($item_name) . '?timestamp=' . filemtime($file_path);
} elseif (File::exists($thumb_path)) {
$thumb_url = $this->getThumbUrl($item_name) . '?timestamp=' . filemtime($thumb_path);
} else {
$thumb_url = $this->getFileUrl($item_name) . '?timestamp=' . filemtime($file_path);
}
} else {
$extension = strtolower(File::extension($item_name));
$file_type = config('lfm.file_type_array.' . $extension) ?: 'File';
$icon = config('lfm.file_icon_array.' . $extension) ?: 'fa-file';
$thumb_url = null;
}
return (object) [
'name' => $item_name,
'url' => $is_file ? $this->getFileUrl($item_name) : '',
'size' => $is_file ? $this->humanFilesize(File::size($item)) : '',
'updated' => filemtime($item),
'path' => $is_file ? '' : $this->getInternalPath($item),
'time' => date('Y-m-d h:i', filemtime($item)),
'type' => $file_type,
'icon' => $icon,
'thumb' => $thumb_url,
'is_file' => $is_file,
];
}
/**
* Create folder if not exist.
*
* @param string $path Real path of a directory.
* @return null
*/
public function createFolderByPath($path)
{
if (! File::exists($path)) {
File::makeDirectory($path, config('lfm.create_folder_mode', 0755), true, true);
}
}
/**
* Check a folder and its subfolders is empty or not.
*
* @param string $directory_path Real path of a directory.
* @return bool
*/
public function directoryIsEmpty($directory_path)
{
return count(File::allFiles($directory_path)) == 0;
}
/**
* Check a file is image or not.
*
* @param mixed $file Real path of a file or instance of UploadedFile.
* @return bool
*/
public function fileIsImage($file)
{
$mime_type = $this->getFileType($file);
return starts_with($mime_type, 'image');
}
/**
* Check thumbnail should be created when the file is uploading.
*
* @param mixed $file Real path of a file or instance of UploadedFile.
* @return bool
*/
public function imageShouldHaveThumb($file)
{
if (! config('lfm.should_create_thumbnails', true)) {
return false;
}
$mime_type = $this->getFileType($file);
return in_array(
$mime_type,
config('lfm.raster_mimetypes', ['image/jpeg', 'image/pjpeg', 'image/png'])
);
}
/**
* Get mime type of a file.
*
* @param mixed $file Real path of a file or instance of UploadedFile.
* @return string
*/
public function getFileType($file)
{
if ($file instanceof UploadedFile) {
$mime_type = $file->getMimeType();
} else {
$mime_type = File::mimeType($file);
}
return $mime_type;
}
/**
* Sort files and directories.
*
* @param mixed $arr_items Array of files or folders or both.
* @param mixed $sort_type Alphabetic or time.
* @return array of object
*/
public function sortFilesAndDirectories($arr_items, $sort_type)
{
if ($sort_type == 'time') {
$key_to_sort = 'updated';
} elseif ($sort_type == 'alphabetic') {
$key_to_sort = 'name';
} else {
$key_to_sort = 'updated';
}
uasort($arr_items, function ($a, $b) use ($key_to_sort) {
return strcmp($a->{$key_to_sort}, $b->{$key_to_sort});
});
return $arr_items;
}
/****************************
*** Miscellaneouses ***
****************************/
/**
* Get the name of private folder of current user.
*
* @return string
*/
public function getUserSlug()
{
if (is_callable(config('lfm.user_field'))) {
$slug_of_user = call_user_func(config('lfm.user_field'));
} elseif (class_exists(config('lfm.user_field'))) {
$config_handler = config('lfm.user_field');
$slug_of_user = app()->make($config_handler)->userField();
} else {
$old_slug_of_user = config('lfm.user_field');
$slug_of_user = empty(auth()->user()) ? '' : auth()->user()->$old_slug_of_user;
}
return $slug_of_user;
}
/**
* Shorter function of getting localized error message..
*
* @param mixed $error_type Key of message in lang file.
* @param mixed $variables Variables the message needs.
* @return string
*/
public function error($error_type, $variables = [])
{
return trans('laravel-filemanager::lfm.error-' . $error_type, $variables);
}
/**
* Make file size readable.
*
* @param int $bytes File size in bytes.
* @param int $decimals Decimals.
* @return string
*/
public function humanFilesize($bytes, $decimals = 2)
{
$size = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . @$size[$factor];
}
/**
* Check current operating system is Windows or not.
*
* @return bool
*/
public function isRunningOnWindows()
{
return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
}
}

View File

@@ -1,147 +1,153 @@
<?php
/*
|--------------------------------------------------------------------------
| Documentation for this config :
|--------------------------------------------------------------------------
| online => http://unisharp.github.io/laravel-filemanager/config
| offline => vendor/unisharp/laravel-filemanager/docs/config.md
*/
return [
/*
|--------------------------------------------------------------------------
| Routing
|--------------------------------------------------------------------------
*/
*/
// Include to pre-defined routes from package or not. Middlewares
'use_package_routes' => true,
// Middlewares which should be applied to all package routes.
// For laravel 5.1 and before, remove 'web' from the array.
'middlewares' => ['web', 'auth'],
// The url to this package. Change it if necessary.
'url_prefix' => 'laravel-filemanager',
'use_package_routes' => true,
/*
|--------------------------------------------------------------------------
| Multi-User Mode
| Shared folder / Private folder
|--------------------------------------------------------------------------
*/
|
| If both options are set to false, then shared folder will be activated.
|
*/
// If true, private folders will be created for each signed-in user.
'allow_multi_user' => true,
// If true, share folder will be created when allow_multi_user is true.
'allow_share_folder' => true,
'allow_private_folder' => true,
// Flexible way to customize client folders accessibility
// If you want to customize client folders, publish tag="lfm_handler"
// Then you can rewrite userField function in App\Handler\ConfigHander class
// And set 'user_field' to App\Handler\ConfigHander::class
// Then you can rewrite userField function in App\Handler\ConfigHandler class
// And set 'user_field' to App\Handler\ConfigHandler::class
// Ex: The private folder of user will be named as the user id.
'user_field' => UniSharp\LaravelFilemanager\Handlers\ConfigHandler::class,
'private_folder_name' => UniSharp\LaravelFilemanager\Handlers\ConfigHandler::class,
'allow_shared_folder' => true,
'shared_folder_name' => 'shares',
/*
|--------------------------------------------------------------------------
| Working Directory
| Folder Names
|--------------------------------------------------------------------------
*/
*/
// Which folder to store files in project, fill in 'public', 'resources', 'storage' and so on.
// You should create routes to serve images if it is not set to public.
'base_directory' => 'public',
'images_folder_name' => 'photos',
'files_folder_name' => 'files',
'shared_folder_name' => 'shares',
'thumb_folder_name' => 'thumbs',
'folder_categories' => [
'file' => [
'folder_name' => 'files',
'startup_view' => 'list',
'max_size' => 50000, // size in KB
'thumb' => true,
'thumb_width' => 80,
'thumb_height' => 80,
'valid_mime' => [
'image/jpeg',
'image/pjpeg',
'image/png',
'image/gif',
'application/pdf',
'text/plain',
],
],
'image' => [
'folder_name' => 'photos',
'startup_view' => 'grid',
'max_size' => 50000, // size in KB
'thumb' => true,
'thumb_width' => 80,
'thumb_height' => 80,
'valid_mime' => [
'image/jpeg',
'image/pjpeg',
'image/png',
'image/gif',
],
],
],
/*
|--------------------------------------------------------------------------
| Startup Views
| Pagination
|--------------------------------------------------------------------------
*/
*/
// The default display type for items.
// Supported: "grid", "list"
'images_startup_view' => 'grid',
'files_startup_view' => 'list',
'paginator' => [
'perPage' => 30,
],
/*
|--------------------------------------------------------------------------
| Upload / Validation
|--------------------------------------------------------------------------
*/
*/
// If true, the uploaded file will be renamed to uniqid() + file extension.
'rename_file' => false,
'disk' => 'public',
// If rename_file set to false and this set to true, then non-alphanumeric characters in filename will be replaced.
'alphanumeric_filename' => false,
'rename_file' => false,
// If true, non-alphanumeric folder name will be rejected.
'alphanumeric_directory' => false,
'rename_duplicates' => false,
// If true, the uploading file's size will be verified for over than max_image_size/max_file_size.
'should_validate_size' => false,
'alphanumeric_filename' => false,
'max_image_size' => 50000,
'max_file_size' => 50000,
'alphanumeric_directory' => false,
// If true, the uploading file's mime type will be valid in valid_image_mimetypes/valid_file_mimetypes.
'should_validate_mime' => false,
'should_validate_size' => false,
// available since v1.3.0
'valid_image_mimetypes' => [
'image/jpeg',
'image/pjpeg',
'image/png',
'image/gif',
'image/svg+xml',
],
'should_validate_mime' => true,
// behavior on files with identical name
// setting it to true cause old file replace with new one
// setting it to false show `error-file-exist` error and stop upload
'over_write_on_duplicate' => false,
// mimetypes of executables to prevent from uploading
'disallowed_mimetypes' => ['text/x-php', 'text/html', 'text/plain'],
// Item Columns
'item_columns' => ['name', 'url', 'time', 'icon', 'is_file', 'is_image', 'thumb_url'],
/*
|--------------------------------------------------------------------------
| Thumbnail
|--------------------------------------------------------------------------
*/
// If true, image thumbnails would be created during upload
'should_create_thumbnails' => true,
'thumb_folder_name' => 'thumbs',
// Create thumbnails automatically only for listed types.
'raster_mimetypes' => [
'raster_mimetypes' => [
'image/jpeg',
'image/pjpeg',
'image/png',
],
// permissions to be set when create a new folder or when it creates automatically with thumbnails
'create_folder_mode' => 0755,
'thumb_img_width' => 200, // px
// permissions to be set on file upload.
'create_file_mode' => 0644,
// If true, it will attempt to chmod the file after upload
'should_change_file_mode' => true,
// available since v1.3.0
// only when '/laravel-filemanager?type=Files'
'valid_file_mimetypes' => [
'image/jpeg',
'image/pjpeg',
'image/png',
'image/gif',
'image/svg+xml',
'application/pdf',
'text/plain',
],
/*
|--------------------------------------------------------------------------
| Image / Folder Setting
|--------------------------------------------------------------------------
*/
'thumb_img_width' => 200,
'thumb_img_height' => 200,
'thumb_img_height' => 200, // px
/*
|--------------------------------------------------------------------------
| File Extension Information
|--------------------------------------------------------------------------
*/
*/
'file_type_array' => [
'file_type_array' => [
'pdf' => 'Adobe Acrobat',
'doc' => 'Microsoft Word',
'docx' => 'Microsoft Word',
@@ -156,21 +162,6 @@ return [
'pptx' => 'Microsoft PowerPoint',
],
'file_icon_array' => [
'pdf' => 'fa-file-pdf-o',
'doc' => 'fa-file-word-o',
'docx' => 'fa-file-word-o',
'xls' => 'fa-file-excel-o',
'xlsx' => 'fa-file-excel-o',
'zip' => 'fa-file-archive-o',
'gif' => 'fa-file-image-o',
'jpg' => 'fa-file-image-o',
'jpeg' => 'fa-file-image-o',
'png' => 'fa-file-image-o',
'ppt' => 'fa-file-powerpoint-o',
'pptx' => 'fa-file-powerpoint-o',
],
/*
|--------------------------------------------------------------------------
| php.ini override
@@ -181,9 +172,8 @@ return [
|
| Please note that the 'upload_max_filesize' & 'post_max_size'
| directives are not supported.
*/
'php_ini_overrides' => [
'memory_limit' => '256M',
*/
'php_ini_overrides' => [
'memory_limit' => '256M',
],
];

View File

@@ -18,8 +18,8 @@ return [
'title-panel' => 'مدير الملفات',
'title-upload' => 'رفع ملف',
'title-view' => 'عرض الملف',
'title-root' => 'الملفات',
'title-shares' => 'الملفات المشتركة',
'title-user' => 'الملفات',
'title-share' => 'الملفات المشتركة',
'title-item' => 'ملف',
'title-size' => 'الحجم',
'title-type' => 'النوع',

View File

@@ -0,0 +1,83 @@
<?php
return [
'nav-back' => 'Geri',
'nav-new' => 'Yeni qovluq',
'nav-upload' => 'Yüklə',
'nav-thumbnails' => 'Kiçik formatda (thumb)',
'nav-list' => 'Siyahı',
'nav-sort' => 'Sırala',
'nav-sort-alphabetic'=> 'A-Z Sırala',
'nav-sort-time' => 'Zamana Görə Sırala',
'menu-rename' => 'Ad dəyişmək',
'menu-delete' => 'Sil',
'menu-view' => 'Görüntülə',
'menu-download' => 'Endir',
'menu-resize' => 'Ölçüləndir',
'menu-crop' => 'Kəsmək',
'menu-move' => 'Yerini dəyiş',
'menu-multiple' => 'Multi-seçim',
'title-page' => 'Fayl menecer',
'title-panel' => 'Fayl menecer',
'title-upload' => 'Fayl yülə',
'title-view' => 'Fayla bax',
'title-root' => 'Fayllarım',
'title-shares' => 'Paylaşılan Fayllar',
'title-item' => 'Faylalr',
'title-size' => 'Böyütmək',
'title-type' => 'Tip',
'title-modified' => 'Dəyişmək',
'title-action' => 'Funksiyalar',
'title-user' => 'Fayllar',
'title-share' => 'Paylaşılmış fayllar',
'type-folder' => 'Qovluq',
'message-empty' => 'Qovluq boşdur',
'message-choose' => 'Fayl seç',
'message-delete' => 'Bu faylı silmək istədiyinizə əminsiniz?',
'message-name' => 'Qovluq adı:',
'message-rename' => 'Yeni ad:',
'message-extension_not_found' => 'Xahiş olunur , Şəkilləri kəsmək və ya yenidən ölçü vermək istəyirsinizsə gd və ya imagick genişlənmələriniz serverinizdə aktiov edin.',
'message-drop' => 'və ya yükləmək üçün faylları bura atın',
'error-rename' => 'Fayl adı artıq istifadə olunur!',
'error-file-name' => 'Dosya adı boş bırakılamaz!',
'error-file-empty' => 'Fayl adı boş ola bilməz!',
'error-file-exist' => 'Bu adda bir fayl artıq var!',
'error-file-size' => 'Fayl ölçüsü limiti keçir! (maximum ölçü: :max)',
'error-delete-folder'=> 'Qovluq boş olmadığından silmək mümkün olmadı!',
'error-folder-name' => 'Qovluq adı boş ola bilməz!',
'error-folder-exist'=> 'Bu adda qovluq artıq var!',
'error-folder-alnum'=> 'Yalnız hərf və rəqəmdən ibarət adlara icazə verilir',
'error-folder-not-found'=> 'Qovluq tapılmadı! (:folder)',
'error-mime' => 'İcazə verilməyən fayl tipi: ',
'error-size' => 'Həcm limiti keçir:',
'error-instance' => 'Yüklənən fayl, UploadedFile nümunəsi kimi olmalıdır',
'error-invalid' => 'Yükləmə istəyi doğru deyil',
'error-other' => 'Xəta bax verdi: ',
'error-too-large' => 'Yüklənmə sayı limiti keçir!',
'btn-upload' => 'Yüklə',
'btn-uploading' => 'Yüklenir...',
'btn-close' => 'Bağla',
'btn-crop' => 'Kəs',
'btn-copy-crop' => 'Kopyala & Kəs',
'btn-cancel' => 'İmtina',
'btn-resize' => 'Ölçünü dəyiş',
'btn-crop-free' => 'Sərbəst',
'btn-confirm' => 'Təsdiq et',
'btn-open' => 'Qovluğu aç',
'resize-ratio' => 'Nisbət:',
'resize-scaled' => 'Böyüdüldü:',
'resize-true' => 'Bəli',
'resize-old-height' => 'Original Hündürlür:',
'resize-old-width' => 'Original En:',
'resize-new-height' => 'Hündürlük:',
'resize-new-width' => 'En:',
'locale-bootbox' => 'az',
];

Some files were not shown because too many files have changed in this diff Show More