eZ Platform Discussions

[LP] Multiple Content List Block: Articles should appear only once


#1

Salut !

On my landing page, (managed by the studio), my administrators will place different automatic or manual content display blocks.

Example: An embed block with an object of type UNE that contains an object relationship field.
This block displays a list of items chosen by the administrator.

Further on he adds a “content List” block.
It selects a folder, a number of articles (5), a type of content (article).
But we don’t want articles that are already posted in the UNE to appear in the “content List”.

How to do this?


#2

I’m going on the idea of “overloading” ContentListBlockListener.

I’m relying on this doc. (Hopefully it’s still valid. I’m in 2.3)
https://doc.ezplatform.com/en/2.2/guide/extending_page

I start by defining a service:

service.yml

services:
    my.block.contentlist:
        class: MyBundle\Block\ContentListBlockListener
        tags:
            - {name: ezplatform.ezlandingpage.block.definition.contentlist}
            - {name: ezplatform.ezlandingpage.block.render.contentlist.pre}
            - {name: ezplatform.ezlandingpage.block.render.pre}
            - {name: ezplatform.ezlandingpage.block.render.post}

And my associate class:

namespace MyBundle\Block;
use EzSystems\EzPlatformPageFieldType\FieldType\Page\Block\Definition\BlockDefinitionEvents;
use EzSystems\EzPlatformPageFieldType\FieldType\Page\Block\Definition\Event\BlockAttributeDefinitionEvent;
use EzSystems\EzPlatformPageFieldType\FieldType\Page\Block\Renderer\BlockRenderEvents;
use EzSystems\EzPlatformPageFieldType\FieldType\Page\Block\Renderer\Event\PreRenderEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ContentListBlockListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        //die (__METHOD__); // OK this die die :)
        return [
            BlockDefinitionEvents::getBlockAttributeDefinitionEventName('contentList', 'contentId') => 'onContentIdAttributeDefinition',
            BlockRenderEvents::getBlockPreRenderEventName('contentList') => 'onBlockPreRender',
        ];
    }

    public function onContentIdAttributeDefinition(BlockAttributeDefinitionEvent $event)
    {
        die(__METHOD__); // This die dont die :'(
    }

    public function onBlockPreRender(PreRenderEvent $event)
    {
        die(__METHOD__); // This die dont die :'(
    }
}

But I don’t feel like my code is being executed.


#3

The doc in 2.3 is identical to the doc in 2.2.

https://doc.ezplatform.com/en/2.3/guide/extending_form_builder/


#4

Hi remy_php,

Service definition seems to be wrong:

services:
    my.block.contentlist:
        class: MyBundle\Block\ContentListBlockListener
        tags:
            - {name: ezplatform.ezlandingpage.block.definition.contentlist}
            - {name: ezplatform.ezlandingpage.block.render.contentlist.pre}
            - {name: ezplatform.ezlandingpage.block.render.pre}
            - {name: ezplatform.ezlandingpage.block.render.post}

If you don’t rely on Symfony container autowire, you should not tag the service with event names, but tell Symfony your class is an Event Subscriber. Proper service definition would look like this:

services:
    my.block.contentlist:
        class: MyBundle\Block\ContentListBlockListener
        tags:
            - kernel.event_subscriber

You can find more information about Symfony event subscribers and how to register them here, in a documentation for Symfony 3.4: https://symfony.com/doc/3.4/event_dispatcher.html

Cheers!


#5

Ok.

I therefore declare my service as an event_subscriber.
But the problem is that the native service is always called. And that he’s called after mine.
So the value I assign to the contentArray parameter is overwritten.

services:
    my.block.contentlist:
        class: MyBundle\Block\ContentListBlockListener
        arguments:
            - '@ezpublish.api.repository'
            - '@fos_http_cache.handler.tag_handler' # ==  '@ezplatform.http_cache.fos_tag_handler.xkey'
            - '$languages$'
            - '@monolog.logger'
        tags:
            - kernel.event_subscriber
class ContentListBlockListener  implements EventSubscriberInterface
{
   //...
    public static function getSubscribedEvents()
    {
        return [
            BlockRenderEvents::getBlockPreRenderEventName('contentlist') => 'onBlockPreRender',
            BlockResponseEvents::getBlockResponseEventName('contentlist') => 'onBlockResponse',
        ];
    }
   //...
}

#6

For the moment I’m getting by by declaring a new variable. (Which is therefore not overwritten)

    public function onBlockPreRender(PreRenderEvent $event)
    {
        // ....  
        $contentArray; // = Content+Location List 
        $parameters['contentArray'] = $contentArray;
        $parameters['contentArray2'] = $contentArray;
    }

And in the template I use my new variable. (With the std variable in default)

     {% if contentArray2|default(contentArray)|length > 0 %}
            {% for content in contentArray2|default(contentArray) %}
                {{ fos_httpcache_tag('relation-' ~ content.content.id) }}
                {{ render(controller("ez_content:viewAction", {"contentId": content.content.id, "viewType": "embed"})) }}
            {% endfor %}
    {% endif %}