Commit 64393a57 authored by Nicolas Widart's avatar Nicolas Widart

Squashed 'Modules/Media/' content from commit 551ec60

git-subtree-dir: Modules/Media
git-subtree-split: 551ec6006744ecfc3bbe43b4f650113746e25aef
parents
.php_cs.cache
vendor/
composer.lock
Modules/
/.project
build/
<?php
$finder = Symfony\CS\Finder\DefaultFinder::create()
->exclude('Modules')
->exclude('vendor')
->in(__DIR__)
;
return Symfony\CS\Config\Config::create()
->setUsingCache(true)
->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
->fixers(array(
// Concatenation should be used with at least one whitespace around.
'concat_with_spaces',
// Unused use statements must be removed.
'ordered_use',
// Removes extra empty lines.
'extra_empty_lines',
// Removes line breaks between use statements.
'remove_lines_between_uses',
// An empty line feed should precede a return statement.
'return',
// Unused use statements must be removed.
'unused_use',
// Remove trailing whitespace at the end of blank lines.
'whitespacy_lines',
// There MUST be one blank line after the namespace declaration.
'line_after_namespace',
// There should be exactly one blank line before a namespace declaration.
'single_blank_line_before_namespace',
// Each namespace use MUST go on its own line and there MUST be one blank line after the use statements block.
'single_line_after_imports',
// Ensure there is no code on the same line as the PHP open tag and it is followed by a blankline.
'blankline_after_open_tag',
// Remove duplicated semicolons.
'duplicate_semicolon',
// PHP multi-line arrays should have a trailing comma.
'multiline_array_trailing_comma',
// There should be no empty lines after class opening brace.
'no_blank_lines_after_class_opening',
// There should not be blank lines between docblock and the documented element.
'no_empty_lines_after_phpdocs',
// Phpdocs should start and end with content, excluding the very first and last line of the docblocks.
'phpdoc_trim',
// Removes line breaks between use statements.
'remove_lines_between_uses',
))
->finder($finder);
rules:
php.interface_has_no_interface_suffix:
enabled: false
language: php
php:
- 7
- 5.6
cache:
directories:
- $HOME/.composer/cache
env:
- LARAVEL_VERSION="~5.2" TESTBENCH_VERSION="~3.2"
before_script:
- travis_retry composer self-update
- travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-dist
script: phpunit
sudo: false
notifications:
slack: asgardcms:rQqM7V2EoZOrsv6GgAemZyOS
email:
- n.widart@gmail.com
- josh@joshbrown.me
This diff is collapsed.
This diff is collapsed.
$( document ).ready(function() {
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone(".dropzone", {
url: Asgard.dropzonePostUrl,
autoProcessQueue: true,
maxFilesize: maxFilesize,
acceptedFiles : acceptedFiles
});
myDropzone.on("queuecomplete", function(file, http) {
window.setTimeout(function(){
location.reload();
}, 1000);
});
myDropzone.on("sending", function(file, xhr, fromData) {
xhr.setRequestHeader("Authorization", AuthorizationHeaderValue);
if ($('.alert-danger').length > 0) {
$('.alert-danger').remove();
}
});
myDropzone.on("error", function(file, errorMessage) {
var html = '<div class="alert alert-danger" role="alert">' + errorMessage + '</div>';
$('.col-md-12').first().prepend(html);
setTimeout(function() {
myDropzone.removeFile(file);
}, 2000);
});
});
$( document ).ready(function() {
var $fileCount = $('.jsFileCount');
var sortableWrapper = $(".jsThumbnailImageWrapper");
var sortableSelection = sortableWrapper.not(".jsSingleThumbnailWrapper");
// This comes from new-file-link-single
if (typeof window.openMediaWindowSingle === 'undefined') {
window.mediaZone = '';
window.openMediaWindowSingle = function (event, zone) {
window.single = true;
window.old = false;
window.mediaZone = zone;
window.zoneWrapper = $(event.currentTarget).siblings('.jsThumbnailImageWrapper');
window.open(Asgard.mediaGridSelectUrl, '_blank', 'menubar=no,status=no,toolbar=no,scrollbars=yes,height=500,width=1000');
};
}
if (typeof window.includeMediaSingle === 'undefined') {
window.includeMediaSingle = function (mediaId, filePath, mediaType, mimetype) {
var mediaPlaceholder;
if (mediaType === 'image') {
mediaPlaceholder = '<img src="' + filePath + '" alt=""/>';
} else if (mediaType == 'video') {
mediaPlaceholder = '<video src="' + filePath + '" controls width="320"></video>';
} else if (mediaType == 'audio') {
mediaPlaceholder = '<audio controls><source src="' + filePath + '" type="' + mimetype + '"></audio>'
} else {
mediaPlaceholder = '<i class="fa fa-file" style="font-size: 50px;"></i>';
}
var html = '<figure data-id="'+ mediaId +'">' + mediaPlaceholder +
'<a class="jsRemoveSimpleLink" href="#" data-id="' + mediaId + '">' +
'<i class="fa fa-times-circle removeIcon"></i></a>' +
'</figure>';
window.zoneWrapper.append(html).fadeIn('slow', function() {
toggleButton($(this));
});
window.zoneWrapper.children('input').val(mediaId);
};
}
// This comes from new-file-link-multiple
if (typeof window.openMediaWindowMultiple === 'undefined') {
window.mediaZone = '';
window.openMediaWindowMultiple = function (event, zone) {
window.single = false;
window.old = false;
window.mediaZone = zone;
window.zoneWrapper = $(event.currentTarget).siblings('.jsThumbnailImageWrapper');
window.open(Asgard.mediaGridSelectUrl, '_blank', 'menubar=no,status=no,toolbar=no,scrollbars=yes,height=500,width=1000');
};
}
if (typeof window.includeMediaMultiple === 'undefined') {
window.includeMediaMultiple = function (mediaId, filePath, mediaType, mimetype) {
var mediaPlaceholder;
if (mediaType === 'image') {
mediaPlaceholder = '<img src="' + filePath + '" alt=""/>';
} else if (mediaType == 'video') {
mediaPlaceholder = '<video src="' + filePath + '" controls width="320"></video>';
} else if (mediaType == 'audio') {
mediaPlaceholder = '<audio controls><source src="' + filePath + '" type="' + mimetype + '"></audio>'
} else {
mediaPlaceholder = '<i class="fa fa-file" style="font-size: 50px;"></i>';
}
var html = '<figure data-id="' + mediaId + '">' + mediaPlaceholder +
'<a class="jsRemoveLink" href="#" data-id="' + mediaId + '">' +
'<i class="fa fa-times-circle removeIcon"></i>' +
'</a>' +
'<input type="hidden" name="medias_multi[' + window.mediaZone + '][files][]" value="' + mediaId + '">' +
'</figure>';
window.zoneWrapper.append(html).fadeIn();
window.zoneWrapper.trigger('sortupdate');
if ($fileCount.length > 0) {
var count = parseInt($fileCount.text());
$fileCount.text(count + 1);
}
};
}
// This comes from new-file-link-multiple
sortableWrapper.on('click', '.jsRemoveLink', function (e) {
e.preventDefault();
var pictureWrapper = $(this).parent();
var pictureSortable = pictureWrapper.parent();
pictureWrapper.fadeOut().remove();
pictureSortable.trigger('sortupdate');
if ($fileCount.length > 0) {
var count = parseInt($fileCount.text());
$fileCount.text(count - 1);
}
});
// This comes from new-file-link-multiple
sortableSelection.sortable({
items: "figure",
placeholder: 'ui-state-highlight',
cursor:'move',
helper: 'clone',
containment: 'parent',
forcePlaceholderSize: false,
forceHelperSize: true
});
sortableSelection.on('sortupdate', function(e, ui) {
var dataSortable = $(this).sortable('toArray', {attribute: 'data-id'});
$(this).find($('.orders')).val(dataSortable);
});
// This comes from new-file-link-single
sortableWrapper.off('click', '.jsRemoveSimpleLink');
sortableWrapper.on('click', '.jsRemoveSimpleLink', function (e) {
e.preventDefault();
$(e.delegateTarget).fadeOut('slow', function() {
toggleButton($(this));
}).children('figure').remove();
$(e.delegateTarget).children('input').val('');
});
function toggleButton(el) {
var browseButton = el.parent().find('.btn-browse');
browseButton.toggle();
}
});
<?php
namespace Modules\Media\Blade\Facades;
use Illuminate\Support\Facades\Facade;
class MediaMultipleDirective extends Facade
{
protected static function getFacadeAccessor()
{
return 'media.multiple.directive';
}
}
<?php
namespace Modules\Media\Blade\Facades;
use Illuminate\Support\Facades\Facade;
class MediaSingleDirective extends Facade
{
protected static function getFacadeAccessor()
{
return 'media.single.directive';
}
}
<?php
namespace Modules\Media\Blade;
class MediaMultipleDirective
{
/**
* @var string
*/
private $zone;
/**
* @var
*/
private $entity;
/**
* @var string|null
*/
private $view;
public function show($arguments)
{
$this->extractArguments($arguments);
$view = $this->view ?: 'media::admin.fields.new-file-link-multiple';
$zone = $this->zone;
if ($this->entity !== null) {
$media = $this->entity->filesByZone($this->zone)->get();
}
return view($view, compact('media', 'zone'));
}
/**
* Extract the possible arguments as class properties
* @param array $arguments
*/
private function extractArguments(array $arguments)
{
$this->zone = array_get($arguments, 0);
$this->entity = array_get($arguments, 1);
$this->view = array_get($arguments, 2);
}
}
<?php
namespace Modules\Media\Blade;
class MediaSingleDirective
{
/**
* @var string
*/
private $zone;
/**
* @var
*/
private $entity;
/**
* @var string|null
*/
private $view;
public function show($arguments)
{
$this->extractArguments($arguments);
$view = $this->view ?: 'media::admin.fields.new-file-link-single';
$zone = $this->zone;
if ($this->entity !== null) {
$media = $this->entity->filesByZone($this->zone)->first();
}
return view($view, compact('media', 'zone'));
}
/**
* Extract the possible arguments as class properties
* @param array $arguments
*/
private function extractArguments(array $arguments)
{
$this->zone = array_get($arguments, 0);
$this->entity = array_get($arguments, 1);
$this->view = array_get($arguments, 2);
}
}
<?php
namespace Modules\Media\Composers\Backend;
use Modules\Core\Foundation\Asset\Manager\AssetManager;
use Modules\Core\Foundation\Asset\Pipeline\AssetPipeline;
use Modules\Core\Foundation\Asset\Types\AssetTypeFactory;
class PartialAssetComposer
{
/**
* @var AssetManager
*/
private $assetManager;
/**
* @var AssetPipeline
*/
private $assetPipeline;
/**
* @var AssetTypeFactory
*/
private $assetFactory;
public function __construct()
{
$this->assetManager = app(AssetManager::class);
$this->assetPipeline = app(AssetPipeline::class);
$this->assetFactory = app(AssetTypeFactory::class);
}
public function compose()
{
$this->addAssets();
$this->requireAssets();
}
/**
* Add the assets from the config file on the asset manager
*/
private function addAssets()
{
foreach (config('asgard.media.assets.media-partial-assets', []) as $assetName => $path) {
$path = $this->assetFactory->make($path)->url();
$this->assetManager->addAsset($assetName, $path);
}
}
/**
* Require assets from asset manager
*/
private function requireAssets()
{
$css = config('asgard.media.assets.media-partial-required-assets.css');
$js = config('asgard.media.assets.media-partial-required-assets.js');
if (!empty($css)) {
$this->assetPipeline->requireCss($css);
}
if (!empty($js)) {
$this->assetPipeline->requireJs($js);
}
}
}
<?php
return [
/*
|--------------------------------------------------------------------------
| Define which assets will be available through the asset manager
|--------------------------------------------------------------------------
| These assets are registered on the asset manager
*/
'media-partial-assets' => [
'jquery-ui.js' => ['module' => 'dashboard:vendor/jquery-ui/jquery-ui.min.js'],
'media-partial.js' => ['module' => 'media:js/media-partial.js'],
],
/*
|--------------------------------------------------------------------------
| Define which default assets will always be included in your pages
| through the asset pipeline
|--------------------------------------------------------------------------
*/
'media-partial-required-assets' => [
'js' => [
'jquery-ui.js',
'media-partial.js',
],
],
];
<?php
return [
/*
|--------------------------------------------------------------------------
| Choose which filesystem you wish to use to store the media
|--------------------------------------------------------------------------
| Choose one or more of the filesystems you configured
| in app/config/filesystems.php
| Supported: "local", "s3"
*/
'filesystem' => 'local',
/*
|--------------------------------------------------------------------------
| The path where the media files will be uploaded
|--------------------------------------------------------------------------
| Note: Trailing slash is required
*/
'files-path' => '/assets/media/',
/*
|--------------------------------------------------------------------------
| Specify all the allowed file extensions a user can upload on the server
|--------------------------------------------------------------------------
*/
'allowed-types' => '.jpg,.png',
/*
|--------------------------------------------------------------------------
| Determine the max file size upload rate
| Defined in MB
|--------------------------------------------------------------------------
*/
'max-file-size' => '5',
/*
|--------------------------------------------------------------------------
| Determine the max total media folder size
|--------------------------------------------------------------------------
| Expressed in bytes
*/
'max-total-size' => 1000000000,
/*
|--------------------------------------------------------------------------
| Custom Sidebar Class
|--------------------------------------------------------------------------
| If you want to customise the admin sidebar ordering or grouping
| You can define your own sidebar class for this module.
| No custom sidebar: null
*/
'custom-sidebar' => null,
];
<?php
return [
'media.medias' => [
'index' => 'media::media.list resource',
'create' => 'media::media.create resource',
'edit' => 'media::media.edit resource',
'destroy' => 'media::media.destroy resource',
],
];
<?php
namespace Modules\Media\Console;
use Illuminate\Console\Command;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Modules\Media\Jobs\RebuildThumbnails;
use Modules\Media\Repositories\FileRepository;
class RefreshThumbnailCommand extends Command
{
use DispatchesJobs;
protected $name = 'asgard:media:refresh';
protected $description = 'Create and or refresh the thumbnails';
/**
* @var FileRepository
*/
private $file;
public function __construct(FileRepository $file)
{
parent::__construct();
$this->file = $file;
}
/**
* Execute the console command.
*
* @return mixed
*/
public function fire()
{
$this->line('Preparing to regenerate all thumbnails...');
$this->dispatch(new RebuildThumbnails($this->file->all()->pluck('path')));
$this->info('All thumbnails refreshed');
}
}
<?php
namespace Modules\Media\Contracts;
interface DeletingMedia
{
/**
* Get the entity ID
* @return int
*/
public function getEntityId();
/**
* Get the class name the imageables
* @return string
*/
public function getClassName();
}
<?php
namespace Modules\Media\Contracts;
interface StoringMedia
{
/**
* Return the entity
* @return \Illuminate\Database\Eloquent\Model
*/
public function getEntity();
/**
* Return the ALL data sent
* @return array
*/
public function getSubmissionData();
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateFilesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('media__files', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('filename');
$table->string('path');
$table->string('extension');
$table->string('mimetype');
$table->string('filesize');
$table->integer('folder_id')->unsigned();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('media__files');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateFileTranslationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(
'media__file_translations',
function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('file_id')->unsigned();
$table->string('locale')->index();
$table->string('description');
$table->string('alt_attribute');
$table->string('keywords');
$table->unique(['file_id', 'locale']);
$table->foreign('file_id')->references('id')->on('media__files')->onDelete('cascade');
}
);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('media__file_translations');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateImageLinksTable extends Migration
{
/**
* Run the migrations.
* @return void
*/
public function up()
{
Schema::create('media__imageables', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('file_id');
$table->integer('imageable_id');
$table->string('imageable_type');
$table->string('zone');
$table->timestamps();
});
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
Schema::drop('media__imageables');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddSortable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('media__imageables', function (Blueprint $table) {
$table->integer('order')->nullable()->after('zone');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('media__imageables', function (Blueprint $table) {
$table->dropColumn('order');
});
}
}
<?php
namespace Modules\Media\Database\Seeders;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Seeder;
class MediaDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
}
}
<?php
namespace Modules\Media\Entities;
use Dimsav\Translatable\Translatable;
use Illuminate\Database\Eloquent\Model;
use Modules\Core\Traits\NamespacedEntity;
use Modules\Media\Helpers\FileHelper;
use Modules\Media\Image\Facade\Imagy;
use Modules\Media\ValueObjects\MediaPath;
use Modules\Tag\Contracts\TaggableInterface;
use Modules\Tag\Traits\TaggableTrait;
/**
* Class File
* @package Modules\Media\Entities
* @property \Modules\Media\ValueObjects\MediaPath path
*/
class File extends Model implements TaggableInterface
{
use Translatable, NamespacedEntity, TaggableTrait;
/**
* All the different images types where thumbnails should be created
* @var array
*/
private $imageExtensions = ['jpg', 'png', 'jpeg', 'gif'];
protected $table = 'media__files';
public $translatedAttributes = ['description', 'alt_attribute', 'keywords'];
protected $fillable = [
'description',
'alt_attribute',
'keywords',
'filename',
'path',
'extension',
'mimetype',
'width',
'height',
'filesize',
'folder_id',
];
protected $appends = ['path_string', 'media_type'];
protected static $entityNamespace = 'asgardcms/media';
public function getPathAttribute($value)
{
return new MediaPath($value);
}
public function getPathStringAttribute()
{
return (string) $this->path;
}
public function getMediaTypeAttribute()
{
return FileHelper::getTypeByMimetype($this->mimetype);
}
public function isImage()
{
return in_array(pathinfo($this->path, PATHINFO_EXTENSION), $this->imageExtensions);
}
public function getThumbnail($type)
{
if ($this->isImage() && $this->getKey()) {
return Imagy::getThumbnail($this->path, $type);
}
return false;
}
}
<?php
namespace Modules\Media\Entities;
use Illuminate\Database\Eloquent\Model;
class FileTranslation extends Model
{
public $timestamps = false;
protected $fillable = ['description', 'alt_attribute', 'keywords'];
protected $table = 'media__file_translations';
}
<?php
namespace Modules\Media\Events;
use Modules\Media\Entities\File;
class FileWasLinked
{
/**
* @var File
*/
public $file;
/**
* The entity that was linked to a file
* @var object
*/
public $entity;
/**
* @param File $file
* @param object $entity
*/
public function __construct(File $file, $entity)
{
$this->file = $file;
$this->entity = $entity;
}
}
<?php
namespace Modules\Media\Events;
class FileWasUnlinked
{
/**
* The imageable id
* @var int
*/
public $imageableId;
/**
* @param int $imageableId
*/
public function __construct($imageableId)
{
$this->imageableId = $imageableId;
}
}
<?php
namespace Modules\Media\Events;
use Modules\Media\Entities\File;
class FileWasUploaded
{
/**
* @var File
*/
public $file;
/**
* @param File $file
*/
public function __construct(File $file)
{
$this->file = $file;
}
}
<?php
namespace Modules\Media\Events\Handlers;
use Modules\Media\Contracts\StoringMedia;
class HandleMediaStorage
{
public function handle($event = null)
{
if ($event instanceof StoringMedia) {
$this->handleMultiMedia($event);
$this->handleSingleMedia($event);
}
}
/**
* Handle the request for the multi media partial
* @param StoringMedia $event
*/
private function handleMultiMedia(StoringMedia $event)
{
$entity = $event->getEntity();
$postMedias = array_get($event->getSubmissionData(), 'medias_multi', []);
foreach ($postMedias as $zone => $attributes) {
$syncList = [];
$orders = $this->getOrdersFrom($attributes);
foreach (array_get($attributes, 'files', []) as $fileId) {
$syncList[$fileId] = [];
$syncList[$fileId]['imageable_type'] = get_class($entity);
$syncList[$fileId]['zone'] = $zone;
$syncList[$fileId]['order'] = (int) array_search($fileId, $orders);
}
$entity->filesByZone($zone)->sync($syncList);
}
}
/**
* Handle the request to parse single media partials
* @param StoringMedia $event
*/
private function handleSingleMedia(StoringMedia $event)
{
$entity = $event->getEntity();
$postMedia = array_get($event->getSubmissionData(), 'medias_single', []);
foreach ($postMedia as $zone => $fileId) {
if (!empty($fileId)) {
$entity->filesByZone($zone)->sync([$fileId => ['imageable_type' => get_class($entity), 'zone' => $zone, 'order' => null]]);
} else {
$entity->filesByZone($zone)->sync([]);
}
}
}
/**
* Parse the orders input and return an array of file ids, in order
* @param array $attributes
* @return array
*/
private function getOrdersFrom(array $attributes)
{
$orderString = array_get($attributes, 'orders');
if ($orderString === null) {
return [];
}
$orders = explode(',', $orderString);
return array_filter($orders);
}
}
<?php
namespace Modules\Media\Events\Handlers;
use Illuminate\Support\Facades\DB;
use Modules\Media\Contracts\DeletingMedia;
class RemovePolymorphicLink
{
public function handle($event = null)
{
if ($event instanceof DeletingMedia) {
DB::table('media__imageables')->where('imageable_id', $event->getEntityId())
->where('imageable_type', $event->getClassName())->delete();
}
}
}
<?php
namespace Modules\Media\Helpers;
use Illuminate\Support\Str;
class FileHelper
{
/**
* Get first token of string before delimiter
* @param $mimetype
* @return string
*/
public static function getTypeByMimetype($mimetype)
{
return strtok($mimetype, '/');
}
/**
* Get Font Awesome icon for various files
* @param string $mediaType
* @return string
*/
public static function getFaIcon($mediaType)
{
switch ($mediaType) {
case 'video':
return 'fa-file-video-o';
case 'audio':
return 'fa-file-audio-o';
default:
return 'fa-file';
}
}
public static function slug($name)
{
$extension = self::getExtension($name);
$name = str_replace($extension, '', $name);
$name = Str::slug($name);
return $name . strtolower($extension);
}
/**
* Get the extension from the given name
* @param $name
* @return string
*/
private static function getExtension($name)
{
return substr($name, strrpos($name, '.'));
}
}
<?php
namespace Modules\Media\Http\Controllers\Admin;
use Illuminate\Contracts\Config\Repository;
use Modules\Core\Http\Controllers\Admin\AdminBaseController;
use Modules\Media\Entities\File;
use Modules\Media\Http\Requests\UpdateMediaRequest;
use Modules\Media\Image\Imagy;
use Modules\Media\Image\ThumbnailManager;
use Modules\Media\Repositories\FileRepository;
class MediaController extends AdminBaseController
{
/**
* @var FileRepository
*/
private $file;
/**
* @var Repository
*/
private $config;
/**
* @var Imagy
*/
private $imagy;
/**
* @var ThumbnailManager
*/
private $thumbnailsManager;
public function __construct(FileRepository $file, Repository $config, Imagy $imagy, ThumbnailManager $thumbnailsManager)
{
parent::__construct();
$this->file = $file;
$this->config = $config;
$this->imagy = $imagy;
$this->thumbnailsManager = $thumbnailsManager;
}
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$files = $this->file->all();
$config = $this->config->get('asgard.media.config');
return view('media::admin.index', compact('files', 'config'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
return view('media.create');
}
/**
* Show the form for editing the specified resource.
*
* @param File $file
* @return Response
*/
public function edit(File $file)
{
$thumbnails = $this->thumbnailsManager->all();
return view('media::admin.edit', compact('file', 'thumbnails'));
}
/**
* Update the specified resource in storage.
*
* @param File $file
* @param UpdateMediaRequest $request
* @return Response
*/
public function update(File $file, UpdateMediaRequest $request)
{
$this->file->update($file, $request->all());
return redirect()->route('admin.media.media.index')
->withSuccess(trans('media::messages.file updated'));
}
/**
* Remove the specified resource from storage.
*
* @param File $file
* @internal param int $id
* @return Response
*/
public function destroy(File $file)
{
$this->imagy->deleteAllFor($file);
$this->file->destroy($file);
return redirect()->route('admin.media.media.index')
->withSuccess(trans('media::messages.file deleted'));
}
}
<?php
namespace Modules\Media\Http\Controllers\Admin;
use Modules\Core\Http\Controllers\Admin\AdminBaseController;
use Modules\Media\Image\ThumbnailManager;
use Modules\Media\Repositories\FileRepository;
class MediaGridController extends AdminBaseController
{
/**
* @var FileRepository
*/
private $file;
/**
* @var ThumbnailManager
*/
private $thumbnailsManager;
public function __construct(FileRepository $file, ThumbnailManager $thumbnailsManager)
{
parent::__construct();
$this->file = $file;
$this->thumbnailsManager = $thumbnailsManager;
}
/**
* A grid view for the upload button
* @return \Illuminate\View\View
*/
public function index()
{
$files = $this->file->all();
$thumbnails = $this->thumbnailsManager->all();
return view('media::admin.grid.general', compact('files', 'thumbnails'));
}
/**
* A grid view of uploaded files used for the wysiwyg editor
* @return \Illuminate\View\View
*/
public function ckIndex()
{
$files = $this->file->all();
$thumbnails = $this->thumbnailsManager->all();
return view('media::admin.grid.ckeditor', compact('files', 'thumbnails'));
}
}
<?php
namespace Modules\Media\Http\Controllers\Api;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Response;
use Modules\Media\Entities\File;
use Modules\Media\Events\FileWasLinked;
use Modules\Media\Events\FileWasUnlinked;
use Modules\Media\Events\FileWasUploaded;
use Modules\Media\Helpers\FileHelper;
use Modules\Media\Http\Requests\UploadMediaRequest;
use Modules\Media\Image\Imagy;
use Modules\Media\Repositories\FileRepository;
use Modules\Media\Services\FileService;
class MediaController extends Controller
{
/**
* @var FileService
*/
private $fileService;
/**
* @var FileRepository
*/
private $file;
/**
* @var Imagy
*/
private $imagy;
public function __construct(FileService $fileService, FileRepository $file, Imagy $imagy)
{
$this->fileService = $fileService;
$this->file = $file;
$this->imagy = $imagy;
}
public function all()
{
$files = $this->file->all();
return [
'count' => $files->count(),
'data' => $files,
];
}
/**
* Store a newly created resource in storage.
*
* @param UploadMediaRequest $request
* @return Response
*/
public function store(UploadMediaRequest $request)
{
$savedFile = $this->fileService->store($request->file('file'));
if (is_string($savedFile)) {
return Response::json([
'error' => $savedFile,
], 409);
}
event(new FileWasUploaded($savedFile));
return Response::json($savedFile->toArray());
}
/**
* Link the given entity with a media file
*
* @param Request $request
*/
public function linkMedia(Request $request)
{
$mediaId = $request->get('mediaId');
$entityClass = $request->get('entityClass');
$entityId = $request->get('entityId');
$order = $request->get('order');
$entity = $entityClass::find($entityId);
$zone = $request->get('zone');
$entity->files()->attach($mediaId, [
'imageable_type' => $entityClass,
'zone' => $zone,
'order' => $order,
]);
$imageable = DB::table('media__imageables')->whereFileId($mediaId)
->whereZone($zone)
->whereImageableType($entityClass)
->first();
$file = $this->file->find($imageable->file_id);
$mediaType = FileHelper::getTypeByMimetype($file->mimetype);
$thumbnailPath = $this->getThumbnailPathFor($mediaType, $file);
event(new FileWasLinked($file, $entity));
return Response::json([
'error' => false,
'message' => 'The link has been added.',
'result' => [
'path' => $thumbnailPath,
'imageableId' => $imageable->id,
'mediaType' => $mediaType,
'mimetype' => $file->mimetype,
],
]);
}
/**
* Remove the record in the media__imageables table for the given id
*
* @param Request $request
*/
public function unlinkMedia(Request $request)
{
$imageableId = $request->get('imageableId');
$deleted = DB::table('media__imageables')->whereId($imageableId)->delete();
if (! $deleted) {
return Response::json([
'error' => true,
'message' => 'The file was not found.',
]);
}
event(new FileWasUnlinked($imageableId));
return Response::json([
'error' => false,
'message' => 'The link has been removed.',
]);
}
/**
* Sort the record in the media__imageables table for the given array
* @param Request $request
*/
public function sortMedia(Request $request)
{
$imageableIdArray = $request->get('sortable');
$order = 1;
foreach ($imageableIdArray as $id) {
DB::table('media__imageables')->whereId($id)->update(['order' => $order]);
$order++;
}
return Response::json(['error' => false, 'message' => 'The items have been reorder.']);
}
/**
* Get the path for the given file and type
* @param string $mediaType
* @param File $file
* @return string
*/
private function getThumbnailPathFor($mediaType, File $file)
{
if ($mediaType === 'image') {
return $this->imagy->getThumbnail($file->path, 'mediumThumb');
}
return $file->path->getRelativeUrl();
}
}
<?php
namespace Modules\Media\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateMediaRequest extends FormRequest
{
public function rules()
{
return [];
}
public function authorize()
{
return true;
}
public function messages()
{
return [];
}
}
<?php
namespace Modules\Media\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UploadMediaRequest extends FormRequest
{
public function rules()
{
return [
'file' => ['required', 'max_size'],
];
}
public function authorize()
{
return true;
}
public function messages()
{
$bytes = config('asgard.media.config.max-total-size');
$size = $this->formatBytes($bytes);
return [
'file.max_size' => trans('media::media.validation.max_size', ['size' => $size]),
];
}
public function formatBytes($bytes, $precision = 2)
{
$units = [
trans('media::media.file-sizes.B'),
trans('media::media.file-sizes.KB'),
trans('media::media.file-sizes.MB'),
trans('media::media.file-sizes.GB'),
trans('media::media.file-sizes.TB'),
];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . ' ' . $units[$pow];
}
}
<?php
use Illuminate\Routing\Router;
/** @var Router $router */
$router->group(['middleware' => 'api.token'], function (Router $router) {
$router->post('file', [
'uses' => 'MediaController@store',
'as' => 'api.media.store',
'middleware' => 'token-can:media.medias.create',
]);
$router->post('media/link', [
'uses' => 'MediaController@linkMedia',
'as' => 'api.media.link',
]);
$router->post('media/unlink', [
'uses' => 'MediaController@unlinkMedia',
'as' => 'api.media.unlink',
]);
$router->get('media/all', [
'uses' => 'MediaController@all',
'as' => 'api.media.all',
'middleware' => 'token-can:media.medias.index',
]);
$router->post('media/sort', [
'uses' => 'MediaController@sortMedia',
'as' => 'api.media.sort',
]);
});
<?php
use Illuminate\Routing\Router;
/** @var Router $router */
$router->bind('media', function ($id) {
return app(\Modules\Media\Repositories\FileRepository::class)->find($id);
});
$router->group(['prefix' => '/media'], function (Router $router) {
$router->get('media', [
'as' => 'admin.media.media.index',
'uses' => 'MediaController@index',
'middleware' => 'can:media.medias.index',
]);
$router->get('media/create', [
'as' => 'admin.media.media.create',
'uses' => 'MediaController@create',
'middleware' => 'can:media.medias.create',
]);
$router->post('media', [
'as' => 'admin.media.media.store',
'uses' => 'MediaController@store',
'middleware' => 'can:media.medias.create',
]);
$router->get('media/{media}/edit', [
'as' => 'admin.media.media.edit',
'uses' => 'MediaController@edit',
'middleware' => 'can:media.medias.edit',
]);
$router->put('media/{media}', [
'as' => 'admin.media.media.update',
'uses' => 'MediaController@update',
'middleware' => 'can:media.medias.edit',
]);
$router->delete('media/{media}', [
'as' => 'admin.media.media.destroy',
'uses' => 'MediaController@destroy',
'middleware' => 'can:media.medias.destroy',
]);
$router->get('media-grid/index', [
'uses' => 'MediaGridController@index',
'as' => 'media.grid.select',
'middleware' => 'can:media.medias.index',
]);
$router->get('media-grid/ckIndex', [
'uses' => 'MediaGridController@ckIndex',
'as' => 'media.grid.ckeditor',
'middleware' => 'can:media.medias.index',
]);
});
<?php
namespace Modules\Media\Image\Facade;
use Illuminate\Support\Facades\Facade;
class Imagy extends Facade
{
protected static function getFacadeAccessor()
{
return 'imagy';
}
}
<?php
namespace Modules\Media\Image;
interface ImageFactoryInterface
{
/**
* Return a new Manipulation class
* @param string $manipulation
* @return \Modules\Media\Image\ImageHandlerInterface
*/
public function make($manipulation);
}
<?php
namespace Modules\Media\Image;
interface ImageHandlerInterface
{
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options);
}
<?php
namespace Modules\Media\Image;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\ServiceProvider;
use Modules\Media\Image\Intervention\InterventionFactory;
class ImageServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->bind(ImageFactoryInterface::class, InterventionFactory::class);
$this->app->singleton(ThumbnailManager::class, function () {
return new ThumbnailManagerRepository();
});
$this->app['imagy'] = $this->app->share(function ($app) {
$factory = new InterventionFactory();
return new Imagy($factory, $app[ThumbnailManager::class], $app['config']);
});
$this->app->booting(function () {
$loader = AliasLoader::getInstance();
$loader->alias('Imagy', Facade\Imagy::class);
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return ['imagy'];
}
}
<?php
namespace Modules\Media\Image;
use GuzzleHttp\Psr7\Stream;
use Illuminate\Contracts\Filesystem\Factory;
use Intervention\Image\ImageManager;
use Modules\Media\Entities\File;
use Modules\Media\ValueObjects\MediaPath;
class Imagy
{
/**
* @var \Intervention\Image\Image
*/
private $image;
/**
* @var ImageFactoryInterface
*/
private $imageFactory;
/**
* @var ThumbnailManager
*/
private $manager;
/**
* All the different images types where thumbnails should be created
* @var array
*/
private $imageExtensions = ['jpg', 'png', 'jpeg', 'gif'];
/**
* @var Factory
*/
private $filesystem;
/**
* @param ImageFactoryInterface $imageFactory
* @param ThumbnailManager $manager
*/
public function __construct(ImageFactoryInterface $imageFactory, ThumbnailManager $manager)
{
$this->image = app(ImageManager::class);
$this->filesystem = app(Factory::class);
$this->imageFactory = $imageFactory;
$this->manager = $manager;
}
/**
* Get an image in the given thumbnail options
* @param string $path
* @param string $thumbnail
* @param bool $forceCreate
* @return string
*/
public function get($path, $thumbnail, $forceCreate = false)
{
if (!$this->isImage($path)) {
return;
}
$filename = config('asgard.media.config.files-path') . $this->newFilename($path, $thumbnail);
if ($this->returnCreatedFile($filename, $forceCreate)) {
return $filename;
}
if ($this->fileExists($filename) === true) {
$this->filesystem->disk($this->getConfiguredFilesystem())->delete($filename);
}
$mediaPath = (new MediaPath($filename))->getUrl();
$this->makeNew($path, $mediaPath, $thumbnail);
return (new MediaPath($filename))->getUrl();
}
/**
* Return the thumbnail path
* @param string|File $originalImage
* @param string $thumbnail
* @return string
*/
public function getThumbnail($originalImage, $thumbnail)
{
if ($originalImage instanceof File) {
$originalImage = $originalImage->path;
}
if (!$this->isImage($originalImage)) {
if ($originalImage instanceof MediaPath) {
return $originalImage->getUrl();
}
return (new MediaPath($originalImage))->getRelativeUrl();
}
$path = config('asgard.media.config.files-path') . $this->newFilename($originalImage, $thumbnail);
return (new MediaPath($path))->getUrl();
}
/**
* Create all thumbnails for the given image path
* @param MediaPath $path
*/
public function createAll(MediaPath $path)
{
if (!$this->isImage($path)) {
return;
}
foreach ($this->manager->all() as $thumbnail) {
$image = $this->image->make($this->filesystem->disk($this->getConfiguredFilesystem())->get($this->getDestinationPath($path->getRelativeUrl())));
$filename = config('asgard.media.config.files-path') . $this->newFilename($path, $thumbnail->name());
foreach ($thumbnail->filters() as $manipulation => $options) {
$image = $this->imageFactory->make($manipulation)->handle($image, $options);
}
$image = $image->stream(pathinfo($path, PATHINFO_EXTENSION), array_get($thumbnail->filters(), 'quality', 90));
$this->writeImage($filename, $image);
}
}
/**
* Prepend the thumbnail name to filename
* @param $path
* @param $thumbnail
* @return mixed|string
*/
private function newFilename($path, $thumbnail)
{
$filename = pathinfo($path, PATHINFO_FILENAME);
return $filename . '_' . $thumbnail . '.' . pathinfo($path, PATHINFO_EXTENSION);
}
/**
* Return the already created file if it exists and force create is false
* @param string $filename
* @param bool $forceCreate
* @return bool
*/
private function returnCreatedFile($filename, $forceCreate)
{
return $this->fileExists($filename) && $forceCreate === false;
}
/**
* Write the given image
* @param string $filename
* @param Stream $image
*/
private function writeImage($filename, Stream $image)
{
$filename = $this->getDestinationPath($filename);
$resource = $image->detach();
$config = [
'visibility' => 'public',
'mimetype' => \GuzzleHttp\Psr7\mimetype_from_filename($filename),
];
if ($this->fileExists($filename)) {
return $this->filesystem->disk($this->getConfiguredFilesystem())->updateStream($filename, $resource, $config);
}
$this->filesystem->disk($this->getConfiguredFilesystem())->writeStream($filename, $resource, $config);
}
/**
* Make a new image
* @param MediaPath $path
* @param string $filename
* @param string null $thumbnail
*/
private function makeNew(MediaPath $path, $filename, $thumbnail)
{
$image = $this->image->make($path->getUrl());
foreach ($this->manager->find($thumbnail) as $manipulation => $options) {
$image = $this->imageFactory->make($manipulation)->handle($image, $options);
}
$image = $image->stream(pathinfo($path, PATHINFO_EXTENSION));
$this->writeImage($filename, $image);
}
/**
* Check if the given path is en image
* @param string $path
* @return bool
*/
public function isImage($path)
{
return in_array(pathinfo($path, PATHINFO_EXTENSION), $this->imageExtensions);
}
/**
* Delete all files on disk for the given file in storage
* This means the original and the thumbnails
* @param $file
* @return bool
*/
public function deleteAllFor(File $file)
{
if (!$this->isImage($file->path)) {
return $this->filesystem->disk($this->getConfiguredFilesystem())->delete($this->getDestinationPath($file->path->getRelativeUrl()));
}
$paths[] = $this->getDestinationPath($file->path->getRelativeUrl());
$fileName = pathinfo($file->path, PATHINFO_FILENAME);
$extension = pathinfo($file->path, PATHINFO_EXTENSION);
foreach ($this->manager->all() as $thumbnail) {
$path = config('asgard.media.config.files-path') . "{$fileName}_{$thumbnail->name()}.{$extension}";
if ($this->fileExists($this->getDestinationPath($path))) {
$paths[] = (new MediaPath($this->getDestinationPath($path)))->getRelativeUrl();
}
}
return $this->filesystem->disk($this->getConfiguredFilesystem())->delete($paths);
}
private function getConfiguredFilesystem()
{
return config('asgard.media.config.filesystem');
}
/**
* @param $filename
* @return bool
*/
private function fileExists($filename)
{
return $this->filesystem->disk($this->getConfiguredFilesystem())->exists($filename);
}
/**
* @param string $path
* @return string
*/
private function getDestinationPath($path)
{
if ($this->getConfiguredFilesystem() === 'local') {
return basename(public_path()) . $path;
}
return $path;
}
}
<?php
namespace Modules\Media\Image\Intervention;
use Modules\Media\Image\ImageFactoryInterface;
class InterventionFactory implements ImageFactoryInterface
{
/**
* @param string $manipulation
* @return \Modules\Media\Image\ImageHandlerInterface
*/
public function make($manipulation)
{
$class = 'Modules\\Media\\Image\\Intervention\\Manipulations\\' . ucfirst($manipulation);
return new $class();
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Blur implements ImageHandlerInterface
{
private $defaults = [
'amount' => 1,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->blur($options['amount']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Brightness implements ImageHandlerInterface
{
private $defaults = [
'level' => 1,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->brightness($options['level']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class CanvasResize implements ImageHandlerInterface
{
private $defaults = [
'width' => 100,
'height' => 100,
'anchor' => 'center',
'relative' => false,
'bgcolor' => 'rgba(255, 255, 255, 0)',
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->resizeCanvas($options['width'], $options['height'], $options['anchor'], $options['relative'], $options['bgcolor']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Colorize implements ImageHandlerInterface
{
private $defaults = [
'red' => 100,
'green' => 100,
'blue' => 100,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->colorize($options['red'], $options['green'], $options['blue']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Contrast implements ImageHandlerInterface
{
private $defaults = [
'level' => 0,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->contrast($options['level']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Crop implements ImageHandlerInterface
{
private $defaults = [
'width' => '100',
'height' => '100',
'x' => null,
'y' => null,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return mixed
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->crop($options['width'], $options['height'], $options['x'], $options['y']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Fit implements ImageHandlerInterface
{
private $defaults = [
'width' => 100,
'height' => null,
'position' => 'center',
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
$callback = isset($options['callback']) ? $options['callback'] : null;
return $image->fit($options['width'], $options['height'], $callback, $options['position']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Flip implements ImageHandlerInterface
{
private $defaults = [
'mode' => 'h',
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->flip($options['mode']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Gamma implements ImageHandlerInterface
{
private $defaults = [
'correction' => 0,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->gamma($options['correction']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Greyscale implements ImageHandlerInterface
{
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
return $image->greyscale();
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Heighten implements ImageHandlerInterface
{
private $defaults = [
'height' => 0,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
$callback = isset($options['callback']) ? $options['callback'] : null;
return $image->heighten($options['height'], $callback);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Invert implements ImageHandlerInterface
{
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
return $image->invert();
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class LimitColors implements ImageHandlerInterface
{
private $defaults = [
'count' => 255,
'matte' => null,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->limitColors($options['count'], $options['matte']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Opacity implements ImageHandlerInterface
{
private $defaults = [
'transparency' => 50,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->opacity($options['transparency']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Orientate implements ImageHandlerInterface
{
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
return $image->orientate();
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Pixelate implements ImageHandlerInterface
{
private $defaults = [
'size' => 0,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->pixelate($options['size']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Quality implements ImageHandlerInterface
{
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
return $image;
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Resize implements ImageHandlerInterface
{
private $defaults = [
'width' => 200,
'height' => 200,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
$callback = isset($options['callback']) ? $options['callback'] : null;
return $image->resize($options['width'], $options['height'], $callback);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Rotate implements ImageHandlerInterface
{
private $defaults = [
'angle' => 45,
'bgcolor' => '#000000',
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->rotate($options['angle'], $options['bgcolor']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Sharpen implements ImageHandlerInterface
{
private $defaults = [
'amount' => 10,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->sharpen($options['amount']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Trim implements ImageHandlerInterface
{
private $defaults = [
'base' => 'top-left',
'away' => ['top', 'bottom', 'left', 'right'],
'tolerance' => 0,
'feather' => 0,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->trim($options['base'], $options['away'], $options['tolerance'], $options['feather']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Watermark implements ImageHandlerInterface
{
private $defaults = [
'source' => 'public/assets/watermark.png',
'position' => 'bottom-right',
'x' => null,
'y' => null,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->insert($options['source'], $options['position'], $options['x'], $options['y']);
}
}
<?php
namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Widen implements ImageHandlerInterface
{
private $defaults = [
'width' => 0,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
$callback = isset($options['callback']) ? $options['callback'] : null;
return $image->widen($options['width'], $callback);
}
}
<?php
namespace Modules\Media\Image;
class Thumbnail
{
/**
* @var array
*/
private $filters;
/**
* @var string
*/
private $name;
/**
* @param $name
* @param $filters
*/
private function __construct($name, $filters)
{
$this->filters = $filters;
$this->name = $name;
}
/**
* @param $thumbnailDefinition
* @return static
*/
public static function make($thumbnailDefinition)
{
$name = key($thumbnailDefinition);
return new static($name, $thumbnailDefinition[$name]);
}
/**
* Make multiple thumbnail classes with the given array
* @param array $thumbnailDefinitions
* @return array
*/
public static function makeMultiple(array $thumbnailDefinitions)
{
$thumbnails = [];
foreach ($thumbnailDefinitions as $name => $thumbnail) {
$thumbnails[] = self::make([$name => $thumbnail]);
}
return $thumbnails;
}
/**
* Return the thumbnail name
* @return string
*/
public function name()
{
return $this->name;
}
/**
* @return array
*/
public function filters()
{
return $this->filters;
}
/**
* Return the first width option found in the filters
* @return int
*/
public function width()
{
return $this->getFirst('width');
}
/**
* Return the first height option found in the filters
* @return int
*/
public function height()
{
return $this->getFirst('height');
}
/**
* Get the thumbnail size in format: width x height
* @return string
*/
public function size()
{
return $this->width() . 'x' . $this->height();
}
/**
* Get the first found key in filters
* @param string $key
* @return int
*/
private function getFirst($key)
{
foreach ($this->filters as $filter) {
if (isset($filter[$key])) {
return (int) $filter[$key];
}
}
}
}
<?php
namespace Modules\Media\Image;
interface ThumbnailManager
{
/**
* Register a thumbnail
* @param string $name
* @param array $filters
* @return void
*/
public function registerThumbnail($name, array $filters);
/**
* Return all registered thumbnails
* @return array
*/
public function all();
/**
* Find the filters for the given thumbnail
* @param string $thumbnail
* @return array
*/
public function find($thumbnail);
}
<?php
namespace Modules\Media\Image;
class ThumbnailManagerRepository implements ThumbnailManager
{
/**
* @var array
*/
private $thumbnails = [];
public function registerThumbnail($name, array $filters)
{
$this->thumbnails[$name] = Thumbnail::make([$name => $filters]);
}
/**
* Return all registered thumbnails
* @return array
*/
public function all()
{
return $this->thumbnails;
}
/**
* Find the filters for the given thumbnail
* @param $thumbnail
* @return array
*/
public function find($thumbnail)
{
foreach ($this->all() as $thumb) {
if ($thumb->name() === $thumbnail) {
return $thumb->filters();
}
}
return [];
}
}
<?php
namespace Modules\Media\Jobs;
use App\Jobs\Job;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Modules\Media\ValueObjects\MediaPath;
class CreateThumbnails extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
/**
* @var MediaPath
*/
private $path;
public function __construct(MediaPath $path)
{
$this->path = $path;
}
public function handle()
{
$imagy = app('imagy');
app('log')->info('Generating thumbnails for path: ' . $this->path);
$imagy->createAll($this->path);
}
}
<?php
namespace Modules\Media\Jobs;
use App\Jobs\Job;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
class RebuildThumbnails extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
/**
* @var Collection
*/
private $paths;
public function __construct(Collection $paths)
{
$this->paths = $paths;
}
public function handle()
{
$imagy = app('imagy');
foreach ($this->paths as $path) {
try {
$imagy->createAll($path);
app('log')->info('Generating thumbnails for path: ' . $path);
} catch (\Exception $e) {
app('log')->warning('File not found: ' . $path);
}
}
}
}
# License (MIT)
Copyright (c) 2016 Nicolas Widart , n.widart@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment