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

Switch control structures
Goto page Previous  1, 2
 
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 -> Feature Requests
View previous topic :: View next topic  
Author Message
tpneumat
Smarty Rookie


Joined: 10 Dec 2009
Posts: 5

PostPosted: Fri Jan 08, 2010 6:57 pm    Post subject: Reply with quote

Would be nice to see this working in Smarty 3....
Back to top
View user's profile Send private message
BloodDragon
Smarty n00b


Joined: 25 Jan 2010
Posts: 3

PostPosted: Mon Jan 25, 2010 10:09 am    Post subject: Reply with quote

Since I also like using the switch plugin and recently updated to Smarty 3, I have rewritten the switch plugin to work for Smarty 3. Obviously I wanted to share the code here as well.

As it is not as easy as before, to simply use any string as a parameter for a smarty tag, I now have created a prefilter to make the shorthand version of the switch plugin work (e.g. {switch $value}, instead of {switch var=$value}). To make it work, one simple line in your own code is needed however (see the end of this post).

Furthermore, I added a fix to the code, so that the postfilter, previously needed to remove empty lines, is not needed anymore.

Here's the code, simply put both files in your plugins folder.

compiler.switch.php

Code:
<?php
/**
* Switch statement plugin for smarty.
*    This smarty plugin provides php switch statement functionality in smarty tags.
*    To install this plugin just drop it into your smarty sysplugins folder.
*
* @author Steven Roebert <steven@roebert.nl> (version 2 by Jeremy Pyne <jeremy.pyne@gmail.com>)
* - Updated: 24/01/2010 - Version 3
* - File: smarty/plugins/compiler.switch.php
* - Updates
*    Version 2:
*       Changed the break attribute to cause a break to be printed before the next case, instead of before this
*          case.  This way makes more sense and simplifies the code.  This change in incompatible with code in
*          from version one.  This is written to support nested switches and will work as expected.
*    Version 2.1:
*       Added {/case} tag, this is identical to {break}.
*    Version 3:
*       Rewritten for use with Smarty 3
* - Bugs/Notes:
*       If you are using the short form, you must case condition before the break option.  In long hand this is
*          not necessary.
*
* @package Smarty
* @subpackage plugins
*
* Sample usage:
* <code>
* {foreach item=$debugItem from=$debugData}
*  // Switch on $debugItem.type
*    {switch $debugItem.type}
*       {case 1}
*       {case "invalid_field"}
*          // Case checks for string and numbers.
*       {/case}
*       {case $postError}
*       {case $getError|cat:"_ajax"|lower}
*          // Case checks can also use variables and modifiers.
*          {break}
*       {default}
*          // Default case is supported.
*    {/switch}
* {/foreach}
* </code>
*
* Note in the above example that the break statements work exactly as expected.  Also the switch and default
*    tags can take the break attribute. If set they will break automatically before the next case is printed.
*
* Both blocks produce the same switch logic:
* <code>
*    {case 1 break}
*       Code 1
*    {case 2}
*       Code 2
*    {default break}
*       Code 3
* </code>
*
* <code>
*    {case 1}
*     Code 1
*       {break}
*    {case 2}
*       Code 2
*    {default}
*       Code 3
*       {break}
* </code>
*
* Finally, there is an alternate long hand style for the switch statments that you may need to use in some cases.
*
* <code>
* {switch var=$type}
*    {case value="box" break=true}
*    {case value="line"}
*       {break}
*    {default}
* {/switch}
*/

class Smarty_Compiler_Switch extends Smarty_Internal_CompileBase
{
   /**
    * Close all current open case/default tags
    *
    * @return int amount of closed tags
    */
   protected function close_open_statements()
   {
      $counter = 0;
      while (count($this->compiler->_tag_stack))
      {
         list($open_tag, $data) = end($this->compiler->_tag_stack);
         if (in_array($open_tag, array('case', 'default')))
         {
            $this->_close_tag(array('case', 'default'));
            $counter++;
         }
         else {
            break;
         }
      }
      return $counter;
   }
   
   /**
    * Check whether the previous case/default needs a break
    */
   protected function needs_break()
   {
      if (count($this->compiler->_tag_stack))
      {
         list($open_tag, $data) = end($this->compiler->_tag_stack);
         if (in_array($open_tag, array('case', 'default'))) {
            return $data;
         }
      }
      return false;
   }
   
   /**
    * Check wether the switch php code is still open and so no
    * opening <?php is needed
    */
   protected function is_switch_open()
   {
      if (count($this->compiler->_tag_stack))
      {
         list($open_tag, $data) = end($this->compiler->_tag_stack);
         if ($open_tag == 'switch' && $data === true) {
            return true;
         }
      }
      return false;
   }
   
