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

list all potential smarty variables found in a template
Goto page 1, 2  Next
 
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
3e
Smarty Rookie


Joined: 30 May 2007
Posts: 9

PostPosted: Thu Apr 17, 2008 5:57 am    Post subject: list all potential smarty variables found in a template Reply with quote

I would like to grab all the variables in a smarty template and use them to generate some data fields in a database.

eg
template:
Code:
{$variable  name="var1"}<br />
{$variable  name="var2"}<br />
{$variable  name="var3"}<br />


generates an sql statement like so:

Code:
INSERT INTO Variables VALUES ('var1', 'var2', 'var3');


with some kind of code like:
(pseudocode)
Code:

$vars;
$template = getTemplate(template.tpl);
foreach in (getTemplateVars($template) as $variable) {
    $vars .= "'$variable'" . ", ";
}

$sql = "INSERT INTO Variables VALUES ($vars);



for example.


Last edited by 3e on Fri Apr 18, 2008 1:55 am; edited 1 time in total
Back to top
View user's profile Send private message
shannera
Administrator


Joined: 13 Feb 2006
Posts: 802
Location: Edertal, Germany

PostPosted: Thu Apr 17, 2008 8:06 am    Post subject: Reply with quote

Maybe $smarty->get_template_vars() will help you: http://www.smarty.net/manual/en/api.get.template.vars.php
Back to top
View user's profile Send private message
3e
Smarty Rookie


Joined: 30 May 2007
Posts: 9

PostPosted: Fri Apr 18, 2008 12:01 am    Post subject: almost, but no cigar Reply with quote

That's the wrong way round though...

get_template vars gives me teh vars that can be put into the template...
I need to parse the template and return all of the possible variables within...
Back to top
View user's profile Send private message
Celeb
Administrator


Joined: 17 Apr 2007
Posts: 1025
Location: Vienna

PostPosted: Fri Apr 18, 2008 1:57 am    Post subject: Reply with quote

I suppose the easiest way to accomplish this is by parsing the compiled template (usually under a somewhat cryptic name in the template_c folder).
Something along the lines of:
Code:
$file_name = '/path/to/smarty/templates_c/file';

$fh = fopen($file_name, 'r');
$content = fread($fh, filesize($file_name));
fclose($fh);

$pattern = "/$this\->_tpl_vars\[\'(.*?)\'\]/";
$matches = array();
preg_match_all($pattern, $content, $matches);
$variables = array_unique($matches[1]);

print_r($variables);


I've found another way, it will only work under PHP5 though. And I don't think it's any less dirty than parsing the compiled template.
Firstly, I created a class that acts like an array (implements the ArrayAccess interface) and logs all "array access". Secondly, I created a class that extends the Smarty class and kind of hi-jacked the fetch() method. Note that this array class is no actual array and causes some errors, eg when array_merge is called during the fetch(), so I have to turn off error_reporting temporarily.

Code:
<?php

class TplVarsWrapper implements ArrayAccess {
  private $_data;
 
  private $_requested = array();
 
  function __construct($vars) {
    $this->_data = $vars;
  }
 
  function report() {
    return $this->_requested;
  }

  function offsetExists($offset) {
    return isset($this->_data[$offset]);
  }
 
  function offsetGet($offset) {
    if (!in_array($offset, $this->_requested))
      $this->_requested[] = $offset;
   
    return $this->_data[$offset];
  }
 
  function offsetSet($offset, $value) {
    $this->_data[$offset] = $value;
  }
 
  function offsetUnset($offset) {
    unset($this->_data[$offset]);
  }
}

class DebugSmarty extends Smarty {
 
  function getUsedTemplateVars($resource_name, $cache_id = null, $compile_id = null) {
 
    // Replace _tpl_vars by the wrapper class
    $old_tpl_vars = $this->_tpl_vars;
    $this->_tpl_vars = new TplVarsWrapper($this->_tpl_vars);

    // Turn off error reporting
    $old_error_reporting = $this->error_reporting;
    $this->error_reporting = 0;

    // Fetch the template
    parent::fetch($resource_name, $cache_id, $compile_id, false);

    // Turn error reporting back on
    $this->error_reporting = $old_error_reporting;

    // "Repair" tpl_vars
    $this->_tpl_vars = $old_tpl_vars;

    // Return array of used variables
    return $this->_tpl_vars->report();
  }

}

?>


