Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Suggestions on how to wrap my smarty vars with a function

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> General
View previous topic :: View next topic  
Author Message
scuzzy
Smarty Regular


Joined: 31 Aug 2003
Posts: 84

PostPosted: Wed May 02, 2018 8:42 pm    Post subject: Suggestions on how to wrap my smarty vars with a function Reply with quote

Hello,

I've been using smarty for quote some time now, and I'm trying to improve a concept I have with objects assigned to smarty that permit chaining till the end of the chain at which point the __tostring magic method is called.

There are two classes, MyChain and MyNull, the idea is that once you reach a method that doesn't exist, you instead get an object that can continue the chain, but will always print an empty string.

My problem is I am needing to test against this MyNull object to get a false condition. but with PHP, testing against any object is always true...

Code:
$var = new MyNull();
if( $var )...


My goal is to make templating easy for my developers and the $object->foo->bar notation is as simple as I wish to make it.

What I am trying to achieve is for every instance of the variables being used, the generated php wraps the MyNullWrapper() function around the compiled variable. I've tried to write a regex rule to match $_smarty_tpl->tpl_vars and tried to figure out how to build a parser but failed at that, and I'd really not like to upset the core of the smarty library. Hell If php had a magic __ToBoolean magic method when performing conditions that would be amazing.

composer.json
Code:
{
    "require": {
        "smarty/smarty": "^3.1"
    }
}


chain.php
Code:
<?php

require( 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php' );

$smarty = new Smarty();
$smarty->assign( 'chain', new MyChain() );
$smarty->display( 'chain.tpl' );

class MyChain
{
  function good()
  {
    return $this; // Keeps the chain alive for good
  }
  public function __toString()
  {
    return 'Good-Chain-Value';
  }
  function __call( $ignore, $ignore )
  {
    return new MyNull(); // Keeps the chain alive for bad
  }
}

class MyNull extends MyChain
{
  public function __call( $ignore, $ignore )
  {
    return $this;
  }
  public function __toString()
  {
    return '';
  }
}

function MyNullWrapper( $input )
{
 return ( $input instanceof MyNull === true ) ? null : $input;
}


chain.tpl
Code:
{$chain->good()}
{$chain->good()->good()->good()}

{if $chain->good()->good()}
    Good-Chain-IF
{/if}

{$chain->bad()}
{$chain->good()->good()->bad()}

{if $chain->good()->bad()}
    Bad-Chain-IF{* not to be shown *}
{else}
    Bad-Chain-ELSE
{/if}

{if MyNullWrapper( $chain->good()->bad() ) }
    Wrapped-Bad-Chain-IF{* not to be shown *}
{else}
    Wrapped-Bad-Chain-ELSE
{/if}


prints

Code:
Good-Chain-Value
Good-Chain-Value
Good-Chain-IF
Bad-Chain-IF <- Undesirable behavior
Wrapped-Bad-Chain-ELSE <- Desired Behavior


Is there anyway I can automate the wrapping of MyNullWrapper() so that...

Code:
<?php if ($_smarty_tpl->tpl_vars['chain']->value->good()->bad()->bad()) {?>


...can become...

Code:
<?php if (MyNullWrapper($_smarty_tpl->tpl_vars['chain']->value->good()->bad()->bad())) {?>


Thanks for reading Very Happy


Last edited by scuzzy on Wed May 02, 2018 10:04 pm; edited 2 times in total
Back to top
View user's profile Send private message Visit poster's website
bsmither
Smarty Elite


Joined: 20 Dec 2011
Posts: 322
Location: West Coast

PostPosted: Wed May 02, 2018 9:58 pm    Post subject: Reply with quote

This template code manipulation is something you want to appear in Smarty's rendered output?

If so, you may be interested in a filter. See the docs about: registerFilter()
Back to top
View user's profile Send private message
scuzzy
Smarty Regular


Joined: 31 Aug 2003
Posts: 84

PostPosted: Wed May 02, 2018 10:16 pm    Post subject: Reply with quote

Thanks for the reply bsmither, Correct, I basically want to transform the php that smarty generates to always apply this logic because our application has thousands of instances of this usage, and I'm trying to produce the leanest syntax for our developers to use.

I've played with a prefilter to try to parse the raw .tpl files before it's parsed by smarty, but it started getting messy with more complex patterns such as.

Code:
{if $chain->good() or $chain->good( $chain->bad() )}


and then dealing with loops

Code:
{foreach $chain->good() as $foo => $bar}


Trying to not match $foo and $bar here was a challenge, my parser skills are not upto the task yet.

I was successful with replacing a single modifier though

Code:
$tpl_source = str_replace('|default:','|MyNullWrapperDefault:',$tpl_source);


I had a look at files such as smarty_internal_compile_if.php to see if there was an easy way to extend/wrap these but nothing came to mind short of forking the smarty codebase and creating a "VarPrefix" and "VarSuffix" string to wrap either side of the php smarty generates.

Code:
            if (is_array($parameter['if condition']['var'])) {
                $_output = "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value)) \$_smarty_tpl->createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n";
                $_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . $parameter['if condition']['value'] . ") {?>";
            } else {
                $_output = "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "])) \$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "] = new Smarty_Variable(null{$_nocache});";
                $_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " . $parameter['if condition']['value'] . ") {?>";
            }


I do ultimately think I need to build my own parser or some how leverage the one in smarty.
Back to top
View user's profile Send private message Visit poster's website
bsmither
Smarty Elite


Joined: 20 Dec 2011
Posts: 322
Location: West Coast

PostPosted: Wed May 02, 2018 10:36 pm    Post subject: Reply with quote

If you are interested in an example, see:
https://github.com/markhughes/HTMLMinify-Smarty

Even though this is an output filter (changes the final string), it isn't simple. It demonstrates how elaborate one can get by having the hooked filter function then call whatever other functions and classes to massage the template code.
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> General All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP