"are_related" template operator

Author Message

Mickael Robin

Tuesday 31 March 2009 1:53:03 am

Hi,

I need to implement "if A and B are related..."

I didn't find any native operator for this purpose, but I found 2 ways to explore :

1st way : fetch the objects that are related to A, and check if the array contains B's content_object_id
=> I don't know how to inspect the array produced by the related_objects fetch with the "contains" template operator...

2nd way : make an SQL query directly on ezcontentobject_link table
=> this might be more effective, but seems to require more eZ and SQL knowledge to create a custom operator...

3rd way : ?

Does anyone have an advice on the question?

Thanks in advance,

Mickael

André R.

Tuesday 31 March 2009 2:18:43 am

2 is definitively the most effective.

What is the use case for this?
Normally you'll want to view the relations of the current object your viewing, in what cases do you need to know relation but do not need to fetch any of the objects?

Because if your already fetch the object then something like this in a template operator (php) might be most effective without having to write your own sql.

$object = eZContentObject::fetch( $namedParameters['object_id'] );// either this or passing object as parameter
$relArray = $object->relatedObjects( false, false, 0, array( 'AsObject' => false ) );
$operatorValue = false;
// loop over array and compare with second parameter for related-to-id
// and set $operatorValue to true and break the loop if you find a match

Example of simple template operator:
http://svn.ez.no/svn/extensions/eztinymce/trunk/ezoe/autoloads/eztemplateautoload.php
http://svn.ez.no/svn/extensions/eztinymce/trunk/ezoe/autoloads/ezoetemplateutils.php

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Mickael Robin

Tuesday 31 March 2009 2:32:31 am

Hi Andre,
and thanks for your quick and useful help :-)
I'm gonna try and create my first template operator !

To answer your question about the use case : I am working on http://www.spotilinks.co.uk , a social web app to manage and discover music for Spotify (that I strongly recommend to your ears !!!)

Each member (folder-like class, not user) is invited to select other members to receive their recent playlists.
=> as this selection is managed with an object_relations attribute, if need to check if a member is already related to the one he visits, so he can not select it twice.

Mickael Robin

Tuesday 31 March 2009 6:04:38 am

I think I managed creating my "arerelated" operator but I can't find how to pass the paraméters from template.

<b>1\ Installation seems OK...</b>
I added the code below in \extension\ezwebin\autoloads\eztemplateautoload.php:

$eZTemplateOperatorArray[] = array( 'script' => 'extension/ezwebin/autoloads/arerelated.php',
                                    'class' => 'arerelated',
                                    'operator_names' => array( 'arerelated' ) );

And I regenerated autoload arrays from the admin interface, after creating the following template operator.

<b>2\ Operator should work...</b>
Then I created extension\ezwebin\autoloads\arerelated.php with this code :
<?php
class arerelated
{
function arerelated()
{
}

function operatorList()
{
return array( 'arerelated' );
}

function namedParameterPerOperator()
{
return true;
}

function namedParameterList()
{
return array( 'arerelated' => array( 'object_id_from' => array( 'type' => 'integer',
'required' => true,
'default' => '' ),
'object_id_to' => array( 'type' => 'integer',
'required' => true,
'default' => '' )
) );
}

function modify( $tpl, $operatorName, $operatorParameters, &$rootNamespace, &$currentNamespace, &$operatorValue, &$namedParameters )
{
$object_id_from = $namedParameters['object_id_from'];
$object_id_to = $namedParameters['object_id_to'];

switch ( $operatorName )
{
case 'arerelated':
{
$object_from = eZContentObject::fetch( $object_id_from );
$object_to = eZContentObject::fetch( $object_id_to);
$relArray = $object_from->relatedObjects( false, false, 0, array( 'AsObject' => false ) );
$operatorValue = false;

// loop over array and compare with second parameter for related-to-id
// and set $operatorValue to true and break the loop if you find a match
foreach( $relArray as $rel )
{
if( $rel == $object_id_to )
{
$operatorValue = true;
break;
}
}

}
}
}
}

?>

</code>One question yet : am I supposed to <b>compare objects or object_ids</b> ???

<b>3\ I can't pass the parameters</b>

Now, my problem is that I can't find the template syntax to pass the NamedParameters to my new operator.

I tried :

{if arerelated(array('object_id_from', $member_node.contentobject_id, 'object_id_to', $node.contentobject_id ))}

and

{if arerelated(hash('object_id_from', $member_node.contentobject_id, 'object_id_to', $node.contentobject_id ))}

but I think I am <b>lost within arrays</b>, despite deep survey of existing documentation and code analysis :-(

Thanks in advance for your help :-)

André R.

Tuesday 31 March 2009 8:03:52 am

No, use 'var_dump' on $rel and you'll see what parameters you get.

