Quantcast
NRSoft

Sonata Media fixed dimensions resizer

We assume that you have SonataMediaBundle up and running in your project and have extended the bundle with SonataEasyExtendsBundle in your Application folder.

Next, add the following class in your extended bundle in a Resizer folder

<!--?php 

namespace ApplicationSonataMediaBundleResizer;

use ImagineImageImagineInterface;
use ImagineImageBox;
use GaufretteFile;
use SonataMediaBundleModelMediaInterface;
use ImagineImageImageInterface;
use ImagineExceptionInvalidArgumentException;
use SonataMediaBundleMetadataMetadataBuilderInterface;
use SonataMediaBundleResizerResizerInterface;

class FixedDimensionsResizer implements ResizerInterface
{
    protected $adapter;

    protected $mode;

    protected $metadata;

    /**
     * @param ImagineInterface $adapter
     * @param string           $mode
     */
    public function __construct(ImagineInterface $adapter, $mode, MetadataBuilderInterface $metadata)
    {
        $this->adapter  = $adapter;
        $this->mode     = $mode;
        $this->metadata = $metadata;
    }

    /**
     * {@inheritdoc}
     */
    public function resize(MediaInterface $media, File $in, File $out, $format, array $settings)
    {
        if (!isset($settings['width'])) {
            throw new RuntimeException(sprintf('Width parameter is missing in context "%s" for provider "%s"', $media->getContext(), $media->getProviderName()));
        }

        $image = $this->adapter->load($in->getContent());

        $content = $image
            ->thumbnail($this->getBox($media, $settings), $this->mode)
            ->get($format, array('quality' => $settings['quality']));

        $out->setContent($content, $this->metadata->get($media, $out->getName()));
    }

    /**
     * {@inheritdoc}
     */
    public function getBox(MediaInterface $media, array $settings)
    {
        $size = $media->getBox();

        if ($settings['width'] == null && $settings['height'] == null) {
            throw new RuntimeException(sprintf('Width/Height parameter is missing in context "%s" for provider "%s". Please add at least one parameter.', $media->getContext(), $media->getProviderName()));
        }

        if($settings['constraint'] === false){
            return new Box($settings['width'], $settings['height']);
        }

        if ($settings['height'] == null) {
            $settings['height'] = (int) ($settings['width'] * $size->getHeight() / $size->getWidth());
        }

        if ($settings['width'] == null) {
            $settings['width'] = (int) ($settings['height'] * $size->getWidth() / $size->getHeight());
        }

        return $this->computeBox($media, $settings);
    }

    /**
     * @throws InvalidArgumentException
     *
     * @param MediaInterface $media
     * @param array          $settings
     *
     * @return Box
     */
    private function computeBox(MediaInterface $media, array $settings)
    {
        if ($this->mode !== ImageInterface::THUMBNAIL_INSET && $this->mode !== ImageInterface::THUMBNAIL_OUTBOUND) {
            throw new InvalidArgumentException('Invalid mode specified');
        }

        $size = $media->getBox();

        $ratios = array(
            $settings['width'] / $size->getWidth(),
            $settings['height'] / $size->getHeight()
        );

        if ($this->mode === ImageInterface::THUMBNAIL_INSET) {
            $ratio = min($ratios);
        } else {
            $ratio = max($ratios);
        }

        return $size->scale($ratio);
    }
}

 

Then, add the following service in your config.yml

 

services:
    sonata.media.resizer.fixedDimensions:
        class: ApplicationSonataMediaBundleResizerFixedDimensionsResizer
        arguments: [@sonata.media.adapter.image.gd, 'outbound', @sonata.media.metadata.proxy]

Finally enabled the provider in the sonata_media config

sonata_media:
[...]
providers:
image:
resizer: sonata.media.resizer.fixedDimensions

When you add a new context for your image you can now add the following parameter ton constraint your image dimensions to the width and height specified.

sonata_media:
[...]
contexts:
my_context:
providers:
- sonata.media.provider.image
formats:
small:   { width: 400, height: 300, constraint: false}