Message-ID: <1102418857.3228.1485852451515.JavaMail.confluence@ip-10-127-227-164> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_3227_1133433217.1485852451514" ------=_Part_3227_1133433217.1485852451514 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html How to use a custom controller to display a content item or loca= tion

How to use a custom controller to display a content item or locatio= n

=20 =20

Enhanced views for Content/Location

In some cases, displaying a Content item/Location via the built-in ViewController is not sufficient and will force you to make many su= b-requests in order to access different parameters.

Typical use cases are access to:

In those cases, you may want to use your own controller= to display the current Content item/Location instead of using the built-in=  ViewController.

Description

This feature covers 2 general use cases:

Matching custom controllers

This is possible with the following piece of configuration:

=20
ezpublish:
    system:
        my_siteaccess:
            location_view:
                full:
                    # Defining a ruleset matching a location and pointing t=
o a controller
                    my_ruleset:
                        # The following will let you use your own custom co=
ntroller for location #123
                        # (Here it will use AcmeTestBundle/Controller/Defau=
ltController::viewLocationAction(),
                        # following the Symfony controller notation convent=
ion.
                        # Method viewLocationAction() must follow the same =
prototype as in the built-in ViewController
                        controller: AcmeTestBundle:Default:viewLocation
                        match:
                            Id\Location: 123
=20