Have fun with it Smile
_________________
Darn computers always do what I tell them to instead of what I want them to do.
Back to top
View user's profile Send private message
3e
Smarty Rookie


Joined: 30 May 2007
Posts: 9

PostPosted: Fri Apr 18, 2008 3:12 am    Post subject: Reply with quote

Thanks heaps!
I'll have a crack at that. Was hoping there'd be a function to do it.
Surely smarty forms such a list prior to replacing variables, maybe there is a way to access it?

Is there a recommended way to add new functions to the smarty object?

I saw something that looked vaguely useful here, though wasn't sure about it:

http://www.smarty.net/manual/en/plugins.outputfilters.php
http://www.smarty.net/manual/en/api.register.outputfilter.php
and
http://www.smarty.net/manual/en/advanced.features.outputfilters.php

What do you think?


Last edited by 3e on Fri Apr 18, 2008 3:21 am; edited 3 times in total
Back to top
View user's profile Send private message
3e
Smarty Rookie


Joined: 30 May 2007
Posts: 9

PostPosted: Fri Apr 18, 2008 3:13 am    Post subject: Reply with quote

I'm just looking for a more 'tight' solution that I can encapsulate into a function that appears 'part of smarty'

oh and we're currently only using php4!


Last edited by 3e on Fri Apr 18, 2008 3:40 am; edited 1 time in total
Back to top
View user's profile Send private message
3e
Smarty Rookie


Joined: 30 May 2007
Posts: 9

PostPosted: Fri Apr 18, 2008 3:13 am    Post subject: Reply with quote

now I'm just posting another time so i can post the url for two posts back. (5 post minimum)
Back to top
View user's profile Send private message
Celeb
Administrator


Joined: 17 Apr 2007
Posts: 1025
Location: Vienna

PostPosted: Fri Apr 18, 2008 11:31 am    Post subject: Reply with quote

3e wrote:
Thanks heaps!
I'll have a crack at that. Was hoping there'd be a function to do it.
Surely smarty forms such a list prior to replacing variables, maybe there is a way to access it?

No, Smarty simply fills all the variables assigned by assign() into an internal array and then accesses this array when replacing template variables.

3e wrote:
Is there a recommended way to add new functions to the smarty object?

I'd recommend extending the Smarty class is the way to go. If you avoid using private methods and variables there (those usually begin with a "_") there should be no problem when updating your Smarty installation.
Extending classes is available in PHP4 aswell.

3e wrote:
I saw something that looked vaguely useful here, though wasn't sure about it:

http://www.smarty.net/manual/en/plugins.outputfilters.php
http://www.smarty.net/manual/en/api.register.outputfilter.php
and
http://www.smarty.net/manual/en/advanced.features.outputfilters.php

What do you think?

Outputfilters are applied to the HTML generated by Smarty before being sent to the browser. I don't think they are of any use concerning your problem.
_________________
Darn computers always do what I tell them to instead of what I want them to do.


Last edited by Celeb on Tue Apr 22, 2008 11:13 pm; edited 1 time in total
Back to top
View user's profile Send private message
3e
Smarty Rookie


Joined: 30 May 2007
Posts: 9

PostPosted: Tue Apr 22, 2008 9:39 am    Post subject: Reply with quote

OK Thanks for the use of your brain.
Much appreciated.
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Tue Apr 22, 2008 4:24 pm    Post subject: Reply with quote

You might take a step back and figure out why you want to do this in the first place. Assembling a SQL query from the available variables in a template is completely backwards. The template should just be handling presentation, not dictating business logic.
Back to top
View user's profile Send private message Visit poster's website
3e
Smarty Rookie


Joined: 30 May 2007
Posts: 9

PostPosted: Thu Apr 24, 2008 1:36 am    Post subject: Reply with quote

This would seem like wisdom.

But what I'm doing is:

the cms I'm using (cms made simple) uses an API to generate form elements which are assigned to smarty vars which appear in templates...

What I'm trying to do is build an html page, parse it and generate the associated php code with api calls, smarty templates and language information to generate that page via the cms api.

thanks.
Back to top
View user's profile Send private message
shannera
Administrator


Joined: 13 Feb 2006
Posts: 802
Location: Edertal, Germany

PostPosted: Thu Apr 24, 2008 9:41 am    Post subject: Reply with quote

So you generate a template e.g. with a form, parse it to create PHP code out of it that creates a form? Sounds a little bit crazy for me, a shot in the head through the feet...
Back to top
View user's profile Send private message
vesech
Smarty Rookie


