From ae83b43e6f0c780aba7e95801efaff0082008409 Mon Sep 17 00:00:00 2001 From: Reto Ryter Date: Fri, 8 Mar 2013 14:54:14 +0100 Subject: [PATCH 1/4] added cache-invalidator-listener service (just the setup) --- .../ImageCacheInvalidatorListener.php | 30 +++++++++++++++++++ Resources/config/odm.xml | 4 --- Resources/config/odm_image.xml | 20 +++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 EventListener/ImageCacheInvalidatorListener.php create mode 100644 Resources/config/odm_image.xml diff --git a/EventListener/ImageCacheInvalidatorListener.php b/EventListener/ImageCacheInvalidatorListener.php new file mode 100644 index 00000000..35a189e6 --- /dev/null +++ b/EventListener/ImageCacheInvalidatorListener.php @@ -0,0 +1,30 @@ + - - - - diff --git a/Resources/config/odm_image.xml b/Resources/config/odm_image.xml new file mode 100644 index 00000000..0bb3ddfe --- /dev/null +++ b/Resources/config/odm_image.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + From 54ea79e682bee10f6121c5f07a575a198d81044d Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Tue, 12 Mar 2013 19:03:03 +0100 Subject: [PATCH 2/4] starting to implement invalidation --- .../DoctrinePHPCRExtension.php | 9 ++- .../ImageCacheInvalidatorListener.php | 30 -------- .../ImagineCacheInvalidatorSubscriber.php | 69 +++++++++++++++++++ Resources/config/odm_image.xml | 13 ++-- 4 files changed, 84 insertions(+), 37 deletions(-) delete mode 100644 EventListener/ImageCacheInvalidatorListener.php create mode 100644 EventListener/ImagineCacheInvalidatorSubscriber.php diff --git a/DependencyInjection/DoctrinePHPCRExtension.php b/DependencyInjection/DoctrinePHPCRExtension.php index e6312b91..689b4c6b 100644 --- a/DependencyInjection/DoctrinePHPCRExtension.php +++ b/DependencyInjection/DoctrinePHPCRExtension.php @@ -145,14 +145,14 @@ private function loadJackalopeSession(array $session, ContainerBuilder $containe // Factory if (isset($session['backend']['factory'])) { /** - * If it is a class, pass the name as is, else assume it is + * If it is a class, pass the name as is, else assume it is * a service id and get a reference to it */ if (class_exists($session['backend']['factory'])) { - $parameters['jackalope.factory'] = $session['backend']['factory']; + $parameters['jackalope.factory'] = $session['backend']['factory']; } else { $parameters['jackalope.factory'] = new Reference($session['backend']['factory']); - } + } } break; } @@ -251,6 +251,9 @@ private function odmLoad(array $config, ContainerBuilder $container) $dm->addMethodCall('setLocaleChooserStrategy', array(new Reference('doctrine_phpcr.odm.locale_chooser'))); } + // TODO make optional + $this->loader->load('odm_image.xml'); + $documentManagers = array(); foreach ($config['document_managers'] as $name => $documentManager) { if (empty($config['default_document_manager'])) { diff --git a/EventListener/ImageCacheInvalidatorListener.php b/EventListener/ImageCacheInvalidatorListener.php deleted file mode 100644 index 35a189e6..00000000 --- a/EventListener/ImageCacheInvalidatorListener.php +++ /dev/null @@ -1,30 +0,0 @@ -manager = $manager; + } + + /** + * {@inheritDoc} + */ + public function getSubscribedEvents() + { + return array( + 'postUpdate', + 'preRemove', // when removing, do before the flush to still get parents + ); + } + + public function postUpdate(LifecycleEventArgs $args) + { + $this->invalidateCache($args); + } + + public function preRemove(LifecycleEventArgs $args) + { + $this->invalidateCache($args); + } + + /** + * Check if this could mean an image document was modified (check resource, + * file and image) + * + * @param LifecycleEventArgs $args + */ + private function invalidateCache(LifecycleEventArgs $args) + { + $document = $args->getDocument(); + if ($document instanceof Resource) { + $document = $document->getParent(); + } + if ($document instanceof File) { + $document = $document->getParent(); + } + if ($document instanceof Image) { + // TODO: this does not work, what do we need to pass to manager->remove? + // TODO: can we invalidate all caches? otherwise inject filter name(s)? by config + $this->manager->remove($document->getId(), 'image_upload_thumbnail'); + } + } + +} diff --git a/Resources/config/odm_image.xml b/Resources/config/odm_image.xml index 0bb3ddfe..39a8059e 100644 --- a/Resources/config/odm_image.xml +++ b/Resources/config/odm_image.xml @@ -4,15 +4,20 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + Doctrine\Bundle\PHPCRBundle\Form\Type\ImageType + Doctrine\Bundle\PHPCRBundle\EventListener\ImagineCacheInvalidatorSubscriber + + - + - - - + + + From 9ac3f2864f93be8e20b4290a55cd002cd3d698a7 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Wed, 13 Mar 2013 12:09:04 +0100 Subject: [PATCH 3/4] improve image type and invalidate imagine cache --- DependencyInjection/Configuration.php | 21 ++++++++ .../DoctrinePHPCRExtension.php | 14 ++++- .../ImagineCacheInvalidatorSubscriber.php | 52 +++++++++++++++++-- Form/Type/ImageType.php | 19 ++++++- Resources/config/odm_image.xml | 3 ++ Resources/views/Form/fields.html.twig | 2 +- 6 files changed, 102 insertions(+), 9 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 47035b9b..bf440e1e 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -154,6 +154,7 @@ private function addOdmSection(ArrayNodeDefinition $node) ->fixXmlConfig('document_manager') ->append($this->getOdmDocumentManagersNode()) ->append($this->getOdmLocaleNode()) + ->append($this->getOdmImagineNode()) ->end() ->end() ; @@ -245,4 +246,24 @@ private function getOdmCacheDriverNode($name) return $node; } + + private function getOdmImagineNode() + { + $treeBuilder = new TreeBuilder(); + $node = $treeBuilder->root('imagine'); + + $node + ->children() + ->scalarNode('enabled')->defaultValue(false)->end() + ->scalarNode('filter')->defaultValue('image_upload_thumbnail')->end() + ->arrayNode('extra_filters') + ->requiresAtLeastOneElement() + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ; + + return $node; + } } diff --git a/DependencyInjection/DoctrinePHPCRExtension.php b/DependencyInjection/DoctrinePHPCRExtension.php index 689b4c6b..4bfecb01 100644 --- a/DependencyInjection/DoctrinePHPCRExtension.php +++ b/DependencyInjection/DoctrinePHPCRExtension.php @@ -42,6 +42,7 @@ class DoctrinePHPCRExtension extends AbstractDoctrineExtension private $defaultSession; private $sessions = array(); private $bundleDirs = array(); + /** @var XmlFileLoader */ private $loader; public function load(array $configs, ContainerBuilder $container) @@ -251,8 +252,17 @@ private function odmLoad(array $config, ContainerBuilder $container) $dm->addMethodCall('setLocaleChooserStrategy', array(new Reference('doctrine_phpcr.odm.locale_chooser'))); } - // TODO make optional - $this->loader->load('odm_image.xml'); + if ($config['imagine']['enabled']) { + $filter = $config['imagine']['filter']; + $filters = isset($config['imagine']['extra_filters']) && is_array($config['imagine']['extra_filters']) + ? $config['imagine']['extra_filters'] + : array(); + + $filters[] = $filter; + $container->setParameter('doctrine_phpcr.odm.subscriber.image_cache.filter', $filter); + $container->setParameter('doctrine_phpcr.odm.subscriber.image_cache.all_filters', $filters); + $this->loader->load('odm_image.xml'); + } $documentManagers = array(); foreach ($config['document_managers'] as $name => $documentManager) { diff --git a/EventListener/ImagineCacheInvalidatorSubscriber.php b/EventListener/ImagineCacheInvalidatorSubscriber.php index 66719b96..12133112 100644 --- a/EventListener/ImagineCacheInvalidatorSubscriber.php +++ b/EventListener/ImagineCacheInvalidatorSubscriber.php @@ -3,6 +3,8 @@ namespace Doctrine\Bundle\PHPCRBundle\EventListener; use Doctrine\Common\Util\Debug; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\HttpFoundation\Request; use Doctrine\ODM\PHPCR\Document\Image; use Doctrine\ODM\PHPCR\Document\File; use Doctrine\ODM\PHPCR\Document\Resource; @@ -17,10 +19,34 @@ */ class ImagineCacheInvalidatorSubscriber implements EventSubscriber { + /** + * @var CacheManager + */ + private $manager; + + /** + * Used to get the request from to remove cache + * @var Container + */ + private $container; - public function __construct(CacheManager $manager) + /** + * Filter names to invalidate + * @var array + */ + private $filters; + + /** + * @param CacheManager $manager the imagine cache manager + * @param Container $container to get the request from. Need to inject + * this as otherwise we have a scope problem + * @param array $filter list of filter names to invalidate + */ + public function __construct(CacheManager $manager, Container $container, $filters) { $this->manager = $manager; + $this->container = $container; + $this->filters = $filters; } /** @@ -30,15 +56,26 @@ public function getSubscribedEvents() { return array( 'postUpdate', - 'preRemove', // when removing, do before the flush to still get parents + 'preRemove', ); } + /** + * Invalidate cache after a document was updated. + * + * @param LifecycleEventArgs $args + */ public function postUpdate(LifecycleEventArgs $args) { $this->invalidateCache($args); } + /** + * Invalidate the cache when removing an image. Do this before the flush to + * still have access to the parent of the document. + * + * @param LifecycleEventArgs $args + */ public function preRemove(LifecycleEventArgs $args) { $this->invalidateCache($args); @@ -60,9 +97,14 @@ private function invalidateCache(LifecycleEventArgs $args) $document = $document->getParent(); } if ($document instanceof Image) { - // TODO: this does not work, what do we need to pass to manager->remove? - // TODO: can we invalidate all caches? otherwise inject filter name(s)? by config - $this->manager->remove($document->getId(), 'image_upload_thumbnail'); + foreach ($this->filters as $filter) { + $path = $this->manager->resolve($this->container->get('request'), $document->getId(), 'image_upload_thumbnail')->getTargetUrl(); + // TODO: this might not be needed https://github.com/liip/LiipImagineBundle/issues/162 + if (false !== strpos($path, $filter)) { + $path = substr($path, strpos($path, $filter) + strlen($filter)); + } + $this->manager->remove($path, $filter); + } } } diff --git a/Form/Type/ImageType.php b/Form/Type/ImageType.php index 2258ab0d..f796ebf3 100644 --- a/Form/Type/ImageType.php +++ b/Form/Type/ImageType.php @@ -3,12 +3,21 @@ namespace Doctrine\Bundle\PHPCRBundle\Form\Type; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\Form\FormBuilderInterface; use Doctrine\Bundle\PHPCRBundle\Form\DataTransformer\ModelToFileTransformer; class ImageType extends AbstractType { + private $defaultFilter; + + public function __construct($defaultFilter) + { + $this->defaultFilter = $defaultFilter; + } + public function getParent() { return 'file'; @@ -25,8 +34,16 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->addModelTransformer($transformer); } + public function buildView(FormView $view, FormInterface $form, array $options) + { + $view->vars['imagine_filter'] = $options['imagine_filter']; + } + public function setDefaultOptions(OptionsResolverInterface $options) { - $options->setDefaults(array('data_class' => 'Doctrine\ODM\PHPCR\Document\Image')); + $options->setDefaults(array( + 'data_class' => 'Doctrine\ODM\PHPCR\Document\Image', + 'imagine_filter' => $this->defaultFilter, + )); } } diff --git a/Resources/config/odm_image.xml b/Resources/config/odm_image.xml index 39a8059e..4affcd63 100644 --- a/Resources/config/odm_image.xml +++ b/Resources/config/odm_image.xml @@ -12,12 +12,15 @@ + %doctrine_phpcr.odm.subscriber.image_cache.filter% + + %doctrine_phpcr.odm.subscriber.image_cache.all_filters% diff --git a/Resources/views/Form/fields.html.twig b/Resources/views/Form/fields.html.twig index 03215ce7..5d35c36e 100644 --- a/Resources/views/Form/fields.html.twig +++ b/Resources/views/Form/fields.html.twig @@ -1,6 +1,6 @@ {% block phpcr_odm_image_widget %} {{ form_widget(form) }} {% if form.vars.data %} - + {% endif %} {% endblock %} \ No newline at end of file From 79e8e2efec648fef4aa47cc8be889f588f15e56a Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Wed, 13 Mar 2013 13:37:14 +0100 Subject: [PATCH 4/4] do not fail if the field is not set --- DependencyInjection/DoctrinePHPCRExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DependencyInjection/DoctrinePHPCRExtension.php b/DependencyInjection/DoctrinePHPCRExtension.php index 4bfecb01..430574ae 100644 --- a/DependencyInjection/DoctrinePHPCRExtension.php +++ b/DependencyInjection/DoctrinePHPCRExtension.php @@ -252,7 +252,7 @@ private function odmLoad(array $config, ContainerBuilder $container) $dm->addMethodCall('setLocaleChooserStrategy', array(new Reference('doctrine_phpcr.odm.locale_chooser'))); } - if ($config['imagine']['enabled']) { + if (isset($config['imagine']['enabled']) && $config['imagine']['enabled']) { $filter = $config['imagine']['filter']; $filters = isset($config['imagine']['extra_filters']) && is_array($config['imagine']['extra_filters']) ? $config['imagine']['extra_filters']