Skip to content

Commit

Permalink
Refactoring of event listeners(closes #8, #89, #123, #297)
Browse files Browse the repository at this point in the history
  • Loading branch information
Koc committed Sep 14, 2016
1 parent 0ecb31a commit accb50f
Show file tree
Hide file tree
Showing 25 changed files with 342 additions and 446 deletions.
15 changes: 8 additions & 7 deletions DependencyInjection/Compiler/RegisterPropelModelsPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Vich\UploaderBundle\Exception\MappingNotFoundException;

/**
* Register the uploadable models in BazingaPropelEventDispatcherBundle
*
* @author Kévin Gomez <contact@kevingomez.fr>
* @author Konstantin Myakshin <koc-dp@yandex.ru>
*/
class RegisterPropelModelsPass implements CompilerPassInterface
{
Expand All @@ -23,9 +25,7 @@ public function process(ContainerBuilder $container)
return;
}

$serviceTypes = array(
'inject', 'clean', 'remove', 'upload',
);
$serviceTypes = array('inject', 'clean', 'remove', 'upload',);

$metadata = $container->get('vich_uploader.metadata_reader');
$mappings = $container->getParameter('vich_uploader.mappings');
Expand All @@ -43,11 +43,12 @@ public function process(ContainerBuilder $container)
}

