1
0
cms11/app/Classes/Traits/Repairs/RepairsImages.php

161 lines
4.8 KiB
PHP
Raw Normal View History

<?php
namespace App\Classes\Traits\Repairs;
use Carbon\Carbon;
use Intervention\Image\Laravel\Facades\Image;
/**
* Trait for AttachmentsManager
*/
trait RepairsImages
{
/**
* Repair all attached images
*/
private function repairImages()
{
$this->load();
foreach ($this->manager->get('files', []) as $ref => $data) {
$this->repairKnownImage($ref, $data);
}
$this->save();
}
/**
* Repair a single image. Move it to appropriate directory and create or
* update variations.
*/
private function repairKnownImage(string $ref, array $data)
{
if (!empty($data['url'])) {
$data['filename'] = $data['url'];
unset($data['url']);
$this->manager->set(sprintf('files.%s', $ref), $data);
}
$extension = pathinfo($data['filename'], PATHINFO_EXTENSION);
$currentFullPath = sprintf('%s%s', $this->bundle->getDataDir(), $data['filename']);
$expectedFullPath = sprintf(
'%s%s/%s/%s/original.%s',
$this->bundle->getDataDir(),
$this->attachmentsDir,
$this->kind,
$ref,
$extension
);
if (!$this->disk->exists($currentFullPath)) {
$this->deleteAttachment($ref);
return;
}
if (empty($data['last_modified'])) {
$data['last_modified'] = Carbon::parse($this->disk->lastModified($currentFullPath))->toIso8601String();
}
if ($currentFullPath !== $expectedFullPath) {
$this->disk->move($currentFullPath, $expectedFullPath);
$data['last_modified'] = Carbon::parse($this->disk->lastModified($expectedFullPath))->toIso8601String();
$data['filename'] = sprintf(
'%s/%s/%s/original.%s',
$this->attachmentsDir,
$this->kind,
$ref,
$extension
);
$parentDir = dirname($currentFullPath);
if (empty($this->disk->listContents($parentDir, true))) {
$this->disk->delete($parentDir);
}
}
$this->manager->set(sprintf('files.%s', $ref), $data);
$this->syncImageVariants($ref);
}
/**
* Synchronize image variants (apply pre-defined filters)
*/
private function syncImageVariants(string $ref)
{
$currentVariants = $this->manager->get(sprintf('variants.%s', $ref), []);
$configVariants = array_keys(config('imagefilters'));
// Synchronize or delete currently declared variants
foreach ($currentVariants as $filter => $variantData) {
if (!in_array($filter, $configVariants)) {
$this->deleteVariant($ref, $filter);
continue;
}
$this->syncImageVariant($ref, $filter);
}
// Synchronize variants with the ones expected by configuration
foreach ($configVariants as $filter) {
$this->syncImageVariant($ref, $filter);
}
}
/**
* Synchronize specific image variant
*/
private function syncImageVariant(string $ref, string $filter)
{
$originalData = $this->getAttachmentData($ref);
$variantData = $this->getVariantData($ref, $filter);
$variantFilepath = $this->getVariantFullPath($ref, $filter);
if (!$this->disk->exists($variantFilepath)) {
$this->createImageVariant($ref, $filter);
} else {
$originalLastModified = Carbon::parse($originalData['last_modified']);
$variantLastModified = Carbon::parse($variantData['last_modified'] ?? $this->disk->lastModified($variantFilepath));
if ($originalLastModified->gt($variantLastModified)) {
$this->createImageVariant($ref, $filter);
}
}
}
/**
* Create the variant for specified image and filter
*/
private function createImageVariant(string $ref, string $filter)
{
$filterClass = config(sprintf('imagefilters.%s', $filter));
$original = $this->getAttachmentFullPath($ref);
$target = $this->getVariantFullPath($ref, $filter);
$contents = $this->disk->get($original);
$image = Image::read($contents);
$variantData = $this->getVariantData($ref, $filter);
$image->modify(new $filterClass());
if ($image->isAnimated()) {
$contents = (string) $image->toGif();
} else {
$contents = (string) $image->toWebp();
}
$this->disk->put($target, $contents);
$variantData['filename'] = $this->getVariantRelativePath($ref, $filter);
$variantData['last_modified'] = now();
$this->manager->set(sprintf('variants.%s.%s', $ref, $filter), $variantData);
}
}