Search code examples
phpsymfonyservicesonatasonata-media-bundle

Symfony2 Overriding Sonata media Image provider.(Passing interface to constructor)


I want to override the image provider of SonataMediaBundle, however, when I override it, I get the error, when the constructor is called:

Catchable Fatal Error: Argument 8 passed to Application\Sonata\MediaBundle\Provider\NewImageProvider::__construct() must be an instance of Imagine\Image\ImagineInterface, none given

This is the constructor:

/**
 * @param string                                                $name
 * @param \Gaufrette\Filesystem                                 $filesystem
 * @param \Sonata\MediaBundle\CDN\CDNInterface                  $cdn
 * @param \Sonata\MediaBundle\Generator\GeneratorInterface      $pathGenerator
 * @param \Sonata\MediaBundle\Thumbnail\ThumbnailInterface      $thumbnail
 * @param array                                                 $allowedExtensions
 * @param array                                                 $allowedMimeTypes
 * @param \Imagine\Image\ImagineInterface                       $adapter
 * @param \Sonata\MediaBundle\Metadata\MetadataBuilderInterface $metadata
 */
public function __construct($name, Filesystem $filesystem, CDNInterface $cdn, GeneratorInterface $pathGenerator, ThumbnailInterface $thumbnail, array $allowedExtensions = array(), array $allowedMimeTypes = array(), ImagineInterface $adapter, MetadataBuilderInterface $metadata = null)
{
    parent::__construct($name, $filesystem, $cdn, $pathGenerator, $thumbnail, $allowedExtensions, $allowedMimeTypes, $metadata);

    $this->imagineAdapter = $adapter;
}

As you can see argument 8 requires an Interface. Right now in my service I am not passing an 8th argument:

sonata.media.provider.image:
         class: %application_sonata_media.image_class%
         arguments:
            - [sonata.media.provider.image]
            - [@sonata.media.filesystem.local]
            - [@sonata.media.cdn.server]
            - [@sonata.media.generator.default]
            - [@sonata.media.thumbnail.format]
            - [@sonata.media.buzz.browser]
            - [@sonata.media.metadata.proxy]
         tags:
            - { name: sonata.media.provider }
         calls:
                       - [ setTemplates, [ { helper_thumbnail: SonataMediaBundle:Provider:thumbnail.html.twig, helper_view: SonataMediaBundle:Provider:view_youtube.html.twig } ] ]

I tried to pass it in different ways, for example( = array given ):

     arguments:
        - [sonata.media.provider.image]
        - [@sonata.media.filesystem.local]
        - [@sonata.media.cdn.server]
        - [@sonata.media.generator.default]
        - [@sonata.media.thumbnail.format]
        - [@sonata.media.buzz.browser]
        - [@sonata.media.metadata.proxy]
        - [imagine_interface]

I even tried to create a new service that loads the interfase:

test.imagine:
   class: Imagine\Image\ImagineInterface

sonata.media.provider.image:
     class: %application_sonata_media.image_class%
     arguments:
        - [sonata.media.provider.image]
        - [@sonata.media.filesystem.local]
        - [@sonata.media.cdn.server]
        - [@sonata.media.generator.default]
        - [@sonata.media.thumbnail.format]
        - [@sonata.media.buzz.browser]
        - [@sonata.media.metadata.proxy]
        - [@test.imagine]
     tags:
        - { name: sonata.media.provider }
     calls:
                   - [ setTemplates, [ { helper_thumbnail: SonataMediaBundle:Provider:thumbnail.html.twig, helper_view: SonataMediaBundle:Provider:view_youtube.html.twig } ] ]

Then I got the error:

Cannot instantiate interface Imagine\Image\ImagineInterface

Now Im out of ideas. What else can I try?


Solution

  • Sonata base provider has 2 optional parameters inside its constructor - $allowedExtensions and $allowedMimeTypes.

    Because you are passing arrays to a class there is a hidden error, that you fill only the first 7 arguments (where 8th is required).

    You went to the right direction adding additional arguments, but their types was wrong. Your last modification is not working, because you cannot make service from the interface - provided error tells the same)

    Try this (with appropriate image adapter):

     sonata.media.provider.image:
             class: Server\BaseBundle\Provider\ImageProvider
             arguments:
                - sonata.media.provider.image
                - @sonata.media.filesystem.local
                - @sonata.media.cdn.server
                - @sonata.media.generator.default
                - @sonata.media.thumbnail.format
                - []
                - []
                - @sonata.media.adapter.image.gd
                - @sonata.media.metadata.proxy
             tags:
                - { name: sonata.media.provider }
             calls:
                - [ setTemplates, [ { helper_thumbnail: SonataMediaBundle:Provider:thumbnail.html.twig, helper_view: SonataMediaBundle:Provider:view_youtube.html.twig } ] ]
    

    There are some already implemented adapters in sonata:

    • sonata.media.adapter.image.gd
    • sonata.media.adapter.image.imagick
    • sonata.media.adapter.image.gmagick

    Also you can take a look on this. It describes the way you can override services. I think it's more clear approach. For example, to override generator class I use it like this:

    myown.media.provider.file:
            class: Application\MediaBundle\Provider\DemoProvider
            parent: sonata.media.provider.file
            tags:
                - { name: sonata.media.provider }
            calls:
                - [setGenerator, ["@my_own_generator"]]