   /**
    * Compile code for switch statement
    *
    * @param array $args array with tag attributes
    * @param $compiler the Smarty_Internal_TemplateCompilerBase class with tag stack
    */
   public function compile($args, $compiler)
   {
      $this->compiler = $compiler;
      
      $this->required_attributes = array('var');   
      $_attr = $this->_get_attributes($args);
      $this->_open_tag('switch', true);
      
      // Do not close the <?php tag yet, as empty lines after it
      // will break the php code.
      return "<?php switch ({$_attr['var']}) { ";
   }
}

class Smarty_Compiler_Switchclose extends Smarty_Compiler_Switch
{
   /**
    * Compile code for switch close statement.
    *
    * @param array $args array with tag attributes
    * @param $compiler the Smarty_Internal_TemplateCompilerBase class with tag stack
    */
   public function compile($args, $compiler)
   {
      $this->compiler = $compiler;
      
      $output = '';
      if (!$this->is_switch_open())
      {
         // Switch php is closed, so use opening php tag
         $output .= '<?php ';
      }
      
      // Close all case/default and switch statement
      $this->close_open_statements();
      $this->_close_tag('switch');
      
      $output .= '} ?>';
      return $output;
   }
}

class Smarty_Compiler_Break extends Smarty_Compiler_Switch
{
   /**
    * Compile code for break statement.
    *
    * @param array $args array with tag attributes
    * @param $compiler the Smarty_Internal_TemplateCompilerBase class with tag stack
    */
   public function compile($args, $compiler)
   {
      $this->compiler = $compiler;
      $_attr = $this->_get_attributes($args);
      
      // Close all current case/default statements, if 1 or more
      // have been closed, add a break statement
      if ($this->close_open_statements()) {
         return '<?php break; ?>';
      }
      return '';
   }
}

class Smarty_Compiler_Case extends Smarty_Compiler_Switch
{
   /**
    * Compile code for case statement.
    *
    * @param array $args array with tag attributes
    * @param $compiler the Smarty_Internal_TemplateCompilerBase class with tag stack
    */
   public function compile($args, $compiler)
   {
      $this->compiler = $compiler;
   
      $output = '';
      if (!$this->is_switch_open())
      {
         // Switch php is closed, so use opening php tag
         $output .= '<?php ';
      }
      else
      {
         // Switch php is open, do not use opening php tag,
         // instead set switch data to false (meaning: switch php is closed)
         $this->_close_tag('switch');
         $this->_open_tag('switch', false);
      }
      
      // If a break statement is needed from previous case/default statements, add it
      if ($this->needs_break())
      {
         $this->close_open_statements();
         $output .= 'break; ';
      }
   
      $this->required_attributes = array('value');
      $this->optional_attributes = array('break');
      $_attr = $this->_get_attributes($args);

      // Open case statement and
      // check whether there needs to be a break before the next case/default statement
      $break = isset($_attr['break']);
      if ($break && $_attr['break'] !== '') {
         eval('$break = '.$_attr['break'].';');
      }
      $this->_open_tag('case', $break);
      
      $output .= "case {$_attr['value']}: ?>";
      return $output;
   }
}

class Smarty_Compiler_Caseclose extends Smarty_Compiler_Break { }

class Smarty_Compiler_Default extends Smarty_Compiler_Switch
{
   public function compile($args, $compiler)
   {
      $this->compiler = $compiler;
      
      $output = '';
      if (!$this->is_switch_open())
      {
         // Switch php is closed, so use opening php tag
         $output .= '<?php ';
      }
      else
      {
         // Switch php is open, do not use opening php tag,
         // instead set switch data to false (meaning: switch php is closed)
         $this->_close_tag('switch');
         $this->_open_tag('switch', false);
      }
      
      // If a break statement is needed from previous case/default statements, add it
      if ($this->needs_break())
      {
         $this->close_open_statements();
         $output .= 'break; ';
      }
      
      $this->optional_attributes = array('break');
      $_attr = $this->_get_attributes($args);
      
      // Open default statement and
      // check whether there needs to be a break before the next case/default statement
      $break = isset($_attr['break']);
      if ($break && $_attr['break'] !== '') {
         eval('$break = '.$_attr['break'].';');
      }
      $this->_open_tag('default', $break);
      
      $output .= 'default: ?>';
      return $output;
   }
}

class Smarty_Compiler_Defaultclose extends Smarty_Compiler_Break { }
?>


prefilter.switch.php

