diff --git a/Admin/ContainerBlockAdmin.php b/Admin/ContainerBlockAdmin.php index b3ead5d7..3c1c6425 100644 --- a/Admin/ContainerBlockAdmin.php +++ b/Admin/ContainerBlockAdmin.php @@ -30,8 +30,8 @@ protected function configureFormFields(FormMapper $formMapper) { $formMapper ->with('form.group_general') - ->add('parentDocument', 'doctrine_phpcr_odm_tree', array('root_node' => $this->contentRoot, 'choice_list' => array(), 'select_root_node' => true)) - ->add('name', 'text') + ->add('parentDocument', 'doctrine_phpcr_odm_tree', array('root_node' => $this->contentRoot, 'choice_list' => array(), 'select_root_node' => true)) + ->add('name', 'text') ->end() ; } diff --git a/Admin/Imagine/MinimalImagineBlockAdmin.php b/Admin/Imagine/MinimalImagineBlockAdmin.php new file mode 100644 index 00000000..ee3f26b8 --- /dev/null +++ b/Admin/Imagine/MinimalImagineBlockAdmin.php @@ -0,0 +1,27 @@ +getSubject() && $this->getSubject()->getParent()) ? false : true; + + $formMapper + ->with('form.group_general') + ->add('label', 'text', array('required' => false)) + ->add('image', 'phpcr_odm_image', array('required' => $imageRequired, 'label' => 'Slide Image', 'data_class' => 'Doctrine\ODM\PHPCR\Document\Image')) + ->add('position', 'hidden', array('mapped' => false)) + ->end(); + } +} diff --git a/Admin/Imagine/MinimalSlideshowBlockAdmin.php b/Admin/Imagine/MinimalSlideshowBlockAdmin.php new file mode 100644 index 00000000..25129615 --- /dev/null +++ b/Admin/Imagine/MinimalSlideshowBlockAdmin.php @@ -0,0 +1,101 @@ +addIdentifier('id', 'text') + ->add('title', 'text'); + } + + protected function configureFormFields(FormMapper $formMapper) + { + parent::configureFormFields($formMapper); + $formMapper + ->with('form.group_general') + ->add('title', 'text') + ->with('Items') + ->add('children', 'sonata_type_collection', + array( + 'by_reference' => false, + ), + array( + 'edit' => 'inline', + 'inline' => 'table', + 'admin_code' => 'symfony_cmf_block.imagine.minimal_imagine_admin', + 'sortable' => 'position', + )) + ->end(); + + $formBuilder = $formMapper->getFormBuilder(); + $formBuilder->addEventListener(FormEvents::POST_BIND, array($this, 'onPostBind')); + } + + // reorder children according to the form data + public function onPostBind(FormEvent $event) + { + /** @var $newCollection ChildrenCollection */ + $newCollection = $event->getData()->getChildren(); + $newCollection->clear(); + + foreach ($event->getForm()->get('children') as $child) { + if ($child->get('_delete')->getData()) { + // do not re-add a deleted child + continue; + } + if ($child->getName()) { + // keep key in collection + $newCollection[$child->getName()] = $child->getData(); + } else { + $newCollection[] = $child->getData(); + } + } + } + + public function prePersist($slideshow) + { + foreach($slideshow->getChildren() as $child) { + $child->setName($this->generateName()); + } + } + + public function preUpdate($slideshow) + { + foreach($slideshow->getChildren() as $child) { + if (! $this->modelManager->getNormalizedIdentifier($child)) { + $child->setName($this->generateName()); + } + } + } + + /** + * Generate a most likely unique name + * + * TODO: have child documents use the autoname annotation once this is done: http://www.doctrine-project.org/jira/browse/PHPCR-103 + * + * @return string + */ + private function generateName() + { + return 'child_' . time() . '_' . rand(); + } +} diff --git a/Admin/Imagine/SlideshowBlockAdmin.php b/Admin/Imagine/SlideshowBlockAdmin.php new file mode 100644 index 00000000..e377aa92 --- /dev/null +++ b/Admin/Imagine/SlideshowBlockAdmin.php @@ -0,0 +1,34 @@ +blockRoot = $blockRoot; + } + + protected function configureFormFields(FormMapper $formMapper) + { + parent::configureFormFields($formMapper); + $formMapper + ->with('form.group_general') + ->add('parentDocument', 'doctrine_phpcr_odm_tree', array('root_node' => $this->blockRoot, 'choice_list' => array(), 'select_root_node' => true)) + ->add('name', 'text') + ->end(); + } +} diff --git a/Block/ContainerBlockService.php b/Block/ContainerBlockService.php index 4bf91a68..72166609 100644 --- a/Block/ContainerBlockService.php +++ b/Block/ContainerBlockService.php @@ -15,16 +15,23 @@ class ContainerBlockService extends BaseBlockService implements BlockServiceInte { protected $blockRenderer; + protected $template = 'SymfonyCmfBlockBundle:Block:block_container.html.twig'; /** * @param string $name * @param \Symfony\Bundle\FrameworkBundle\Templating\EngineInterface $templating * @param \Sonata\BlockBundle\Block\BlockRendererInterface $blockRenderer + * @param string|null $template */ - public function __construct($name, EngineInterface $templating, BlockRendererInterface $blockRenderer) + public function __construct($name, EngineInterface $templating, BlockRendererInterface $blockRenderer, $template = null) { parent::__construct($name, $templating); + $this->blockRenderer = $blockRenderer; + + if ($template) { + $this->template = $template; + } } /** @@ -48,7 +55,7 @@ public function validateBlock(ErrorElement $errorElement, BlockInterface $block) */ protected function getTemplate() { - return 'SymfonyCmfBlockBundle:Block:block_container.html.twig'; + return $this->template; } /** diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index fed1dbd1..cc7ec391 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -28,7 +28,9 @@ public function getConfigTreeBuilder() $rootNode ->children() ->scalarNode('document_manager_name')->defaultValue('default')->end() - ->scalarNode('content_basepath')->defaultNull('/cms/content')->end() + ->scalarNode('content_basepath')->defaultValue('/cms/content')->end() + ->scalarNode('block_basepath')->defaultValue('/cms/content')->end() + ->scalarNode('imagine')->defaultValue(false)->end() ->scalarNode('simple_admin_class')->defaultNull()->end() ->scalarNode('simple_document_class')->defaultNull()->end() ->scalarNode('container_admin_class')->defaultNull()->end() @@ -74,7 +76,6 @@ public function getConfigTreeBuilder() ->end() ->end() ->end() - ->end() ; diff --git a/DependencyInjection/SymfonyCmfBlockExtension.php b/DependencyInjection/SymfonyCmfBlockExtension.php index 0b9bb133..15177049 100644 --- a/DependencyInjection/SymfonyCmfBlockExtension.php +++ b/DependencyInjection/SymfonyCmfBlockExtension.php @@ -13,6 +13,9 @@ public function load(array $configs, ContainerBuilder $container) { $config = $this->processConfiguration(new Configuration(), $configs); + $container->setParameter($this->getAlias() . '.content_basepath', $config['content_basepath']); + $container->setParameter($this->getAlias() . '.block_basepath', $config['block_basepath']); + $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.xml'); @@ -33,6 +36,10 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter($this->getAlias() . '.multilang.locales', $config['multilang']['locales']); } + if ($config['imagine']) { + $loader->load('imagine.xml'); + } + if (isset($config['simple_document_class'])) { $container->setParameter($this->getAlias() . '.simple_document_class', $config['simple_document_class']); } @@ -61,10 +68,6 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter($this->getAlias() . '.' . 'action_admin_class', $config['action_admin_class']); } - if (isset($config['action_admin_class'])) { - $container->setParameter($this->getAlias() . '.' . 'action_admin_class', $config['action_admin_class']); - } - $blockLoader = $container->getDefinition('symfony_cmf.block.service'); $blockLoader->replaceArgument(1, $config['document_manager_name']); @@ -96,6 +99,10 @@ public function loadSonataAdmin($config, XmlFileLoader $loader, ContainerBuilder if (isset($config['simple_admin_class'])) { $container->setParameter($this->getAlias() . '.' . $prefix . 'simple_admin_class', $config['simple_admin_class']); } + + if (isset($config['imagine']) && $config['imagine']) { + $loader->load('imagine.admin.xml'); + } } public function loadSonataCache($config, XmlFileLoader $loader, ContainerBuilder $container) diff --git a/Document/ContainerBlock.php b/Document/ContainerBlock.php index 8029f714..f64e7e0e 100644 --- a/Document/ContainerBlock.php +++ b/Document/ContainerBlock.php @@ -8,13 +8,16 @@ use Sonata\BlockBundle\Model\BlockInterface; /** - * Block that contains other blocks ... + * Block that contains other blocks * * @PHPCRODM\Document(referenceable=true) */ class ContainerBlock extends BaseBlock { - /** @PHPCRODM\Children */ + /** + * @var ChildrenCollection + * @PHPCRODM\Children + */ protected $children; public function __construct($name = null) @@ -44,16 +47,44 @@ public function setChildren(ChildrenCollection $children) /** * Add a child to this container * - * @param BlockInterface $child - * @param string $key OPTIONAL + * @param BlockInterface $child + * @param string $key the collection index name to use in the + * child collection if not set, the child will simply be appended at + * the end + * * @return boolean */ public function addChild(BlockInterface $child, $key = null) { if ($key != null) { + return $this->children->set($key, $child); } return $this->children->add($child); } + + /** + * Alias to addChild to make the form layer happy + * + * @param BlockInterface $children + * + * @return boolean + */ + public function addChildren(BlockInterface $children) + { + return $this->addChild($children); + } + + /** + * Remove a child from this container + * + * @param mixed $child + * @return void + */ + public function removeChild($child) + { + $this->children->removeElement($child); + } + } diff --git a/Document/ImagineBlock.php b/Document/ImagineBlock.php new file mode 100644 index 00000000..efd1468a --- /dev/null +++ b/Document/ImagineBlock.php @@ -0,0 +1,92 @@ +label = $label; + } + + public function getLabel() + { + return $this->label; + } + + /** + * Set the image for this block. + * + * Setting null will do nothing, as this is what happens when you edit this + * block in a form without uploading a replacement file. + * + * If you need to delete the Image, you can use getImage and delete it with + * the document manager. Note that this block does not make much sense + * without an image, though. + * + * @param Image $image optional the image to update + */ + public function setImage($image) + { + if (!$image) { + return; + } elseif ($this->image && $this->image->getFile()) { + // TODO: this is needed due to a bug in PHPCRODM (http://www.doctrine-project.org/jira/browse/PHPCR-98) + // TODO: this can be removed once the bug is fixed + $this->image->getFile()->setFileContent($image->getFile()->getFileContent()); + } else { + $this->image = $image; + } + } + + /** + * @return Image + */ + public function getImage() + { + return $this->image; + } + + /** + * @return \PHPCR\NodeInterface + */ + public function getNode() + { + return $this->node; + } + +} diff --git a/Document/MultilangImagineBlock.php b/Document/MultilangImagineBlock.php new file mode 100644 index 00000000..b4747bd7 --- /dev/null +++ b/Document/MultilangImagineBlock.php @@ -0,0 +1,30 @@ +locale = $locale; + } + + public function getLocale() + { + return $this->locale; + } +} diff --git a/Document/SlideshowBlock.php b/Document/SlideshowBlock.php new file mode 100644 index 00000000..4f537f01 --- /dev/null +++ b/Document/SlideshowBlock.php @@ -0,0 +1,37 @@ +title; + } + + public function setTitle($title) { + $this->title = $title; + } + +} diff --git a/Resources/config/admin.xml b/Resources/config/admin.xml index 968b44b2..4cd501ea 100644 --- a/Resources/config/admin.xml +++ b/Resources/config/admin.xml @@ -24,5 +24,6 @@ %symfony_cmf_block.content_basepath% + diff --git a/Resources/config/container.admin.xml b/Resources/config/container.admin.xml index 8131017f..9922e159 100644 --- a/Resources/config/container.admin.xml +++ b/Resources/config/container.admin.xml @@ -7,7 +7,6 @@ Symfony\Cmf\Bundle\BlockBundle\Admin\ContainerBlockAdmin Symfony\Cmf\Bundle\BlockBundle\Document\ContainerBlock - /cms/content diff --git a/Resources/config/imagine.admin.xml b/Resources/config/imagine.admin.xml new file mode 100644 index 00000000..922673b5 --- /dev/null +++ b/Resources/config/imagine.admin.xml @@ -0,0 +1,77 @@ + + + + + + Symfony\Cmf\Bundle\BlockBundle\Admin\Imagine\SlideshowBlockAdmin + Symfony\Cmf\Bundle\BlockBundle\Admin\Imagine\MinimalSlideshowBlockAdmin + Symfony\Cmf\Bundle\BlockBundle\Document\SlideshowBlock + + Symfony\Cmf\Bundle\BlockBundle\Admin\Imagine\MinimalImagineBlockAdmin + Symfony\Cmf\Bundle\BlockBundle\Document\ImagineBlock + Symfony\Cmf\Bundle\BlockBundle\Document\MultilangImagineBlock + + + + + + + + %symfony_cmf_block.slideshow_document_class% + SonataAdminBundle:CRUD + + + + + + + + + + %symfony_cmf_block.slideshow_document_class% + SonataAdminBundle:CRUD + + + + + + + %symfony_cmf_block.block_basepath% + + + + + + + + %symfony_cmf_block.imagine_document_class% + SonataAdminBundle:CRUD + + + + + + + %symfony_cmf_block.content_basepath% + + + + + + + %symfony_cmf_block.multilang_imagine_document_class% + SonataAdminBundle:CRUD + + + + + + + %symfony_cmf_block.content_basepath% + + + + + diff --git a/Resources/config/imagine.xml b/Resources/config/imagine.xml new file mode 100644 index 00000000..3553e82a --- /dev/null +++ b/Resources/config/imagine.xml @@ -0,0 +1,18 @@ + + + + + + + + + + symfony_cmf.block.imagine + + SymfonyCmfBlockBundle:Block:block_imagine.html.twig + + + + diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 0f1a85aa..0d0ce068 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -45,6 +45,15 @@ + + + + symfony_cmf.block.slideshow + + + SymfonyCmfBlockBundle:Block:block_slideshow.html.twig + + diff --git a/Resources/translations/SymfonyCmfBlockBundle.en.yml b/Resources/translations/SymfonyCmfBlockBundle.en.yml index 426f814b..7de19738 100644 --- a/Resources/translations/SymfonyCmfBlockBundle.en.yml +++ b/Resources/translations/SymfonyCmfBlockBundle.en.yml @@ -5,8 +5,15 @@ dashboard: label_container_block: Container block label_reference_block: Reference block label_action_block: Action block + label_slideshow_block: Slideshow block breadcrumb: + link_slideshow_block_list: Slideshow Blocks + link_slideshow_block_edit: Edit + link_slideshow_simple_block_create: Create + link_slideshow_simple_block_edit: Edit + link_slideshow_simple_block_delete: Delete + link_simple_block_list: Simple blocks link_simple_block_create: Create link_simple_block_edit: Edit @@ -51,3 +58,6 @@ form: label_content: Content label_referenced_block: Referenced block label_action_name: Action name + label_children: Elements + label_label: Label + label_position: Position diff --git a/Resources/translations/SymfonyCmfBlockBundle.fr.yml b/Resources/translations/SymfonyCmfBlockBundle.fr.yml index 185f92b0..83d6d28a 100644 --- a/Resources/translations/SymfonyCmfBlockBundle.fr.yml +++ b/Resources/translations/SymfonyCmfBlockBundle.fr.yml @@ -5,8 +5,15 @@ dashboard: label_container_block: Bloc conteneur label_reference_block: Bloc référence label_action_block: Bloc action + label_slideshow_block: Bloc slideshow breadcrumb: + link_slideshow_block_list: Blocs slideshow + link_slideshow_block_edit: Edit + link_slideshow_simple_block_create: Créer + link_slideshow_simple_block_edit: Éditer + link_slideshow_simple_block_delete: Supprimer + link_simple_block_list: Blocs simples link_simple_block_create: Créer link_simple_block_edit: Éditer @@ -51,3 +58,6 @@ form: label_content: Contenu label_referenced_block: Bloc référencé label_action_name: Nom de l'action + label_children: Elements + label_label: Label + label_position: Position diff --git a/Resources/views/Block/block_imagine.html.twig b/Resources/views/Block/block_imagine.html.twig new file mode 100644 index 00000000..d38586d0 --- /dev/null +++ b/Resources/views/Block/block_imagine.html.twig @@ -0,0 +1,5 @@ +{% extends 'SymfonyCmfBlockBundle:Block:block_base.html.twig' %} + +{% block block %} + {{ block.label }}{{ block.label }} +{% endblock %} diff --git a/Resources/views/Block/block_slideshow.html.twig b/Resources/views/Block/block_slideshow.html.twig new file mode 100644 index 00000000..b3bd3891 --- /dev/null +++ b/Resources/views/Block/block_slideshow.html.twig @@ -0,0 +1,18 @@ +{% extends 'SymfonyCmfBlockBundle:Block:block_base.html.twig' %} + +{% block block %} + + {% if childBlocks %} + {% if block.title is defined %} +

{{ block.title }}

+ {% endif %} +
+
    + {% for item in childBlocks %} +
  • {{ item | raw }}
  • + {% endfor %} +
+
+ {% endif %} + +{% endblock %} diff --git a/composer.json b/composer.json index d8c4f69c..f4b8d0dd 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ }, "suggest": { "sonata-project/cache-bundle": "To add caching support for block loading", + "liip/imagine-bundle": "When using the ImagineBlock", "eko/feedbundle": "To use the RssBlock" }, "autoload":{