And you do not need the $object_to line.

(hint: 'id')

Note: when you move this out of ezwebin later, you'll need to define the extension you move it into with site.ini [TemplateSettings]ExtensionAutoloadPath[]=your_extension_name.

Note 2: you should call it like {if arerelated( $member_node.contentobject_id, $node.contentobject_id )}

eZ Online Editor 5: http://projects.ez.no/ezoe || eZJSCore (Ajax): http://projects.ez.no/ezjscore || eZ Publish EE http://ez.no/eZPublish/eZ-Publish-Enterprise-Subscription
@: http://twitter.com/andrerom

Mickael Robin

Tuesday 31 March 2009 10:08:21 am

Thanks a lot André,

I could not make it with "->relatedObjects" but the "relatedContentObjectArray" function did the work.

As I had to filter on an attribute_id, I added a NamedParameter to the code below.

As a result, here's the content of my "arerelated.php" :

<?php

class arerelated
{
    function arerelated()
    {
    }

    function operatorList()
    {
        return array( 'arerelated' );
    }

    function namedParameterPerOperator()
    {
        return true;
    }

    function namedParameterList()
    {
        return array( 'arerelated' => array( 'object_id_from' => array( 'type' => 'integer',
                                                               'required' => true,
                                                               'default' => ''),
                                             'object_id_to' => array( 'type' => 'integer',
                                                                'required' => true,
                                                                'default' => '' ),
						'attribute_id' => array( 'type' => 'integer',
                                                                'required' => true,
                                                                'default' => '' )
       					 ) );
    }

    function modify( $tpl, $operatorName, $operatorParameters, &$rootNamespace, &$currentNamespace, &$operatorValue, &$namedParameters )
    {
        $object_id_from = $namedParameters['object_id_from'];
        $object_id_to = $namedParameters['object_id_to'];
        $attribute_id = $namedParameters['attribute_id'];

        
        switch ( $operatorName )
        {
            case 'arerelated':
            {
				$object_from = eZContentObject::fetch( $object_id_from );					            		
//				$relArray = $object_from->relatedObjects( false, $object_id_from, 0, false, false, false );
				$relArray = $object_from->relatedContentObjectArray( false , false, $attribute_id, false );
				$operatorValue = false;

// loop over array and compare with second parameter for related-to-id
// and set $operatorValue to true and break the loop if you find a match
            foreach ( $relArray as $rel )
				{
					$rel_id = $rel->ID;				
   					if( $rel_id == $object_id_to )
    				{
					$operatorValue = true;
    					break;
    				}
				}				

            } 
        }
    }
}

?>

And to call it from my template, I use :

{if arerelated($member_node.contentobject_id, $node.contentobject_id, '386' )}

where 386 is the attibute_id I want to filter on

I'm glad I'me done and I hope this will help others as much André helped me :-)

Powered by eZ Publish™ CMS Open Source Web Content Management. Copyright © 1999-2014 eZ Systems AS (except where otherwise noted). All rights reserved.

eZ debug

Timing: Jan 31 2025 01:35:55
Script start
Timing: Jan 31 2025 01:35:55
Module start 'layout'
Timing: Jan 31 2025 01:35:55
Module start 'content'
Timing: Jan 31 2025 01:35:55
Module end 'content'
Timing: Jan 31 2025 01:35:55
Script end

Main resources:

Total runtime0.0352 sec
Peak memory usage4,096.0000 KB
Database Queries3

Timing points:

CheckpointStart (sec)Duration (sec)Memory at start (KB)Memory used (KB)
Script start 0.00000.0051 588.1328151.2109
Module start 'layout' 0.00510.0044 739.3438220.6875
Module start 'content' 0.00960.0240 960.03131,009.9141
Module end 'content' 0.03360.0016 1,969.945345.9922
Script end 0.0352  2,015.9375 

Time accumulators:

 Accumulator Duration (sec) Duration (%) Count Average (sec)
Ini load
Load cache0.00298.1626140.0002
Check MTime0.00123.3975140.0001
Mysql Total
Database connection0.00072.014310.0007
Mysqli_queries0.00287.915030.0009
Looping result0.00000.045310.0000
Template Total0.00113.210.0011
Template load0.00092.516810.0009
Template processing0.00020.675010.0002
Override
Cache load0.00071.849910.0007
General
dbfile0.009025.450380.0011
String conversion0.00000.023040.0000
Note: percentages do not add up to 100% because some accumulators overlap

Templates used to render the page:

UsageRequested templateTemplateTemplate loadedEditOverride
1print_pagelayout.tpl<No override>extension/community/design/community/templates/print_pagelayout.tplEdit templateOverride template
 Number of times templates used: 1
 Number of unique templates used: 1

Time used to render debug report: 0.0001 secs