Mugo Web main content.

Reading object states in eZ Publish 5

By: Thiago Campos Viana | October 30, 2014 | eZ Publish development tips, ez publish 5, and twig

Object states are used in many ways in eZ Publish, from workflows to menu management to controlling SEO tags. In eZ Publish 5, object state information is not available by default as one of the intrinsic attributes of a content or location object. In this post, we will show you how to access object states in PHP (usually in your custom controllers) or in Twig templates.

In eZ Publish 5, there is a separation of business logic in PHP and display logic in Twig templates. When it comes to object states, it is not a cut and dry argument about where object states should be made available.
    
We'll start with PHP code. Presuming that you already have access to the eZ Publish API repository in a controller, you can use the object state service to access the relevant data:

// loads the object state service object
$stateService = $repository->getObjectStateService();
 
// fetches an object state group by id
$group = $stateService->loadObjectStateGroup( 2 );
 
// Loads the object state for a certain state group
$objStates = $stateService->getContentState( $object->versionInfo->contentInfo, $group );

You can then inject this data (or some other data based on it) into a Twig template. However, if you don't want to have to do this for every controller, you can make object states available in Twig so that your templates can access object states when and where necessary. To make this information available in Twig, you must create a Twig extension. This is straightforward, and you can see the "How to Write a custom Twig Extension" tutorial for more information.

You can either create a separate bundle for this functionality or use it in an existing bundle.

The end goal is that you can access object states in Twig like this:

Load all object states:
 
{% set states = get_object_state( content ) %}
 
By group id:
 
{% set state = get_object_state( content, 2 ) %}
 
By group identifier:
{% set state = get_object_state( content, 'ez_lock' ) %}

The main PHP class should look like this:

<?php
 
namespace Mugo\ObjectStatesBundle\Twig;
 
class MugoExtension extends \Twig_Extension
{
    protected $container;
 
    public function setContainer($container){
        $this->container = $container;
    }
 
    public function getFunctions() {
        return array(
            'get_object_state' => new \Twig_Function_Method( $this, 'getObjectState' )
        );
    }
 
    /** 
     * Returns object state(s) for a given content object 
     * 
     * @param object $contentObject The content object 
     * @param string $state The object state identifier or ID; if omitted, all states are returned 
     * @return array containing "menu" as the menu HTML (false if no linked feature structure is found) and "html" as everything else 
     */ 
    public function getObjectState( $object, $state = '*' ) 
    { 
        // Check that we have a content object 
        if( !( $object instanceof \eZ\Publish\Core\Repository\Values\Content\Content ) ) 
        { 
            return null; 
        } 
 
        $repository = $this->container->get( 'ezpublish.api.repository' ); 
        $stateService = $repository->getObjectStateService(); 
 
        if( $state == '*' ) 
        { 
            $stateArray = array(); 
            $stateGroups = $stateService->loadObjectStateGroups(); 
            foreach( $stateGroups as $group ) 
            { 
                $group = $stateService->loadObjectStateGroup( 
                    $group->id 
                ); 
                $stateArray[] = $stateService->getContentState( $object->versionInfo->contentInfo, $group ); 
            } 
 
            return $stateArray; 
        } 
        else if ( gettype( $state ) == 'integer' ) 
        { 
            try 
            { 
                $group = $stateService->loadObjectStateGroup( $state ); 
                return $stateService->getContentState( $object->versionInfo->contentInfo, $group ); 
            } 
            // Object state with that ID doesn't exist 
            catch( \eZ\Publish\Core\Base\Exceptions\NotFoundException $e ) 
            { 
                return null; 
            } 
        } 
        else 
        { 
            $stateGroups = $stateService->loadObjectStateGroups(); 
            foreach( $stateGroups as $group ) 
            { 
                if( $group->identifier == $state ) 
                { 
                    $group = $stateService->loadObjectStateGroup( $group->id ); 
                    return $stateService->getContentState( $object->versionInfo->contentInfo, $group ); 
                } 
            } 
 
            return null; 
        } 
    }
 
    public function getName()
    {
        return 'mugo_extension';
    }
}
 
?>

To make this functionality available, you just have to add the following to services.yml:

services:
    mugo.twig.mugo_extension:
        class: Mugo\ObjectStatesBundle\Twig\MugoExtension
        calls:
            - [setContainer, [@service_container] ]
        tags:
            - { name: twig.extension }