Code:
<?php
/**
* Prefilter plugin for shorthand mode Switch plugin. (see Switch plugin for details)
*
* @author Steven Roebert <steven@roebert.nl>
* - Created: 25/01/2010 - Version 1
* - File: smarty/plugins/prefilter.switch.php
*
* @package Smarty
* @subpackage plugins
*
* Sample usage:
* <code>
* $smarty->autoload_filters['pre'][] = 'switch';
* </code>
*/
class Smarty_Prefilter_Switch
{
   public function execute($output, $smarty)
   {
      // Add var= to switch statements without it
      $output = preg_replace("/\{switch (?!(\s*)var(\s*)=)/", "{switch var=", $output);
      
      // Add value= to case statements without it
      $output = preg_replace("/\{case (?!(\s*)value(\s*)=)/", "{case value=", $output);
      
      // Return new output
      return $output;
   }
}
?>


To make the prefilter work, in order to have the shorthand version of the switch plugin, add the following line to your code (where $smarty is the instance of smarty you are using):

Code:
$smarty->autoload_filters['pre'][] = 'switch';


It should work the same as before, but let me know if anything is missing or not working.
Back to top
View user's profile Send private message
pynej
Smarty Rookie


Joined: 07 Mar 2008
Posts: 8

PostPosted: Tue Feb 09, 2010 3:47 pm    Post subject: Smarty 3 Switch Statment Reply with quote

An updated version of my switch plugin for Smarty 3 is available here.
Back to top
View user's profile Send private message
pynej
Smarty Rookie


Joined: 07 Mar 2008
Posts: 8

PostPosted: Tue Feb 09, 2010 4:56 pm    Post subject: Smarty 3 Switch Statment Reply with quote

I just updated the plug-in again to version 3.1 re-enabling support for short hand {switch $myvar} tags. This feature requires the inclusion of a load_plugin line in the user code before the template is rendered. If not preloaded the longhand form of the syntax still functions properly.

On an aside, this plugin now uses the internal tag tracking in smarty 3 so there are no messy global variables or conflicts with the tpl_vars. It also fully supports complex variables in both the switch and case statements. That is you can basibly use and expressions including functions and modifiers in the statements so long as they return a string. For example I use the following to test against PHP contents in my code.

Code:
{case "debug::LOG_PLUGIN_LOAD"|get_const break}
  <span class="debug-plugin_load">Loading Plugin: </span>{$debugItem.message}<br>
Back to top
View user's profile Send private message
asimcan
Smarty n00b


Joined: 12 Feb 2011
Posts: 3

PostPosted: Fri Mar 16, 2012 8:46 pm    Post subject: Reply with quote

Code:
[16-Mar-2012 22:40:54] PHP Fatal error:  Call to undefined method Smarty_Compiler_Switch::_get_attributes() in /home/memleket/public_html/libs/plugins/compiler.switch.php on line 147




why?
Back to top
View user's profile Send private message
mohrt
Administrator


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

PostPosted: Fri Mar 16, 2012 8:54 pm    Post subject: Reply with quote

Just a quick thought, you always clear the compiled and cache files after updating smarty, plugins, or compile-time configurations yes?
Back to top
View user's profile Send private message Visit poster's website
asimcan
Smarty n00b


Joined: 12 Feb 2011
Posts: 3

PostPosted: Fri Mar 16, 2012 8:58 pm    Post subject: Reply with quote

$smarty = new Smarty();
$smarty->debugging = true;
$smarty->template_dir = 'templates/yeni/';
$smarty->compile_dir = 'templates_c/';
$smarty->config_dir = 'configs/';
$smarty->cache_dir = 'cache/';
$smarty->caching = true;
$smarty->cache_lifetime = 120;

how is lifetime?
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Sat Mar 17, 2012 9:29 am    Post subject: Reply with quote

There have been a while ago some name changes of internal methods:

_open_tag() => openTag()
_close_tag() => closeTag()
_get_attributes() => getAttributes()

This has to be replaced in the posted compiler code.
Back to top
View user's profile Send private message
asimcan
Smarty n00b


Joined: 12 Feb 2011
Posts: 3

PostPosted: Sat Mar 17, 2012 10:46 pm    Post subject: Reply with quote

Code:
[18-Mar-2012 00:44:30] PHP Warning:  Missing argument 2 for Smarty_Internal_CompileBase::getAttributes(), called in /home/memleket/public_html/libs/plugins/compiler.switch.php on line 147 and defined in /home/memleket/public_html/libs/sysplugins/smarty_internal_compilebase.php on line 56



methods are edited.
now? Sad
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Sun Mar 18, 2012 9:36 am    Post subject: Reply with quote

After having a closer look I found out that because of other internal changes this plugin is not compatible with Smarty 3.1.

I will later look into a corresponding patch.
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Tue Jan 13, 2015 10:28 pm    Post subject: Reply with quote

See https://github.com/pynej/Smarty-Switch-Statement
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 -> Feature Requests All times are GMT
Goto page Previous  1, 2
Page 2 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