Skip to content

Commit

Permalink
Create multiple previews for image files if configured
Browse files Browse the repository at this point in the history
  • Loading branch information
aimeos committed Jun 4, 2019
1 parent 658ed19 commit dfdd7b3
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 25 deletions.
127 changes: 105 additions & 22 deletions controller/common/src/Controller/Common/Media/Standard.php
Expand Up @@ -21,6 +21,7 @@ class Standard
implements \Aimeos\Controller\Common\Media\Iface
{
private $context;
private $types = [];


/**
Expand Down Expand Up @@ -85,7 +86,6 @@ public function copy( \Aimeos\MShop\Media\Item\Iface $item, $fsname = 'fs-media'
}

$fs = $this->context->getFilesystemManager()->get( $fsname );
$preview = $item->getPreview();
$path = $item->getUrl();

if( $fs->has( $path ) )
Expand All @@ -95,15 +95,18 @@ public function copy( \Aimeos\MShop\Media\Item\Iface $item, $fsname = 'fs-media'
$item->setUrl( $newPath );
}

if( $fs->has( $preview ) )
foreach( $item->getPreviews() as $preview )
{
try
if( $fs->has( $preview ) )
{
$newPath = $this->getFilePath( $preview, 'preview', pathinfo( $preview, PATHINFO_EXTENSION ) );
$fs->copy( $preview, $newPath );
$item->setPreview( $newPath );
try
{
$newPath = $this->getFilePath( $preview, 'preview', pathinfo( $preview, PATHINFO_EXTENSION ) );
$fs->copy( $preview, $newPath );
$item->setPreview( $newPath );
}
catch( \Aimeos\MW\Filesystem\Exception $e ) {} // mime icons can't be copied
}
catch( \Aimeos\MW\Filesystem\Exception $e ) {} // mime icons can't be copied
}

return $item;
Expand All @@ -129,22 +132,24 @@ public function delete( \Aimeos\MShop\Media\Item\Iface $item, $fsname = 'fs-medi
}

$fs = $this->context->getFilesystemManager()->get( $fsname );
$preview = $item->getPreview();
$path = $item->getUrl();

if( $path !== '' && $fs->has( $path ) ) {
$fs->rm( $path );
}

try
foreach( $item->getPreviews() as $preview )
{
if( $preview !== '' && $fs->has( $preview ) ) {
$fs->rm( $preview );
try
{
if( $preview !== '' && $fs->has( $preview ) ) {
$fs->rm( $preview );
}
}
catch( \Exception $e ) { ; } // Can be a mime icon with relative path
}
catch( \Exception $e ) { ; } // Can be a mime icon with relative path

return $item->setUrl( '' )->setPreview( '' );
return $item->setUrl( '' )->setPreview( '' )->deletePropertyItems( $item->getPropertyItems() );
}


Expand Down Expand Up @@ -188,25 +193,58 @@ protected function addImages( \Aimeos\MShop\Media\Item\Iface $item, \Aimeos\MW\M
$mediaFile = $this->scaleImage( $media, 'files' );

// Don't overwrite original files that are stored in linked directories
$filepath = ( strncmp( $path, 'files/', 6 ) !== 0 ? $this->getFilePath( $path, 'files', $mime ) : $path );
$filepath = ( strncmp( $path, 'files/', 6 ) ? $this->getFilePath( $path, 'files', $mime ) : $path );

$this->store( $filepath, $mediaFile->save( null, $mime ), $fsname );
$item = $item->setUrl( $filepath )->setMimeType( $mime );
unset( $mediaFile );


$path = $item->getPreview();
$mediaFiles = $this->createPreviews( $media );
$mime = $this->getMimeType( $media, 'preview' );
$mediaFile = $this->scaleImage( $media, 'preview' );
$manager = \Aimeos\MShop::create( $this->context, 'media' );

// Don't try to overwrite mime icons that are stored in another directory
$filepath = ( strncmp( $path, 'preview/', 8 ) !== 0 ? $this->getFilePath( $path, 'preview', $mime ) : $path );
foreach( $mediaFiles as $type => $mediaFile )
{
if( ( $propItem = current( $item->getPropertyItems( $type ) ) ) === false ) {
$propItem = $manager->createPropertyItem()->setType( $type );
}

$this->store( $filepath, $mediaFile->save( null, $mime ), $fsname );
$item = $item->setPreview( $filepath );
unset( $mediaFile );
$path = (string) $propItem->getValue();
// Don't try to overwrite mime icons that are stored in another directory
$filepath = ( strncmp( $path, 'preview/', 8 ) ? $this->getFilePath( $path, '', $mime ) : $path );

return $item;
$this->store( $filepath, $mediaFile->save( null, $mime ), $fsname );
$item->addPropertyItem( $propItem->setValue( $filepath ) );
unset( $mediaFile );
}

return $item->setPreview( current( $item->getPreviews() ) ?: '' );
}


/**
* Adds the used property types if necessary
*
* @param integer[] List of image widths
*/
protected function addPropertyTypes( $types )
{
foreach( $types as $type )
{
if( !isset( $this->types[$type] ) )
{
$manager = \Aimeos\MShop::create( $this->context, 'media/property/type' );

try {
$item = $manager->findItem( $type, [], 'media' );
} catch( \Aimeos\MShop\Exception $e ) {
$item = $manager->createItem()->setDomain( 'media' )->setCode( $type )->setLabel( $type . 'px width' );
}

$this->types[$type] = $manager->saveItem( $item )->getCode();
}
}
}


Expand Down Expand Up @@ -242,6 +280,49 @@ protected function checkFileUpload( \Psr\Http\Message\UploadedFileInterface $fil
}


/**
* Creates scaled images according to the configuration settings
*
* @param \Aimeos\MW\Media\Image\Iface $media Media object
* @return \Aimeos\MW\Media\Image\Iface[] Associative list of image width as keys and scaled media object as values
*/
protected function createPreviews( \Aimeos\MW\Media\Image\Iface $media )
{
$list = [];
$config = $this->context->getConfig();

foreach( $config->get( 'controller/common/media/standard/previews', [] ) as $entry )
{
$maxwidth = ( isset( $entry['maxwidth'] ) ? (int) $entry['maxwidth'] : null );
$maxheight = ( isset( $entry['maxheight'] ) ? (int) $entry['maxheight'] : null );
$fit = ( isset( $entry['force-size'] ) ? (bool) $entry['force-size'] : false );

if( $maxheight || $maxwidth )
{
$image = $media->scale( $maxwidth, $maxheight, !$fit );
$list[$image->getWidth()] = $image;
}
}

if( empty( $list ) )
{
$maxwidth = $config->get( 'controller/common/media/standard/preview/maxwidth', null );
$maxheight = $config->get( 'controller/common/media/standard/preview/maxheight', null );
$fit = (bool) $config->get( 'controller/common/media/standard/preview/force-size', false );

if( $maxheight || $maxwidth )
{
$image = $media->scale( $maxwidth, $maxheight, !$fit );
$list[$image->getWidth()] = $image;
}

}

$this->addPropertyTypes( array_keys( $list ) );
return $list;
}


/**
* Returns the context item
*
Expand Down Expand Up @@ -294,6 +375,7 @@ protected function getFileContent( $path, $fsname )
* @param string $type File type, i.e. "files" or "preview"
* @param string $mimeext Mime type or extension of the file
* @return string New file name including the file path
* @deprecated 2020.01 $type will be removed
*/
protected function getFilePath( $filename, $type, $mimeext )
{
Expand Down Expand Up @@ -463,6 +545,7 @@ protected function getMimeType( \Aimeos\MW\Media\Image\Iface $media, $type )
* @param \Aimeos\MW\Media\Image\Iface $media Media object
* @param string $type Type of the image like "preview" or "files"
* @return \Aimeos\MW\Media\Image\Iface Scaled media object
* @deprecated 2020.01 Will scale main file only
*/
protected function scaleImage( \Aimeos\MW\Media\Image\Iface $media, $type )
{
Expand Down
30 changes: 27 additions & 3 deletions controller/common/tests/Controller/Common/Media/StandardTest.php
Expand Up @@ -17,14 +17,17 @@ class StandardTest extends \PHPUnit\Framework\TestCase

protected function setUp()
{
\Aimeos\MShop::cache( true );

$this->context = \TestHelperCntl::getContext();
$this->object = new \Aimeos\Controller\Common\Media\Standard( $this->context );
}


protected function tearDown()
{
$this->object = null;
\Aimeos\MShop::cache( false );
unset( $this->object );
}


Expand All @@ -36,12 +39,23 @@ public function testAdd()
->getMock();

$object->expects( $this->once() )->method( 'checkFileUpload' );
$object->expects( $this->exactly( 2 ) )->method( 'store' );
$object->expects( $this->exactly( 3 ) )->method( 'store' );

$file = $this->getMockBuilder( \Psr\Http\Message\UploadedFileInterface::class )->getMock();
$file->expects( $this->once() )->method( 'getStream' )
->will( $this->returnValue( file_get_contents( __DIR__ . '/testfiles/test.gif' ) ) );


$propManager = $this->getMockBuilder( \Aimeos\MShop\Media\Manager\Property\Type\Standard::class )
->setConstructorArgs( array( $this->context ) )
->setMethods( array( 'saveItem' ) )
->getMock();

$propManager->expects( $this->exactly( 2 ) )->method( 'saveItem' )->will( $this->returnArgument( 0 ) );

\Aimeos\MShop::inject( 'media/property/type', $propManager );


$item = \Aimeos\MShop::create( $this->context, 'media' )->createItem();

$this->assertInstanceOf( \Aimeos\MShop\Media\Item\Iface::class, $object->add( $item, $file ) );
Expand Down Expand Up @@ -138,7 +152,17 @@ public function testScale()
$object->expects( $this->once() )->method( 'getFileContent' )
->will( $this->returnValue( file_get_contents( __DIR__ . '/testfiles/test.png' ) ) );

$object->expects( $this->exactly( 2 ) )->method( 'store' );
$object->expects( $this->exactly( 3 ) )->method( 'store' );


$propManager = $this->getMockBuilder( \Aimeos\MShop\Media\Manager\Property\Type\Standard::class )
->setConstructorArgs( array( $this->context ) )
->setMethods( array( 'saveItem' ) )
->getMock();

$propManager->expects( $this->exactly( 2 ) )->method( 'saveItem' )->will( $this->returnArgument( 0 ) );

\Aimeos\MShop::inject( 'media/property/type', $propManager );


$item = \Aimeos\MShop::create( $this->context, 'media' )->createItem();
Expand Down
8 changes: 8 additions & 0 deletions controller/common/tests/config/controller.php
Expand Up @@ -13,6 +13,14 @@
'mimeicon' => array(
'directory' => dirname( __DIR__ ) . '/tmp/media/mimeicons',
),
'previews' => array(
0 => array(
'maxwidth' => 32
),
1 => array(
'maxwidth' => 50
),
),
),
),
),
Expand Down

0 comments on commit dfdd7b3

Please sign in to comment.