Dynamic substitution of a template operator in eZ Publish
Today I had the problem of many people (believing forum posts left unanswered for years) :
How can I replace the code that runs behind a template operator, to avoid override all my templates?
How can I trigger this operator substitution directly from another operator, live in the template? (like an on / off switch...)
How to have absolute URLs in all templates calling "ezurl" without modifying the template code?!?
I finally have the answer! A technical solution that does not change anything in the kernel, which can be done in a small independent extension and which does not break ANYTHING until you have decided to activate the operator substitution! It's clean, it's fast, a little "on" at the beginning of the template, a little "off" at the end to clean, and all templates that will be called between them will use your own operator code!
The principle is simple (at first): simply declare (registerOperators) an operator that has the same name as the one that wants to replace ... Easy ... but as a simple solution does not always work (depending on the order in which extensions are loaded, and therefore WHO has the last word on the declaration of the operator ...), it's about making a register live in the template (switch to "on": to force dynamic declaration). It is also possible to reverse the process to return to the native operator. This gives the following code:
BEFORE : {'/user/login'|ezurl()} {* relative url... *}
WITH SUBSTITUTION :
{sethacks()}... {* switch on substitution *}
{'/user/login'|ezurl()} {* absolute url, or custom result *}
{unsethacks()}... {* switch off substitution *}
AFTER : {'/user/login'|ezurl()} {* relative url again... *}Just between sethacks() and unsethacks(), I call any full view of my content, and the template operator (ezurl in my example) is the one I have recoded in my extension!
Well now, how this works?
Suppose you can do an extension with template operators (if you cannot, lean on known examples, as ezwebin ...).
In your eztemplateautoload.php file, you will get this :
$eZTemplateOperatorArray = array(); $eZTemplateOperatorArray[] = array( 'script' => 'extension/my_extension/autoloads/hackedoperators.php', 'class' => 'HackedOperators', 'operator_names' => array( 'sethacks' // NOTHING MORE HERE !!! ) );
You'll notice here, I do declare only a single operator, which allows the switch to initiate the process...
in your template operators file (hackedoperators.php for example), you will get this :
class HackedOperators {
function HackedOperators() {
$this->Operators = array(
'sethacks', 'unsethacks',
'ezurl' // HERE, FULL DECLARATION !
);
$this->NamedOperators = array(
'sethacks'=> array( ),
'unsethacks'=> array( ),
'ezurl'=> array(
'quote' => array( 'type'=>'string',
'required'=>false,'default'=>"double"),
'type' => array( 'type'=>'string',
'required'=>false,'default'=>"full"),
)
);
}
function modify($tpl, $operatorName, $operatorParameters,
$rootNamespace, $currentNamespace, &$operatorValue,
$namedParameters) {
switch ( $operatorName ) {
case 'sethacks':
$tpl->registerOperators($this); // force set for all ops
break;
case 'unsethacks':
$tpl->registerOperators(new eZURLOperator()); // reset ops
// complete here with all reset instructions
break;
case 'ezurl':
$this->ezurl($operatorValue, $namedParameters);
break;
default :
$tpl->warning( $operatorName, "Unknown operator" );
break;
}
}
function ezurl(&$value, $namedParameters) {
// HERE, PUT YOUR NEW EZURL CODE.
}
function operatorList() {
return $this->Operators;
}
function namedParameterPerOperator() {
return true;
}
function namedParameterList() {
return $this->NamedOperators;
}
}That's it!
Enjoy.

Comments
well
Friday 23 April 2010 11:07:32 am
anny