Filtros por Proveedor (sonata.media.provider) de archivos Media en SonataAdmin

Crear un filtro en una Admin Class de SonataAdminBundle es una tarea bastante sencilla.

Si vamos un poco más allá, podemos necesitar configurar un filtro de una propiedad de una entidad relacionada con la que estamos administrando.

Supongamos que tenemos una entidad Prensa, con un campo relacionado con un Media de SonataMediaBundle, y queremos filtrar el listado por el tipo de proveedor del Media (sonata.media.provider.*).

Primero muestro la relación en nuestra entidad (Entity).

Prensa.php

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Prensa
 *
 * @ORM\Table()
 */
class Prensa
{
    //..
    
    /**
     * @ORM\OneToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media",cascade={"all"}, orphanRemoval=true), 
     * @ORM\JoinColumn(name="archivo_id", referencedColumnName="id")
     * 
     * @Assert\NotBlank()
     */
    private $archivo;

    //..

    /**
     * Set archivo
     *
     * @param \Application\Sonata\MediaBundle\Entity\Media $archivo
     * @return Prensa
     */
    public function setArchivo(\Application\Sonata\MediaBundle\Entity\Media $archivo= null)
    {
        $this->archivo= $archivo;

        return $this;
    }

    /**
     * Get archivo
     *
     * @return \Application\Sonata\MediaBundle\Entity\Media 
     */
    public function getArchivo()
    {
        return $this->archivo;
    }

    //..
}

Como se puede ver, es una relación Uno a Uno (OneToOne).

Segundo, creamos el contexto

sonata_media.yml

sonata_media:

    #...
      
    contexts:

        context_name:

            providers:

                - sonata.media.provider.image
                - sonata.media.provider.file
                - sonata.media.provider.video
                - sonata.media.provider.youtube

            formats:
                admin: { width: 55 , height: 55 , quality: 80}
                small: { width: 75 , quality: 80}
                medium: { width: 125 , quality: 80}
                big: { width: 265 , quality: 80}  

El nombre del contexto (context), definido en la línea 7, es el que utilizaremos en la Admin Class para SonataAdminBundle en el siguiente paso.

Tercero y el motivo de este Post, creamos el filtro en la Admin Class

PrensaAdmin.php

<?php

namespace AppBundle\Admin;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\AdminBundle\Route\RouteCollection;

/**
 * Description of PrensaAdmin
 *
 * @author Juanjo García
 */
class PrensaAdmin extends Admin {

    protected function configureRoutes(RouteCollection $collection) {
        //...
    }

    // Fields to be shown on create/edit forms
    protected function configureFormFields(FormMapper $formMapper) {
        //...
    }

    // Fields to be shown on filter forms
    protected function configureDatagridFilters(DatagridMapper $datagridMapper) {
        
        $pool  = $this->getConfigurationPool()->getContainer()->get('sonata.media.pool');
		
        $providers = array();

        $providerNames = (array) $pool->getProviderNamesByContext('context_name');

        foreach ($providerNames as $name) {

            $providers[$name] = $name;
        }

        $datagridMapper->add('archivo.providerName', 'doctrine_orm_choice', array(
            'field_options' => array(
                'choices' => $providers,
                'required' => false,
                'multiple' => false,
                'expanded' => false,
            ),
            'field_type' => 'choice',
        ));
    }

    // Fields to be shown on lists
    protected function configureListFields(ListMapper $listMapper) {
        //...
    }

    /**
     * @param ShowMapper $showMapper
     */
    protected function configureShowFields(ShowMapper $showMapper) {
        //...
    }
}

Como se puede ver en la línea 42, el primer parámetro de add() es el nombre del campo en la entidad Prensa, seguido por el nombre del campo de la segunda entidad, separados por un punto.

Para calcular los proveedores del contexto, nos fijamos de la línea 31 a la 40, aquí recuperamos este listado, utilizando el nombre del contexto creado para esta entidad.

El array con el listado de los proveedores (sonata.media.provider) se pasa al filtro en la línea 44.

Referencias

En la documentación de SonataMediaBundle, podemos encontrar la información de como filtrar por las propiedades de una subentidad, FILTERING BY SUB ENTITY PROPERTIES