Skip to content

Commit

Permalink
Feature with spatie/image (#7)
Browse files Browse the repository at this point in the history
* add Spatie Image
remove bkwld/croppa

* plug Spatie image to getCroppaUrl

* fix image url with Spatie Image

* add config for images thumbnails

* add delete thumbnails

* Fix styling

* add controller, route for rendering images on the fly

---------

Co-authored-by: webplusmultimedia <[email protected]>
  • Loading branch information
webplusmultimedia and webplusmultimedia committed Apr 17, 2024
1 parent 94c19f9 commit 9667987
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 12 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
],
"require": {
"php": "^8.1",
"bkwld/croppa": "^6.0",
"filament/filament": "^3.0",
"illuminate/contracts": "^10.0",
"spatie/image": "^2.2",
"spatie/laravel-package-tools": "^1.15.0"
},
"require-dev": {
Expand Down
11 changes: 11 additions & 0 deletions config/gallery-json-media.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,20 @@
declare(strict_types=1);

// config for WebplusMultimedia\GalleryJsonMedia
use Spatie\Image\Manipulations;

return [
'disk' => 'public',
'root_directory' => 'web_attachments',
'images' => [
'path' => 'storage/(.*)$',
'signing_key' => 'app.key',
'driver' => 'imagick', // gd or imagick
'quality' => 80,
'thumbnails-crop-method' => Manipulations::CROP_CENTER,
'thumbnails-saved-format' => null, // Manipulations::FORMAT_PNG / following formats are supported: FORMAT_JPG, FORMAT_PJPG, FORMAT_PNG, FORMAT_GIF, FORMAT_WEBP and FORMAT_TIFF

],
'form' => [
'default' => [
'image_accepted_text' => '.jpg, .svg, .png, .webp, .avif',
Expand Down
10 changes: 10 additions & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

use GalleryJsonMedia\JsonMedia\Controllers\JsonImageController;
use GalleryJsonMedia\JsonMedia\UrlParser;
use Illuminate\Support\Facades\Route;

Route::get('{path}', [JsonImageController::class, 'handle'])
->where('path', UrlParser::make()->routePattern());
12 changes: 8 additions & 4 deletions src/Form/JsonMediaGallery.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

namespace GalleryJsonMedia\Form;

use Bkwld\Croppa\Facades\Croppa;
use Closure;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\BaseFileUpload;
use GalleryJsonMedia\Form\Concerns\HasCustomProperties;
use GalleryJsonMedia\JsonMedia\ImageManipulation\Croppa;
use GalleryJsonMedia\Support\Concerns\HasThumbProperties;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Validator;
Expand Down Expand Up @@ -56,6 +56,8 @@ protected function setUp(): void

$this->multiple();

$this->diskName = config('gallery-json-media.disk');

$this->registerActions(
actions: [
static fn (JsonMediaGallery $component): ?Action => $component->getCustomPropertiesAction(),
Expand Down Expand Up @@ -141,13 +143,15 @@ public function getUploadedFiles(): array

$fileName = data_get($file, 'file');
$mimeType = data_get($file, 'mime_type');

$url[$fileKey] = [
'name' => $fileName,
'size' => data_get($file, 'size'),
'mime_type' => $mimeType,
'url' => ($this->isImageFile($mimeType) and ! $this->isSvgFile($mimeType))
? url(Croppa::url($storage->url($fileName), $this->getThumbWidth()))
: $storage->url($fileName),
? (new Croppa(filesystem: $storage, filePath: $fileName, width: $this->getThumbWidth(), height: $this->getThumbHeight()))
->url()
: $storage->url($fileName),
];
}

Expand All @@ -170,7 +174,7 @@ public function saveUploadedFiles(): void
$state = array_filter(array_map(function (array $file) use ($storage) {
if (isset($file['deleted']) and $file['deleted']) {
try {
Croppa::reset($storage->url($file['file'])); // remove all thumbs
(new Croppa($storage, $file['file']))->reset(); // remove all thumbs
} catch (\Throwable) {
//never mind if file doesn't exist
}
Expand Down
61 changes: 61 additions & 0 deletions src/JsonMedia/Controllers/JsonImageController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);
/**
* Created by PhpStorm.
*
* @category Category
*
* @author daniel
*
* @link http://webplusm.net
* Date: 16/04/2024 10:09
*/

namespace GalleryJsonMedia\JsonMedia\Controllers;

use GalleryJsonMedia\JsonMedia\ImageManipulation\Croppa;
use GalleryJsonMedia\JsonMedia\UrlParser;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\Local\LocalFilesystemAdapter;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class JsonImageController extends Controller
{
public function __construct(protected UrlParser $urlParser)
{
}

public function handle(string $requestPath)
{
// Validate the signing token
$token = $this->urlParser->signingToken($requestPath);

if ($token !== request('_token')) {
throw new NotFoundHttpException('Token mismatch');
}

$url = $this->urlParser->parse($requestPath);

/** @var FilesystemAdapter $storage */
$storage = Storage::disk(config('gallery-json-media.disk'));

/**@todo : for non local file Soon */
// Create the image file
$croppa = (new Croppa(filesystem: $storage, filePath: $url['path'], width: $url['width'], height: $url['height']));
$croppa->render();
if ($storage->getAdapter() instanceof LocalFilesystemAdapter) {
return redirect($requestPath, 301);
}

$absolutePath = $storage->path($requestPath);

return new BinaryFileResponse($absolutePath, 200, [
'Content-Type' => $storage->mimeType($requestPath),
]);

}
}
107 changes: 107 additions & 0 deletions src/JsonMedia/ImageManipulation/Croppa.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

declare(strict_types=1);

namespace GalleryJsonMedia\JsonMedia\ImageManipulation;

use GalleryJsonMedia\JsonMedia\UrlParser;
use Illuminate\Contracts\Filesystem\Filesystem;
use Spatie\Image\Exceptions\InvalidImageDriver;
use Spatie\Image\Exceptions\InvalidManipulation;
use Spatie\Image\Image;
use Spatie\Image\Manipulations;

final class Croppa
{
public function __construct(protected Filesystem $filesystem, private string $filePath, private ?int $width = null, private ?int $height = null)
{
}

public function url(): string
{
/*if (! $this->filesystem->exists($this->getPathNameForThumbs())) {
$this->save();
}*/
$url = $this->filesystem->url($this->getPathNameForThumbs());
$url .= '?_token=' . UrlParser::make()->signingToken($url);

return $url;
}

/**
* @throws InvalidManipulation
* @throws InvalidImageDriver
*/
public function render(): void
{
$image = Image::load($this->filesystem->path($this->filePath))
->useImageDriver(config('gallery-json-media.images.driver'));

$manipulations = new Manipulations();
$manipulations->quality(config('gallery-json-media.images.quality'));

if ($this->width and $this->height) {
$manipulations->crop(
cropMethod: config('gallery-json-media.images.thumbnails-crop-method'),
width: $this->width,
height: $this->height
);
} else {
if ($this->width) {
$manipulations->width($this->width);
}
if ($this->height) {
$manipulations->height($this->height);
}
}
$image->manipulate($manipulations)
->save($this->filesystem->path($this->getPathNameForThumbs()));
}

protected function getPathNameForThumbs(): string
{
return $this->getBaseNameForTumbs() . $this->getSuffix() . '.' . $this->getFileInfo()['extension'];
}

protected function getBaseNameForTumbs()
{
$basePath = str($this->filePath)->beforeLast('/');

return $basePath . '/' . $this->getFileInfo()['filename'];
}

protected function getSuffix(): string
{
$suffix = '-';
if ($this->width === null && $this->height === null) {
return '';
}
$width = $this->width ?? '_';
$height = $this->height ?? '_';
$suffix .= $width . 'x' . $height;

return $suffix;
}

/**
* @return array{dirname : string,basename:string,extension : string,filename : string}
*/
protected function getFileInfo(): array
{
return pathinfo($this->filesystem->path($this->filePath));
}

public function reset(): void
{
$search = $this->filesystem->path($this->getBaseNameForTumbs() . '-*.*');
foreach (glob($search) as $file) {
unlink($file);
}
}

public function delete(): void
{
$this->reset();
$this->filesystem->delete($this->filePath);
}
}
32 changes: 26 additions & 6 deletions src/JsonMedia/Media.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@

namespace GalleryJsonMedia\JsonMedia;

use Bkwld\Croppa\Facades\Croppa;
use Exception;
use GalleryJsonMedia\JsonMedia\Concerns\HasFile;
use GalleryJsonMedia\JsonMedia\Contracts\CanDeleteMedia;
use GalleryJsonMedia\JsonMedia\ImageManipulation\Croppa;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\View\View;
use Stringable;
Expand Down Expand Up @@ -37,14 +36,25 @@ public static function isImage(string $mimeType): bool
return str($mimeType)->startsWith('image');
}

protected function getPath(): ?string
{
if ($fileName = $this->getContentKeyValue('file')) {
$storage = $this->getDisk();
if ($storage->exists($fileName)) {
return $storage->path($fileName);
}
}

return null;
}

public function getUrl(): ?string
{
if ($fileName = $this->getContentKeyValue('file')) {
$storage = $this->getDisk();
if ($storage->exists($fileName)) {
return $storage->url($fileName);
}
//throw new Exception("File not Found [\$imagesDirectory] {$fileName}");
}

return null;
Expand All @@ -55,8 +65,18 @@ public function getCropUrl(?int $width = null, ?int $height = null, ?array $opti
if ($this->isSvgFile()) {
return $this->getUrl();
}
if ($path = $this->getPath()) {
$croppa = new Croppa(
$this->getDisk(),
$this->getContentKeyValue('file'),
$width,
$height
);

return $croppa->url();
}

return url(Croppa::url($this->getUrl(), $width, $height, $options));
return '';
}

public function isSvgFile(): bool
Expand All @@ -79,8 +99,8 @@ public function withImageProperties(int $width, int $height): Media

public function delete(): void
{
if ($this->getUrl()) {
Croppa::delete($this->getUrl());
if ($this->getFileName()) {
(new Croppa($this->getDisk(), $this->getFileName()))->delete();
}
}

Expand Down
Loading

0 comments on commit 9667987

Please sign in to comment.