207 lines
5.8 KiB
PHP
207 lines
5.8 KiB
PHP
<?php
|
|
|
|
|
|
namespace App\Service;
|
|
|
|
use App\Entity\Image;
|
|
use Doctrine\ORM\EntityManager;
|
|
use Imagine\Gd\Imagine;
|
|
use Imagine\Image\Box;
|
|
use Imagine\Image\ImageInterface;
|
|
use Symfony\Component\Yaml\Parser;
|
|
use Zend\Config\Reader\Yaml;
|
|
|
|
class GalleryService
|
|
{
|
|
|
|
const CONFIG_FILE = 'data/galleries/config.yaml';
|
|
const IMAGE_BASEDIR = 'data/galleries/%s/';
|
|
const EXPORT_DIR = 'data/export/';
|
|
const THUMBNAIL_SIZE = 500;
|
|
|
|
protected $contentTypeMap = [
|
|
'jpg' => 'image/jpeg',
|
|
'jpeg' => 'image/jpeg',
|
|
'png' => 'image/png',
|
|
];
|
|
protected $config;
|
|
|
|
/**
|
|
* @var EntityManager
|
|
*/
|
|
protected $em;
|
|
|
|
public function __construct(EntityManager $entityManager)
|
|
{
|
|
$this->em = $entityManager;
|
|
}
|
|
|
|
public function getExportFileName(string $slug)
|
|
{
|
|
$config = $this->getConfig();
|
|
if (!isset($config['galleries'][$slug])) {
|
|
return false;
|
|
}
|
|
$dir = $config['galleries'][$slug]['dir'];
|
|
return $this->ensureExportFileExists($dir, "{$slug}.zip");
|
|
}
|
|
|
|
private function ensureExportFileExists(string $dir, string $filename)
|
|
{
|
|
$exportName = self::EXPORT_DIR . $filename;
|
|
if(file_exists($exportName)) {
|
|
return $exportName;
|
|
}
|
|
$exportLock = sprintf("data/tmp/%s.lock", $dir);
|
|
|
|
if(file_exists($exportLock)) {
|
|
return false;
|
|
}
|
|
|
|
$images = array_map('basename', glob($this->getImageDir($dir) . "*.{jpg,jpeg,png}", GLOB_BRACE));
|
|
|
|
$zipName = tempnam("data/tmp", "export");
|
|
touch($exportLock);
|
|
$zipArchive = new \ZipArchive();
|
|
$zipArchive->open($zipName, \ZipArchive::CREATE);
|
|
foreach ($images as $image) {
|
|
ini_set("max_execution_time", 60);
|
|
$zipArchive->addFile(
|
|
sprintf(self::IMAGE_BASEDIR,$dir) . $image,
|
|
"{$dir}/{$image}"
|
|
);
|
|
}
|
|
$zipArchive->close();
|
|
rename($zipName, $exportName);
|
|
unlink($exportLock);
|
|
return $exportName;
|
|
}
|
|
|
|
public function loadGalleryData($includeHidden = false)
|
|
{
|
|
$config = $this->getConfig();
|
|
$albums = [];
|
|
foreach ($config['galleries'] as $id => $data) {
|
|
if ($includeHidden || $data['public']) {
|
|
$galleryImages = $this->loadGalleryImages($data['dir']);
|
|
$albums[] = [
|
|
'slug' => $id,
|
|
'name' => $data['name'],
|
|
'coverImage' => isset($data['cover'])
|
|
? $this->getCoverImage($galleryImages, $data['cover'])
|
|
: null,
|
|
'date' => $this->getGalleryDate($data['dir']),
|
|
'type' => $data['type'],
|
|
'isNew' => $data['new'],
|
|
'isPublic' => $data['public'],
|
|
'images' => $galleryImages,
|
|
];
|
|
}
|
|
}
|
|
return $albums;
|
|
}
|
|
|
|
private function getCoverImage(array &$images, string $coverFileName): Image
|
|
{
|
|
$filtered = array_values(array_filter($images, function(Image $image) use ($coverFileName) {
|
|
return $image->getPath() == $coverFileName;
|
|
}));
|
|
return array_pop($filtered);
|
|
}
|
|
|
|
private function getGalleryDate(string $dir): string
|
|
{
|
|
$timestamp = sprintf("@%s", filemtime($this->getImageDir($dir)));
|
|
$date = new \DateTime($timestamp);
|
|
return $date->format("Y-m-d");
|
|
}
|
|
|
|
/**
|
|
* @param string $dir
|
|
* @return Image[]
|
|
* @todo implement label for image in some way
|
|
*/
|
|
private function loadGalleryImages(string $dir): array
|
|
{
|
|
$images = array_map('basename', glob(
|
|
sprintf(self::IMAGE_BASEDIR . "*.{jpg,jpeg,png}", $dir),
|
|
GLOB_BRACE
|
|
));
|
|
$imagine = new Imagine();
|
|
return array_map(function ($imagePath) use ($dir, $imagine) {
|
|
$imageEntity = $this->em->getRepository(Image::class)->findOneBy([
|
|
'dir' => $dir,
|
|
'path' => $imagePath,
|
|
]);
|
|
$this->ensureThumbnailExists($dir, $imagePath);
|
|
if (null === $imageEntity) {
|
|
$image = $imagine->open($this->getImageDir($dir) . $imagePath);
|
|
$imageSize = $image->getSize();
|
|
unset($image);
|
|
|
|
$thumb = $imagine->open($this->getThumbDir($dir) . $imagePath);
|
|
$thumbSize = $thumb->getSize();
|
|
unset($thumb);
|
|
|
|
$imageEntity = new Image();
|
|
$imageEntity->setLabel("")
|
|
->setDir($dir)
|
|
->setPath($imagePath)
|
|
->setWidth($imageSize->getWidth())
|
|
->setHeight($imageSize->getHeight())
|
|
->setThumbWidth($thumbSize->getWidth())
|
|
->setThumbHeight($thumbSize->getHeight())
|
|
;
|
|
$this->em->persist($imageEntity);
|
|
$this->em->flush();
|
|
}
|
|
return $imageEntity;
|
|
}, $images);
|
|
}
|
|
|
|
private function ensureThumbnailExists(string $dir, string $imageName) {
|
|
$imageDir = $this->getImageDir($dir);
|
|
$thumbPath = $imageDir . "thumb_" . self::THUMBNAIL_SIZE;
|
|
@mkdir($thumbPath);
|
|
$thumbImageName = $thumbPath . "/" . $imageName;
|
|
|
|
if (!file_exists($thumbImageName)) {
|
|
$thumbSize = new Box(self::THUMBNAIL_SIZE, self::THUMBNAIL_SIZE * 10);
|
|
$imagine = new Imagine();
|
|
$image = $imagine->open($imageDir . $imageName)
|
|
->thumbnail($thumbSize, ImageInterface::THUMBNAIL_INSET);
|
|
$image->effects()->sharpen();
|
|
$image->save($thumbImageName);
|
|
}
|
|
|
|
return $thumbImageName;
|
|
}
|
|
|
|
public function getImageFileName(string $slug, string $image, $isThumbnail = false): string
|
|
{
|
|
$config = $this->getConfig();
|
|
$dir = $config['galleries'][$slug]['dir'];
|
|
$this->ensureThumbnailExists($config['galleries'][$slug]['dir'], $image);
|
|
return $isThumbnail
|
|
? ($this->getThumbDir($dir) . $image)
|
|
: ($this->getImageDir($dir) . $image);
|
|
}
|
|
|
|
private function getImageDir($dir): string {
|
|
return sprintf(self::IMAGE_BASEDIR, $dir);
|
|
}
|
|
|
|
private function getThumbDir($dir): string {
|
|
return sprintf(self::IMAGE_BASEDIR, "{$dir}/thumb_" . self::THUMBNAIL_SIZE);
|
|
}
|
|
|
|
private function getConfig()
|
|
{
|
|
if (null === $this->config) {
|
|
$parser = new Parser();
|
|
$configReader = new Yaml([$parser, 'parse']);
|
|
$this->config = $configReader->fromFile(self::CONFIG_FILE);
|
|
}
|
|
return $this->config;
|
|
}
|
|
} |