The only requirement here is that your action method has a similar signa= ture than  ViewController::viewLocation() or  = ViewController::viewContent() (depending on what you're matching of = course). However, note that all arguments are not mandatory since Symfony is cl= ever enough to know what to inject into your action method . That is wh= y you aren't forced to mimic the ViewController's sign= ature strictly. For example, if you omit $layout and = $params arguments, it will still be valid. Symfony will just a= void injecting them into your action method.

Original ViewController signatures

viewLocation() signature
=20
/**
 * Main action for viewing content through a location in the repository.
 *
 * @param int $locationId
 * @param string $viewType
 * @param boolean $layout
 * @param array $params
 *
 * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException
 * @throws \Exception
 *
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function viewLocation( $locationId, $viewType, $layout =3D false, ar=
ray $params =3D array() )
=20
viewContent() signature
=20
/**
 * Main action for viewing content.
 *
 * @param int $contentId
 * @param string $viewType
 * @param boolean $layout
 * @param array $params
 *
 * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException
 * @throws \Exception
 *
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function viewContent( $contentId, $viewType, $layout =3D false, arra=
y $params =3D array() )
=20

Note

Controller selection doesn't apply to block_view since you = can already use your own controller to display bloc= ks.

Warning on caching

Using your own controller, it is your responsibility to = define cache rules, like for every custom controller !

So don't forget to set cache rules and the appropriate&= nbsp; X-Location-Id header in the return= ed Response object.

See built-in ViewController fo= r more details on this.

Examples

Enriching built-in ViewController

This example shows how to use a custom controller to enrich the final co= nfigured view template. Your controller will here forward the request to th= e built-in ViewController with some additional param= eters.

This is usually the recommended way to use a custom controller.

Always ensure that you add new parameters to existing $params associative array, using + union operator or array_merge() .
Not doing so (e.g. only passing your custom parameters a= rray) can result in unexpected issues with content preview. Previe= wed content and other parameters are indeed passed in $params.=

ezplatform.yml
=20
ezpublish:
    system:
        ezdemo_frontend_group:
            location_view:
                full:
                    article_test:
                        # Configuring both controller and template as the c=
ontroller will forward
                        # the request to the ViewController which will rend=
er the configured template.
                        controller: AcmeTestBundle:Default:articleViewEnhan=
ced
                        template: AcmeTestBundle:full:article_test.html.twi=
g
                        match:
                            Identifier\ContentType: [article]
=20
Controller
=20
<?php
namespace Acme\TestBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use eZ\Bundle\EzPublishCoreBundle\Controller;

class DefaultController extends Controller
{
    public function articleViewEnhancedAction( $locationId, $viewType, $lay=
out =3D false, array $params =3D array() )
    {
        // Add custom parameters to existing ones.
        $params +=3D array( 'myCustomVariable' =3D> "Hey, I'm a custom m=
essage!" );
        // Forward the request to the original ViewController
        // And get the response. Eventually alter it (here we change the sm=
ax-age for cache).
        $response =3D $this->get( 'ez_content' )->viewLocation( $loca=
tionId, $viewType, $layout, $params );
        $response->setSharedMaxAge( 600 );

        return $response;
    }
}
=20
article_test.html.twig
=20
{% extends noLayout ? viewbaseLayout : "eZDemoBundle::pagelayout.ht=
ml.twig" %}

{% block content %}
    <h1>{{ ez_render_field( content, 'title' ) }}</h1>
    <h2>{{ myCustomVariable }}</h2>
    {{ ez_render_field( content, 'body' ) }}
{% endblock %}
=20

Using a custom controller to get full contr= ol

This example shows you how to configure and use your own controller to h= andle a location.

ezplatform.yml
=20
ezpublish:
    system:
        ezdemo_frontend_group:
            location_view:
                full:
                    my_ruleset:
                        controller: AcmeTestBundle:Default:viewFolder
                        match:
                            Identifier\ContentType: [folder]
                            Identifier\Section: [standard]
=20

Always ensure to have a $params argument and add new parame= ters to it, using + union operator or array_merge() .

Not doing so (e.g. only passing your custom parameters array) ca= n result in unexpected issues with content preview. Previewed cont= ent and other parameters are indeed passed in $params.

Controller
=20
<?php
namespace Acme\TestBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use eZ\Bundle\EzPublishCoreBundle\Controller;

class DefaultController extends Controller
{
    public function viewFolderAction( $locationId, $layout =3D false, $para=
ms =3D array() )
    {
        $repository =3D $this->getRepository();
        $location =3D $repository->getLocationService()->loadLocation=
( $locationId );
        // Check if content is not already passed. Can be the case when usi=
ng content preview.
        $content =3D isset( $params['content'] ) ? $params['content'] : $re=
pository->getContentService()->loadContentByContentInfo( $location-&g=
t;getContentInfo() )
        $response =3D new Response();
        $response->headers->set( 'X-Location-Id', $locationId );
        // Caching for 1h and make the cache vary on user hash
        $response->setSharedMaxAge( 3600 );
        $response->setVary( 'X-User-Hash' );
        return $this->render(
            'AcmeTestBundle::custom_controller_folder.html.twig',
            array(
                'location' =3D> $location,
                'content' =3D> $content,
                'foo' =3D> 'Hey world!!!',
                'osTypes' =3D> array( 'osx', 'linux', 'losedows' )
            ) + $params
        );
    }
}

=20
custom_controller_folder.html.twig
=20
{% extends "eZDemoBundle::pagelayout.html.twig" %}

{% block content %}
<h1>{{ ez_render_field( content, 'title' ) }}</h1>
    <h1>{{ foo }}</h1>
    <ul>
    {% for os in osTypes %}
        <li>{{ os }}</li>
    {% endfor %}
    </ul>
{% endblock %}
=20

Overriding the built-in ViewController

One other way to keep control of what is passed to the view is to use yo= ur own controller instead of the built-in ViewController.

Base ViewController being defined as a service, with a service alias, th= is can be easily achieved from your bundle's configuration:

=20
parameters:
    my.custom.view_controller.class: Acme\TestBundle\MyViewController

services:
    my.custom.view_controller:
        class: %my.custom.view_controller.class%
        arguments: [@some_dependency, @other_dependency]

    # Change the alias here and make it point to your own controller
    ez_content:
        alias: my.custom.view_controller
=20

Warning

Doing so will completely override the built-in ViewController! Use this = at your own risk!

 

 

------=_Part_3227_1133433217.1485852451514--