Skip to content

Instantly share code, notes, and snippets.

@OskarStark
Last active February 15, 2021 05:08
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save OskarStark/ee012ddd7f65a5d914da to your computer and use it in GitHub Desktop.
Save OskarStark/ee012ddd7f65a5d914da to your computer and use it in GitHub Desktop.
If you need to get the SonataMedia public urls exposed through the api
<?php
namespace Application\Sonata\MediaBundle\Listener;
use Application\Sonata\MediaBundle\Entity\Media;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Sonata\MediaBundle\Provider\MediaProviderInterface;
use Sonata\MediaBundle\Provider\Pool;
use Symfony\Component\DependencyInjection\ContainerInterface;
class InjectMediaUrlsListener
{
/**
* @var ContainerInterface
*/
private $container;
/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* @param LifecycleEventArgs $args
*/
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof Media) {
$this->injectMediaUrls($entity);
}
}
/**
* Generate and inject public URLs for the given Media entity.
*
* @param Media $media
*/
private function injectMediaUrls(Media $media)
{
$pool = $this->getPool();
$context = $media->getContext();
$formats = $pool->getFormatNamesByContext($context);
if (null === $formats) {
return;
}
$provider = $this->getProvider($media->getProviderName());
$publicUrls = array();
foreach ($formats as $format => $options) {
$format = $provider->getFormatName($media, $format);
$options['url'] = $provider->generatePublicUrl($media, $format);
$publicUrls[str_replace($context.'_', '', $format)] = $options;
}
if ('sonata.media.provider.file' === $media->getProviderName()) {
$publicUrls['reference'] = $provider->generatePublicUrl($media, 'reference');
}
$media->setPublicUrls($publicUrls);
}
/**
* Lazy-load the media pool from the container.
*
* @return Pool
*/
private function getPool()
{
return $this->container->get('sonata.media.pool');
}
/**
* Get the provider service by name.
*
* @param string $name
* @return MediaProviderInterface
*/
private function getProvider($name)
{
return $this->container->get($name);
}
}
<?php
namespace Application\Sonata\MediaBundle\Entity;
use AppBundle\Interfaces\EtagProviderInterface;
use AppBundle\Traits\EtagProviderTrait;
use AppBundle\Traits\SerializeModelNameTrait;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation as Serializer;
use Sonata\MediaBundle\Entity\BaseMedia as BaseMedia;
/**
* This file has been generated by the Sonata EasyExtends bundle ( https://sonata-project.org/bundles/easy-extends ).
*
* References :
* working with object : http://www.doctrine-project.org/projects/orm/2.0/docs/reference/working-with-objects/en
*
* @Serializer\AccessorOrder("alphabetical")
*
* @Hateoas\Relation(
* "self",
* href = @Hateoas\Route("api_get_media", parameters = {"id" = "expr(object.getId())"}, absolute = true)
* )
*/
class Media extends BaseMedia implements EtagProviderInterface
{
/**
* The unique identifier of the Media.
*
* @var int
*/
protected $id;
/**
* @var array
*/
private $publicUrls = array();
/**
* Get id.
*
* @return int $id
*/
public function getId()
{
return $this->id;
}
/**
* @param $publicUrls array
*
* @return self
*/
public function setPublicUrls(array $publicUrls)
{
$this->publicUrls = $publicUrls;
return $this;
}
/**
* @return array
*/
public function getPublicUrls()
{
return $this->publicUrls;
}
/**
* @param $format string
*
* @return null|string
*/
public function getPublicUrlByFormat($format)
{
if (!isset($this->publicUrls[$format])) {
return null;
}
return $this->publicUrls[$format]['url'];
}
}
@enekochan
Copy link

Is it possible to get a media provider by name in a service/listener/twig-extension/etc. without injecting the container?

https://gist.github.com/OskarStark/ee012ddd7f65a5d914da#file-injectmediaurlslistener-php-L86

As it is discouraged to do so I'm trying to remove it wherever I can.

@goroba
Copy link

goroba commented Jan 10, 2019

I guess this should work correctly for https://gist.github.com/OskarStark/ee012ddd7f65a5d914da#file-injectmediaurlslistener-php-L51

$provider = $pool->getProvider($media->getProviderName());

So, you can inject only sonata.media.pool service. Injecting the whole container not the best practice.

@romainnorberg
Copy link

thanks @goroba

@OskarStark
Copy link
Author

I really can’t remember but I would say yes it’s possible without the whole container 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment