I need to integrate this two bundles to be able to add Tags to an Media Entity (Image, Video, etc.).
I'm using:
"sonata-project/media-bundle":"version": "2.3.1" "sonata-project/classification-bundle":"version": "2.2.1" "symfony/symfony":"version": "v2.4.10"
In the sonata sandbox they demonstrate overriding entities.
I'd suggest reviewing their appbundle directory structure and configs. You may have to use the current 2.3 branch folder layout but the concept is the same.
the examples below will assume you are overriding/extending every entity. If you are only planning on overriding the media entity then I believe you would just need to change the namespace for the AppBundle\Entity\Classification\Tag
to Sonata\ClassificationBundle\Model\Tag
(not tested)
you could add extra properties to the media entity located here
AppBundle\Entity\Media\Media.php
/**
* @var ArrayCollection|\AppBundle\Entity\Classification\Tag[]
*/
protected $tags;
/**
* {@inheritdoc}
*/
public function __construct()
{
parent::__construct();
$this->tags = new ArrayCollection();
}
/**
* @return ArrayCollection|\AppBundle\Entity\Classification\Tag[]
*/
public function getTags()
{
return $this->tags;
}
/**
* @param ArrayCollection|\AppBundle\Entity\Classification\Tag[] $tags
*/
public function setTags($tags)
{
$this->tags = $tags;
}
then edit the doctrine xml located here to include these new relationships
AppBundle\Resources\config\doctrine\Media.Media.orm.xml
<many-to-many field="tags" target-entity="\AppBundle\Entity\Classification\Tag">
<cascade>
<cascade-persist/>
</cascade>
<join-table name="media__media_tag">
<join-columns>
<join-column name="media_id" referenced-column-name="id" nullable="false" unique="false" />
</join-columns>
<inverse-join-columns>
<join-column name="tag_id" referenced-column-name="id" column-definition="INT NULL" />
</inverse-join-columns>
</join-table>
</many-to-many>
notice we're creating a new join table called media__media_tag
this is following the existing patter and prefixing the table with media__
and media_tag
indicates the relationship.
we have solved the part of extending the current schema. You'll then need to tell the bundle to use your class instead as seen here (this could be in your app/config/config.yml
instead of being imported from app/config/sonata/sonata_media.yml
like the sandbox
sonata_media:
class:
media: AppBundle\Entity\Media\Media
The last step would be to add the property to the MediaAdmin class for management. This part is a little more tricky and I'm not sure if its the most ideal solution.
MediaBundle has an admin class for each storage model ORM|ODM|PHPCR
implementing the abstract class BaseMediaAdmin unfortunately we would have to extend each one used. I beleive ORM is the most common so we'll extend that one
what we are looking to do is add a form field for the tags
so creating a new directory Admin
inside AppBundle
and a class called MediaAdmin
(or whatever you like as long as it ends in Admin) and extend the class Sonata\MediaBundle\Admin\ORM\MediaAdmin
. The example below we override configureFormFields and call the parent before adding the field for tags.
AppBundle\Admin\MediaAdmin.php
namespace AppBundle\Admin;
class MediaAdmin extends \Sonata\MediaBundle\Admin\ORM
{
/**
* {@inheritdoc}
*/
protected function configureFormFields(FormMapper $formMapper)
{
parent::configureFormFields($formMapper);
$formMapper->add('tags', 'sonata_type_model', array('multiple' => true, 'by_reference' => false));
}
then we need to add a compiler pass to override the MediaAdmin service with our class.
AppBundle\AppBundle.php
namespace AppBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use AppBundle\DependencyInjection\Compiler\OverrideServiceCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class AppBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new OverrideServiceCompilerPass());
}
}
AppBundle\DependencyInjection\Compiler\OverrideServiceCompilerPass.php
namespace AppBundle\DependencyInjection\Compiler;
use AppBundle\Admin\MediaAdmin;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class OverrideServiceCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('sonata.media.admin.media');
$definition->setClass(MediaAdmin::class);
}
}
if you wanted to add a tag filter you could override configureDatagridFilters
, but this should be everything needed to get you started.