Extract thumbnail manager classes from appbox

This commit is contained in:
Thibaud Fabre
2015-07-08 13:43:18 +02:00
parent c65fc6abec
commit e28b080c5a
8 changed files with 348 additions and 146 deletions

View File

@@ -0,0 +1,126 @@
<?php
namespace Alchemy\Phrasea\Core\Thumbnail;
use Alchemy\Phrasea\Application;
use MediaAlchemyst\Alchemyst;
use MediaAlchemyst\Specification\Image as ImageSpecification;
use MediaVorus\Media\Image;
use MediaVorus\Media\MediaInterface;
use MediaVorus\Media\Video;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\File;
abstract class AbstractThumbnailManager
{
/**
* @var string[]
*/
protected static $allowedMimeTypes = [
'image/gif',
'image/png',
'image/jpeg',
'image/jpg',
'image/pjpeg'
];
/**
* @var Alchemyst
*/
protected $alchemyst;
/**
* @var Application
*/
protected $application;
/**
* @var Filesystem
*/
protected $filesystem;
/**
* @var string
*/
protected $rootPath;
/**
* @param Application $application
* @param Alchemyst $alchemyst
* @param Filesystem $filesystem
* @param $rootPath
*/
public function __construct(Application $application, Alchemyst $alchemyst, Filesystem $filesystem, $rootPath)
{
$this->alchemyst = $alchemyst;
$this->application = $application;
$this->filesystem = $filesystem;
$this->rootPath = $rootPath;
}
protected function validateFileMimeType(File $file)
{
if (!in_array(mb_strtolower($file->getMimeType()), self::$allowedMimeTypes)) {
throw new \InvalidArgumentException('Invalid file format');
}
}
/**
* @param MediaInterface $media
* @param int $maxWidth
* @param int $maxHeight
* @return bool
*/
protected function shouldResize($media, $maxWidth, $maxHeight)
{
if (! $media instanceof Image && ! $media instanceof Video) {
return false;
}
return $media->getWidth() > $maxWidth || $media->getHeight() > $maxHeight;
}
/**
* @param ImageSpecification $imageSpec
* @param int $width
* @param int $height
*/
protected function setSpecificationSize(ImageSpecification $imageSpec, $width, $height)
{
$imageSpec->setResizeMode(ImageSpecification::RESIZE_MODE_INBOUND_FIXEDRATIO);
$imageSpec->setDimensions($width, $height);
}
/**
* @param File $file
* @param $imageSpec
* @return string
* @throws \MediaAlchemyst\Exception\FileNotFoundException
*/
protected function resizeMediaFile(File $file, $imageSpec)
{
$tmp = tempnam(sys_get_temp_dir(), 'tmpdatabox') . '.jpg';
$this->alchemyst->turninto($file->getPathname(), $tmp, $imageSpec);
return $tmp;
}
/**
* @param string $target
* @param string $filename
*/
protected function copyFile($target, $filename)
{
if (is_file($target)) {
$this->filesystem->remove($target);
}
if (null === $target || null === $filename) {
return;
}
$this->filesystem->mkdir(dirname($target), 0750);
$this->filesystem->copy($filename, $target, true);
$this->filesystem->chmod($target, 0760);
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace Alchemy\Phrasea\Core\Thumbnail;
use Alchemy\Phrasea\Application;
use MediaAlchemyst\Specification\Image as ImageSpecification;
use Symfony\Component\HttpFoundation\File\File;
class CollectionThumbnailManager extends AbstractThumbnailManager implements ThumbnailManager
{
/**
* @param ThumbnailedElement $element
* @param $thumbnailType
* @param File $file
*/
public function setThumbnail(ThumbnailedElement $element, $thumbnailType, File $file = null)
{
$filename = null;
if (!is_null($file)) {
$this->validateFileMimeType($file);
$filename = $this->generateThumbnail($thumbnailType, $file);
}
$logoFile = $this->rootPath . '/config/' . $thumbnailType . '/' . $element->getRootIdentifier();
$custom_path = $this->rootPath . '/www/custom/' . $thumbnailType . '/' . $element->getRootIdentifier();
foreach ([$logoFile, $custom_path] as $target) {
$this->copyFile($target, $filename);
}
$element->updateThumbnail($thumbnailType, $file);
}
/**
* @param $thumbnailType
* @param File $file
* @return string
*/
protected function generateThumbnail($thumbnailType, File $file)
{
$filename = $file->getPathname();
$imageSpec = new ImageSpecification();
if ($thumbnailType === ThumbnailManager::TYPE_LOGO) {
//resize collection logo
$media = $this->application->getMediaFromUri($filename);
if ($this->shouldResize($media, 120, 24)) {
$this->setSpecificationSize($imageSpec, 120, 24);
}
$filename = $this->resizeMediaFile($file, $imageSpec);
return $filename;
} elseif ($thumbnailType === ThumbnailManager::TYPE_PRESENTATION) {
//resize collection logo
$this->setSpecificationSize($imageSpec, 650, 200);
$filename = $this->resizeMediaFile($file, $imageSpec);
return $filename;
}
return $filename;
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Alchemy\Phrasea\Core\Thumbnail;
use Alchemy\Phrasea\Application;
use MediaAlchemyst\Specification\Image as ImageSpecification;
use Symfony\Component\HttpFoundation\File\File;
class DataboxThumbnailManager extends AbstractThumbnailManager implements ThumbnailManager
{
public function setThumbnail(ThumbnailedElement $element, $thumbnailType, File $file = null)
{
$filename = null;
if ($thumbnailType !== ThumbnailManager::TYPE_PDF) {
throw new \InvalidArgumentException('Unsupported thumbnail type.');
}
if (!is_null($file)) {
$this->validateFileMimeType($file);
$filename = $this->generateThumbnail($file);
}
$logoFile = $this->rootPath . '/config/minilogos/' . $thumbnailType . '_' . $element->getRootIdentifier() . '.jpg';
$custom_path = $this->rootPath . '/www/custom/minilogos/' . $thumbnailType . '_' . $element->getRootIdentifier() . '.jpg';
foreach ([$logoFile, $custom_path] as $target) {
$this->copyFile($target, $filename);
}
$element->updateThumbnail($thumbnailType, $file);
}
/**
* @param File $file
* @return string
*/
protected function generateThumbnail(File $file)
{
$imageSpec = new ImageSpecification();
$this->setSpecificationSize($imageSpec, 120, 35);
$filename = $this->resizeMediaFile($file, $imageSpec);
return $filename;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Alchemy\Phrasea\Core\Thumbnail;
use Symfony\Component\HttpFoundation\File\File;
interface ThumbnailManager
{
const TYPE_LOGO = 'minilogos';
const TYPE_PDF = 'logopdf';
const TYPE_WM = 'wm';
const TYPE_STAMP = 'stamp';
const TYPE_PRESENTATION = 'presentation';
public function setThumbnail(ThumbnailedElement $element, $thumbnailType, File $file = null);
}

View File

@@ -0,0 +1,13 @@
<?php
namespace Alchemy\Phrasea\Core\Thumbnail;
use Symfony\Component\HttpFoundation\File\File;
interface ThumbnailedElement
{
public function getRootIdentifier();
public function updateThumbnail($thumbnailType, File $file = null);
}

View File

@@ -63,145 +63,28 @@ class appbox extends base
public function write_collection_pic(Alchemyst $alchemyst, Filesystem $filesystem, collection $collection, SymfoFile $pathfile = null, $pic_type) public function write_collection_pic(Alchemyst $alchemyst, Filesystem $filesystem, collection $collection, SymfoFile $pathfile = null, $pic_type)
{ {
$filename = null; $manager = new \Alchemy\Phrasea\Core\Thumbnail\CollectionThumbnailManager(
$this->app,
$alchemyst,
$filesystem,
$this->app['root.path']
);
if (!is_null($pathfile)) { $manager->setThumbnail($collection, $pic_type, $pathfile);
if (!in_array(mb_strtolower($pathfile->getMimeType()), ['image/gif', 'image/png', 'image/jpeg', 'image/jpg', 'image/pjpeg'])) {
throw new \InvalidArgumentException('Invalid file format');
}
$filename = $pathfile->getPathname();
if ($pic_type === collection::PIC_LOGO) {
//resize collection logo
$imageSpec = new ImageSpecification();
$media = $this->app->getMediaFromUri($filename);
if ($media->getWidth() > 120 || $media->getHeight() > 24) {
$imageSpec->setResizeMode(ImageSpecification::RESIZE_MODE_INBOUND_FIXEDRATIO);
$imageSpec->setDimensions(120, 24);
}
$tmp = tempnam(sys_get_temp_dir(), 'tmpdatabox') . '.jpg';
try {
$alchemyst->turninto($pathfile->getPathname(), $tmp, $imageSpec);
$filename = $tmp;
} catch (\MediaAlchemyst\Exception $e) {
}
} elseif ($pic_type === collection::PIC_PRESENTATION) {
//resize collection logo
$imageSpec = new ImageSpecification();
$imageSpec->setResizeMode(ImageSpecification::RESIZE_MODE_INBOUND_FIXEDRATIO);
$imageSpec->setDimensions(650, 200);
$tmp = tempnam(sys_get_temp_dir(), 'tmpdatabox') . '.jpg';
try {
$alchemyst->turninto($pathfile->getPathname(), $tmp, $imageSpec);
$filename = $tmp;
} catch (\MediaAlchemyst\Exception $e) {
}
}
}
switch ($pic_type) {
case collection::PIC_WM;
$collection->reset_watermark();
break;
case collection::PIC_LOGO:
case collection::PIC_PRESENTATION:
break;
case collection::PIC_STAMP:
$collection->reset_stamp();
break;
default:
throw new \InvalidArgumentException('unknown pic_type');
break;
}
if ($pic_type == collection::PIC_LOGO) {
$collection->update_logo($pathfile);
}
$file = $this->app['root.path'] . '/config/' . $pic_type . '/' . $collection->get_base_id();
$custom_path = $this->app['root.path'] . '/www/custom/' . $pic_type . '/' . $collection->get_base_id();
foreach ([$file, $custom_path] as $target) {
if (is_file($target)) {
$filesystem->remove($target);
}
if (null === $target || null === $filename) {
continue;
}
$filesystem->mkdir(dirname($target), 0750);
$filesystem->copy($filename, $target, true);
$filesystem->chmod($target, 0760);
}
return $this; return $this;
} }
public function write_databox_pic(Alchemyst $alchemyst, Filesystem $filesystem, databox $databox, SymfoFile $pathfile = null, $pic_type) public function write_databox_pic(Alchemyst $alchemyst, Filesystem $filesystem, databox $databox, SymfoFile $pathfile = null, $pic_type)
{ {
$filename = null; $manager = new \Alchemy\Phrasea\Core\Thumbnail\DataboxThumbnailManager(
$this->app,
$alchemyst,
$filesystem,
$this->app['root.path']
);
if (!is_null($pathfile)) { $manager->setThumbnail($databox, $pic_type, $pathfile);
if (!in_array(mb_strtolower($pathfile->getMimeType()), ['image/jpeg', 'image/jpg', 'image/pjpeg', 'image/png', 'image/gif'])) {
throw new \InvalidArgumentException('Invalid file format');
}
}
if (!in_array($pic_type, [databox::PIC_PDF])) {
throw new \InvalidArgumentException('unknown pic_type');
}
if ($pathfile) {
$filename = $pathfile->getPathname();
$imageSpec = new ImageSpecification();
$imageSpec->setResizeMode(ImageSpecification::RESIZE_MODE_INBOUND_FIXEDRATIO);
$imageSpec->setDimensions(120, 35);
$tmp = tempnam(sys_get_temp_dir(), 'tmpdatabox') . '.jpg';
try {
$alchemyst->turninto($pathfile->getPathname(), $tmp, $imageSpec);
$filename = $tmp;
} catch (\MediaAlchemyst\Exception $e) {
}
}
$file = $this->app['root.path'] . '/config/minilogos/' . $pic_type . '_' . $databox->get_sbas_id() . '.jpg';
$custom_path = $this->app['root.path'] . '/www/custom/minilogos/' . $pic_type . '_' . $databox->get_sbas_id() . '.jpg';
foreach ([$file, $custom_path] as $target) {
if (is_file($target)) {
$filesystem->remove($target);
}
if (is_null($filename)) {
continue;
}
$filesystem->mkdir(dirname($target));
$filesystem->copy($filename, $target);
$filesystem->chmod($target, 0760);
}
$databox->delete_data_from_cache('printLogo');
return $this; return $this;
} }

View File

@@ -14,11 +14,14 @@ use Alchemy\Phrasea\Core\Event\Collection\CollectionEvent;
use Alchemy\Phrasea\Core\Event\Collection\CollectionEvents; use Alchemy\Phrasea\Core\Event\Collection\CollectionEvents;
use Alchemy\Phrasea\Core\Event\Collection\CreatedEvent; use Alchemy\Phrasea\Core\Event\Collection\CreatedEvent;
use Alchemy\Phrasea\Core\Event\Collection\NameChangedEvent; use Alchemy\Phrasea\Core\Event\Collection\NameChangedEvent;
use Alchemy\Phrasea\Core\Thumbnail\ThumbnailedElement;
use Alchemy\Phrasea\Core\Thumbnail\ThumbnailManager;
use Alchemy\Phrasea\Exception\InvalidArgumentException; use Alchemy\Phrasea\Exception\InvalidArgumentException;
use Alchemy\Phrasea\Model\Entities\User; use Alchemy\Phrasea\Model\Entities\User;
use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\Connection;
use Symfony\Component\HttpFoundation\File\File;
class collection implements cache_cacheableInterface class collection implements cache_cacheableInterface, ThumbnailedElement
{ {
protected $base_id; protected $base_id;
protected $sbas_id; protected $sbas_id;
@@ -227,6 +230,31 @@ class collection implements cache_cacheableInterface
return $this->databox->get_connection(); return $this->databox->get_connection();
} }
public function getRootIdentifier()
{
return $this->base_id;
}
public function updateThumbnail($thumbnailType, File $file = null)
{
switch ($thumbnailType) {
case ThumbnailManager::TYPE_WM;
$this->reset_watermark();
break;
case ThumbnailManager::TYPE_LOGO:
$this->update_logo($file);
break;
case ThumbnailManager::TYPE_PRESENTATION:
break;
case ThumbnailManager::TYPE_STAMP:
$this->reset_stamp();
break;
default:
throw new \InvalidArgumentException('Unsupported thumbnail type.');
}
}
public function set_public_presentation($publi) public function set_public_presentation($publi)
{ {
if (in_array($publi, ['none', 'wm', 'stamp'])) { if (in_array($publi, ['none', 'wm', 'stamp'])) {

View File

@@ -20,22 +20,34 @@ use Alchemy\Phrasea\Status\StatusStructureFactory;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use Alchemy\Phrasea\Core\PhraseaTokens; use Alchemy\Phrasea\Core\PhraseaTokens;
class databox extends base class databox extends base implements \Alchemy\Phrasea\Core\Thumbnail\ThumbnailedElement
{ {
/** @var int */
protected $id; const BASE_TYPE = self::DATA_BOX;
/** @var string */ const CACHE_META_STRUCT = 'meta_struct';
protected $structure; const CACHE_THESAURUS = 'thesaurus';
const CACHE_COLLECTIONS = 'collections';
const CACHE_STRUCTURE = 'structure';
const PIC_PDF = 'logopdf';
/** @var array */ /** @var array */
protected static $_xpath_thesaurus = []; protected static $_xpath_thesaurus = [];
/** @var array */ /** @var array */
protected static $_dom_thesaurus = []; protected static $_dom_thesaurus = [];
/** @var array */ /** @var array */
protected static $_thesaurus = []; protected static $_thesaurus = [];
/** @var SimpleXMLElement */
protected static $_sxml_thesaurus = [];
/** @var int */
protected $id;
/** @var string */
protected $structure;
/** @var array */ /** @var array */
protected $_xpath_structure; protected $_xpath_structure;
/** @var DOMDocument */ /** @var DOMDocument */
@@ -48,16 +60,8 @@ class databox extends base
protected $meta_struct; protected $meta_struct;
/** @var databox_subdefsStructure */ /** @var databox_subdefsStructure */
protected $subdef_struct; protected $subdef_struct;
/** @var SimpleXMLElement */
protected static $_sxml_thesaurus = [];
const BASE_TYPE = self::DATA_BOX;
const CACHE_META_STRUCT = 'meta_struct';
const CACHE_THESAURUS = 'thesaurus';
const CACHE_COLLECTIONS = 'collections';
const CACHE_STRUCTURE = 'structure';
const PIC_PDF = 'logopdf';
/** @var string[] */
private $labels = []; private $labels = [];
private $ord; private $ord;
private $viewname; private $viewname;
@@ -132,6 +136,16 @@ class databox extends base
return $this->app->getApplicationBox(); return $this->app->getApplicationBox();
} }
public function getRootIdentifier()
{
return $this->get_sbas_id();
}
public function updateThumbnail($thumbnailType, File $file = null)
{
$this->delete_data_from_cache('printLogo');
}
/** /**
* @return collection[] * @return collection[]
*/ */