Joined: 21 Sep 2008
Posts: 10

PostPosted: Fri Nov 28, 2008 8:47 am    Post subject: Reply with quote

Celeb wrote:


I've found another way, it will only work under PHP5 though. And I don't think it's any less dirty than parsing the compiled template.
Firstly, I created a class that acts like an array (implements the ArrayAccess interface) and logs all "array access". Secondly, I created a class that extends the Smarty class and kind of hi-jacked the fetch() method. Note that this array class is no actual array and causes some errors, eg when array_merge is called during the fetch(), so I have to turn off error_reporting temporarily.

Code:
<?php

class TplVarsWrapper implements ArrayAccess {
  private $_data;
 
  private $_requested = array();
 
  function __construct($vars) {
    $this->_data = $vars;
  }
 
  function report() {
    return $this->_requested;
  }

  function offsetExists($offset) {
    return isset($this->_data[$offset]);
  }
 
  function offsetGet($offset) {
    if (!in_array($offset, $this->_requested))
      $this->_requested[] = $offset;
   
    return $this->_data[$offset];
  }
 
  function offsetSet($offset, $value) {
    $this->_data[$offset] = $value;
  }
 
  function offsetUnset($offset) {
    unset($this->_data[$offset]);
  }
}

class DebugSmarty extends Smarty {
 
  function getUsedTemplateVars($resource_name, $cache_id = null, $compile_id = null) {
 
    // Replace _tpl_vars by the wrapper class
    $old_tpl_vars = $this->_tpl_vars;
    $this->_tpl_vars = new TplVarsWrapper($this->_tpl_vars);

    // Turn off error reporting
    $old_error_reporting = $this->error_reporting;
    $this->error_reporting = 0;

    // Fetch the template
    parent::fetch($resource_name, $cache_id, $compile_id, false);

    // Turn error reporting back on
    $this->error_reporting = $old_error_reporting;

    // "Repair" tpl_vars
    $this->_tpl_vars = $old_tpl_vars;

    // Return array of used variables
    return $this->_tpl_vars->report();
  }

}

?>



Cheers for this Celeb. It made it possible for me to display a list of templates which must be used by users when setting a template (linked to a previous question here: [see next edit since I'm not allowed to post a link until I have 3 posts!]

I did notice an issue with the class you've given though, in that you return the original $this->_tpl_vars variable instead of the instantiated wrapper and throw it away too early. I've made changes as follows:

Code:


   class DebugSmarty extends Smarty {

     function getUsedTemplateVars($resource_name, $cache_id = null, $compile_id = null) {

       // Replace _tpl_vars by the wrapper class
       $old_tpl_vars = $this->_tpl_vars;
       $this->_tpl_vars = new TplVarsWrapper($this->_tpl_vars);

       // Turn off error reporting
       $old_error_reporting = $this->error_reporting;
       $this->error_reporting = 0;

       // Fetch the template
       parent::fetch($resource_name, $cache_id, $compile_id, false);

       // Turn error reporting back on
       $this->error_reporting = $old_error_reporting;

       // Take a note of the wrapper vars
       $tpl_vars_wrapper = $this->_tpl_vars;

       // "Repair" tpl_vars
       $this->_tpl_vars = $old_tpl_vars;

       // Return array of used variables
       return $tpl_vars_wrapper->report();
     }

   }


Cheers again, works like a charm.

Ves.
Back to top
View user's profile Send private message
vesech
Smarty Rookie


Joined: 21 Sep 2008
Posts: 10

PostPosted: Fri Nov 28, 2008 8:48 am    Post subject: Reply with quote

As per last post: http://www.phpinsider.com/smarty-forum/viewtopic.php?p=53156
Back to top
View user's profile Send private message
vesech
Smarty Rookie


Joined: 21 Sep 2008
Posts: 10

PostPosted: Fri Nov 28, 2008 3:42 pm    Post subject: Reply with quote

Gah. So close. Smarty's intelligence getting the better of this:

Code:

{if $var1 gt 3}
{if $var2}
Var2 won't display in the list of available templates!
{/if}
{/if}

print_r($debugSmarty->getUsedTemplateVars());

Array (
[0] => [var1]
)


... :/

Obviously since smarty isn't going in that far (with good reason) in order for the ArrayAccess to ultimately make note of it.

Anyone see any obvious workaround to make ALL the potential template variables display? Neutral
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
Goto page 1, 2  Next
Page 1 of 2

 
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