foreach ($serviceTypes as $type) {
if (!$container->has(sprintf('vich_uploader.listener.%s.%s', $type, $field['mapping']))) {
continue;
}
$listenerId = sprintf('vich_uploader.listener.%s.propel.%s', $type, $field['mapping']);

$definition = $container
->setDefinition($listenerId, new DefinitionDecorator(sprintf('vich_uploader.listener.%s.propel', $type)))
->replaceArgument(1, new Reference('vich_uploader.adapter.propel'));

$definition = $container->getDefinition(sprintf('vich_uploader.listener.%s.%s', $type, $field['mapping']));
$definition->setClass($container->getDefinition($definition->getParent())->getClass());
$definition->setPublic(true);
$definition->addTag('propel.event_subscriber', array('class' => $class));
Expand Down
44 changes: 19 additions & 25 deletions DependencyInjection/VichUploaderExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class VichUploaderExtension extends Extension
protected $tagMap = array(
'orm' => 'doctrine.event_subscriber',
'mongodb' => 'doctrine_mongodb.odm.event_subscriber',
'phpcr' => 'doctrine_phpcr.event_subscriber'
'phpcr' => 'doctrine_phpcr.event_subscriber',
);

/**
Expand Down Expand Up @@ -153,26 +153,24 @@ protected function fixDbDriverConfig(array $config)

protected function registerListeners(ContainerBuilder $container, array $config)
{
$servicesMap = array(
'inject_on_load' => array('name' => 'inject', 'priority' => 0),
'delete_on_update' => array('name' => 'clean', 'priority' => 50),
'delete_on_remove' => array('name' => 'remove', 'priority' => 0)
$dbDrivers = array();
foreach ($config['mappings'] as $mapping) {
$dbDrivers[$mapping['db_driver']] = true;
}
// register propel via compiler pass
unset($dbDrivers['propel']);

$serviceTypes = array(
'upload' => 0,
'inject' => 0,
'clean' => 50,
'remove' => 0,
);

foreach ($config['mappings'] as $name => $mapping) {
$driver = $mapping['db_driver'];

// create optionnal listeners
foreach ($servicesMap as $configOption => $service) {
if (!$mapping[$configOption]) {
continue;
}

$this->createListener($container, $name, $service['name'], $driver, $service['priority']);
foreach (array_keys($dbDrivers) as $driver) {
foreach ($serviceTypes as $serviceType => $priority) {
$this->createListener($container, $serviceType, $driver, $priority);
}

// the upload listener is mandatory
$this->createListener($container, $name, 'upload', $driver);
}
}

Expand All @@ -199,16 +197,12 @@ protected function createNamerService(ContainerBuilder $container, $mappingName,
return $mapping;
}

protected function createListener(ContainerBuilder $container, $name, $type, $driver, $priority = 0)
protected function createListener(ContainerBuilder $container, $type, $driver, $priority = 0)
{
$definition = $container
->setDefinition(sprintf('vich_uploader.listener.%s.%s', $type, $name), new DefinitionDecorator(sprintf('vich_uploader.listener.%s.%s', $type, $driver)))
->replaceArgument(0, $name)
->getDefinition(sprintf('vich_uploader.listener.%s.%s', $type, $driver))
->replaceArgument(1, new Reference('vich_uploader.adapter.'.$driver));

// propel does not require tags to work
if (isset($this->tagMap[$driver])) {
$definition->addTag($this->tagMap[$driver], array('priority' => $priority));
}
$definition->addTag($this->tagMap[$driver], array('priority' => $priority));
}
}
62 changes: 62 additions & 0 deletions EventListener/BaseListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Vich\UploaderBundle\EventListener;

use Vich\UploaderBundle\Util\ClassUtils;
use Vich\UploaderBundle\Adapter\AdapterInterface;
use Vich\UploaderBundle\Handler\UploadHandler;
use Vich\UploaderBundle\Metadata\MetadataReader;

/**
* BaseListener
*
* @author Konstantin Myakshin <koc-dp@yandex.ru>
*/
abstract class BaseListener
{
/**
* @var array
*/
protected $mappings;

/**
* @var AdapterInterface $adapter
*/
protected $adapter;

/**
* @var MetadataReader $metadata
*/
protected $metadata;

/**
* @var UploadHandler $handler
*/
protected $handler;

/**
* Constructs a new instance of listener.
*
* @param array $mappings The mappings configuration.
* @param AdapterInterface $adapter The adapter.
* @param MetadataReader $metadata The metadata reader.
* @param UploadHandler $handler The upload handler.
*/
public function __construct(array $mappings, AdapterInterface $adapter, MetadataReader $metadata, UploadHandler $handler)
{
$this->mappings = $mappings;
$this->adapter = $adapter;
$this->metadata = $metadata;
$this->handler = $handler;
}

protected function isFlagEnabledForField($flag, array $field)
{
return true === $this->mappings[$field['mapping']][$flag];
}

protected function getUploadableFields($object)
{
return $this->metadata->getUploadableFields(ClassUtils::getClass($object));
}
}
72 changes: 3 additions & 69 deletions EventListener/Doctrine/BaseListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,80 +3,14 @@
namespace Vich\UploaderBundle\EventListener\Doctrine;

use Doctrine\Common\EventSubscriber;

use Vich\UploaderBundle\Adapter\AdapterInterface;
use Vich\UploaderBundle\Handler\UploadHandler;
use Vich\UploaderBundle\Metadata\MetadataReader;
use Vich\UploaderBundle\Util\ClassUtils;
use Vich\UploaderBundle\EventListener\BaseListener as CommonListener;

/**
* BaseListener
*
* @author Kévin Gomez <contact@kevingomez.fr>
* @author Konstantin Myakshin <koc-dp@yandex.ru>
*/
abstract class BaseListener implements EventSubscriber
abstract class BaseListener extends CommonListener implements EventSubscriber
{
/**
* @var string
*/
protected $mapping;

/**
* @var AdapterInterface $adapter
*/
protected $adapter;

/**
* @var MetadataReader $metadata
*/
protected $metadata;

/**
* @var UploadHandler $handler
*/
protected $handler;

/**
* Constructs a new instance of UploaderListener.
*
* @param string $mapping The mapping name.
* @param AdapterInterface $adapter The adapter.
* @param MetadataReader $metadata The metadata reader.
* @param UploadHandler $handler The upload handler.
*/
public function __construct($mapping, AdapterInterface $adapter, MetadataReader $metadata, UploadHandler $handler)
{
$this->mapping = $mapping;
$this->adapter = $adapter;
$this->metadata = $metadata;
$this->handler = $handler;
}

/**
* Checks if the given object is uploadable using the current mapping.
*
* @param mixed $object The object to test.
*
* @return bool
*/
protected function isUploadable($object)
{
return $this->metadata->isUploadable(ClassUtils::getClass($object), $this->mapping);
}

/**
* Returns a list of uploadable fields for the given object and mapping.
*
* @param mixed $object The object to use.
*
* @return array<string> A list of field names.
*/
protected function getUploadableFields($object)
{
$fields = $this->metadata->getUploadableFields(ClassUtils::getClass($object), $this->mapping);

return array_map(function($data) {
return $data['propertyName'];
}, $fields);
}
}
36 changes: 20 additions & 16 deletions EventListener/Doctrine/CleanListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,47 @@

namespace Vich\UploaderBundle\EventListener\Doctrine;

use Doctrine\Common\EventArgs;
use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Events;

/**
* CleanListener
*
* Listen to the update event to delete old files accordingly.
*
* @author Konstantin Myakshin <koc-dp@yandex.ru>
* @author Kévin Gomez <contact@kevingomez.fr>
*/
class CleanListener extends BaseListener
{
/**
* The events the listener is subscribed to.
*
* @return array The array of events.
* {@inheritdoc}
*/
public function getSubscribedEvents()
{
return array(
'preUpdate',
);
return array(Events::preFlush);
}

/**
* @param EventArgs $event The event.
* @param PreFlushEventArgs $event
*/
public function preUpdate(EventArgs $event)
public function preFlush(PreFlushEventArgs $event)
{
$object = $this->adapter->getObjectFromArgs($event);
$em = $event->getEntityManager();
$identityMap = $em->getUnitOfWork()->getIdentityMap();

if (!$this->isUploadable($object)) {
return;
}
foreach ($identityMap as $class => $entities) {
$fields = $this->metadata->getUploadableFields($class);

foreach ($fields as $field) {
if (!$this->isFlagEnabledForField('delete_on_update', $field)) {
continue;
}

foreach ($this->getUploadableFields($object) as $field) {
$this->handler->clean($object, $field);
$this->adapter->recomputeChangeSet($event);
foreach ($entities as $entity) {
$this->handler->clean($entity, $field['propertyName']);
}
}
}
}
}
26 changes: 12 additions & 14 deletions EventListener/Doctrine/InjectListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,40 @@

namespace Vich\UploaderBundle\EventListener\Doctrine;

use Doctrine\Common\EventArgs;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Events;

/**
* InjectListener
*
* Listen to the load event in order to inject File objects.
*
* @author Konstantin Myakshin <koc-dp@yandex.ru>
* @author Kévin Gomez <contact@kevingomez.fr>
*/
class InjectListener extends BaseListener
{
/**
* The events the listener is subscribed to.
*
* @return array The array of events.
* {@inheritdoc}
*/
public function getSubscribedEvents()
{
return array(
'postLoad',
);
return array(Events::postLoad);
}

/**
* @param EventArgs $event The event.
* @param LifecycleEventArgs $event
*/
public function postLoad(EventArgs $event)
public function postLoad(LifecycleEventArgs $event)
{
$object = $this->adapter->getObjectFromArgs($event);

if (!$this->isUploadable($object)) {
return;
}

foreach ($this->getUploadableFields($object) as $field) {
$this->handler->inject($object, $field);
if (!$this->isFlagEnabledForField('inject_on_load', $field)) {
continue;
}

$this->handler->inject($object, $field['propertyName']);
}
}
}
Loading

0 comments on commit accb50f

Please sign in to comment.