Tuesday, February 9, 2010

Switch Statment for Smarty 3

Here is the updated {switch} statement for Smarty 3. The new version is NOT backwards compatible but the Smarty 2 version is still maintained here.

11/23/2010 - Updated to version 3.5
Updated to work with Smarty 3.0 release. (Tested on 3.0.5).
I removed the code from this posting, it is now available on github here: https://github.com/pynej/Smarty-Switch-Statement/archives/Smarty-3.0

10/28/2010 - Updated to version 3.3
I have added this project to GitHub at http://github.com/pynej/Smarty-Switch-Statement.

02/25/2010 - Updated to version 3.3
Please note that this update is required for version 3.0b6 or grater. The change is simple renaming the execute methods to compile but it not backwards compatible. The Smarty3.0b5 and below version is still available here.

02/09/2010 - Updated to version 3.2
Fixed a bug when chaining case statements without a break.

02/09/2010 - Updated to version 3.1
Updated the plug-in to once again support the shorthand format, {switch $myvar}. To enable this feature you must add the following line to you code somewhere before the template is executed.
$smarty->loadPlugin('smarty_compiler_switch');
If you do not add said line the long hand form will still work correctly.

sample.php
/**
* 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 statements that you may need to use in some cases.
*
* <code>
* {switch var=$type}
*    {case value="box" break=true}
*    {case value="line"}
*       {break}
*    {default}
* {/switch}
* </code>
*/

35 comments:

Jeremy said...

thanks man!

Jeremy Pyne said...

YAh, sorry it took a bit to get out. There is a a lack of documentation on the new plug-in system in smarty 3.

Jeremy said...

I am new to Smarty and this is the first plugin I am trying to use. When I try to call this plugin, using Smarty v.3.0b7, I get the following error.


Fatal error: Uncaught exception 'Exception' with message 'Plugin "switch" not callable' in /Users/mp2/Sites/EHR Scope LLC/v4/_core/includes/third-party/Smarty-3.0b7/libs/sysplugins/smarty_internal_templatecompilerbase.php:186 Stack trace: #0 /Users/mp2/Sites/EHR Scope LLC/v4/_core/includes/third-party/Smarty-3.0b7/libs/sysplugins/smarty_internal_templateparser.php(2142): Smarty_Internal_TemplateCompilerBase->compileTag('switch', Array) #1 /Users/mp2/Sites/EHR Scope LLC/v4/_core/includes/third-party/Smarty-3.0b7/libs/sysplugins/smarty_internal_templateparser.php(2530): Smarty_Internal_Templateparser->yy_r41() #2 /Users/mp2/Sites/EHR Scope LLC/v4/_core/includes/third-party/Smarty-3.0b7/libs/sysplugins/smarty_internal_templateparser.php(2630): Smarty_Internal_Templateparser->yy_reduce(41) #3 /Users/mp2/Sites/EHR Scope LLC/v4/_core/includes/third-party/Smarty-3.0b7/libs/sysplugins/smarty_internal_smartytemplatecompiler.php(46): Smarty_Internal_Templateparser->doParse(4, '???') #4 /Users/mp2/Sites/EHR Scope LLC/v4/_core/includ in /Users/mp2/Sites/EHR Scope LLC/v4/_core/includes/third-party/Smarty-3.0b7/libs/sysplugins/smarty_internal_templatecompilerbase.php on line 186

Do you have any idea as to what this could be? I am not sure that it has to do with this plugin but maybe the plugin system itself? Just thought I'd ask since you seem to know Smarty.

Thanks,
Jeremy

Jeremy Pyne said...

It looks like the plug-in isn't getting loaded. When you download the plugin you should be saving it into the smarty/libs/plugins/ folder.

You can try manual loading it as described in the "Updated to version 3.1" section but this may not fix the problem if there is a configuration issue.

Another option is you can just a print("Loading compiler.switch.php"); line at the top of the plug in file to see if it is loading. If you add a print statement to plug-in before the class definitions it should print out as raw text when a page using the plug-in is loaded.

Jeremy said...

Thanks for your fast response.

By putting the print() into the plugin file, I was able to see the line print out before the fatal error.

I do have the file located in the proper plugin folder, I checked this a few times. lol

Hmm, I'm still receiving this error. I even tried a simple test with:
$Template = new Smarty();
$Template->assign('testSwitch', '10');
$Template->display("testSwitch.tpl");

The error just won't go away. I guess I'll take this to the proper location for help. Don't want to clutter your post with irrelevant content, it seems this may be a bug with Smarty itself.

Jeremy Pyne said...

Its something to do with a change in Beta 6 or 7. I wrote it with Beta 5 but I just updated my code to b7 and get the same error. You can try using the earlier beta for now until I can figure out the problem, as it might be a few days before I can get to it.

SoN9ne said...

Thank you!

I have downgraded to Smarty v.3.0b5 and it is working properly! I tested in beta 6 and it has the same issue as 7. Still wondering if this is a Smarty issue asided from an issue with the plugin.

Thanks for your help. I will say I do fins it entertaining that only Jeremy's have replied to this topic thus far. lol

Jeremy Pyne said...

Ok, while I have a fix for you that works in b7. You just need to replace all the instances of "public function execute($args, $compiler){" with "public function compile($args, $compiler){" in the plug-in. The file above should be updated shortly.

SoN9ne said...

Sweet! Thanks for the fast fix. It works perfectly now. Is this part off the new plugin system for 3? Could you explain as to why that had to be changed? Just wondering since I am sure I will eventually be writing many plugins myself.

Thanks again.
Jeremy

SoN9ne said...
This comment has been removed by the author.
SoN9ne said...

This is a fix for the latest beta (3.0b8).

Replace:
$this->register_prefilter('smarty_prefilter_switch');
$this->register_postfilter('smarty_postfilter_switch');


With:
$this->register->prefilter('smarty_prefilter_switch');
$this->register->postFilter('smarty_postfilter_switch');

tatayoyo said...

Hello,
I'm using the latest switch version and i have this message:
"Parse error: syntax error, unexpected T_INLINE_HTML, expecting T_CASE or T_DEFAULT or '}'"
Nevertheless, my code is very simple.

Code:
{switch var=$element}
{case value='test' break}
test
{default}
test2
{/switch}

Do you have any idea?

Jeremy Pyne said...

This error is because the pre-filter is not getting executed. These lines are responsible for loading the filters:


$this->register_prefilter('smarty_prefilter_switch');
$this->register_postfilter('smarty_postfilter_switch');

If they are missing or not functioning the error will appear. Specifically PHP won't allow the closing of a code section () in between a switch statement and its first case. The filter jsut removes the extra empty space.

There was a change in Smarty 3.0b8 as noted in the previous comment that breaks the filter loading so try replacing the above lines with the fixed ones below. (though I havn't personally tested them.


$this->register->prefilter('smarty_prefilter_switch');
$this->register->postFilter('smarty_postfilter_switch');

Jeremy Simkins said...
This comment has been removed by the author.
Jeremy Simkins said...
This comment has been removed by the author.
Jeremy Simkins said...

I have noticed that I am getting a lot of undefined vars and undefined indexes when using the switch. I was able to fix these issues and I am giving the fixes to you so that you can use them or find a better solution.

Perhaps I am more picky than most but I do not like anything in my error log.

The lines that were causing issues for me were: 144, 151, 179.

Line 144:
Original:
$this->_open_tag('case',array($args['break'],$compiler->tag_nocache));

Fixed:
$this->_open_tag('case',array(((isset($args['break']) ? $args['break'] : NULL)),$compiler->tag_nocache));


Line 151:
Original:
return $_output . '< ?php case ' . $args['value'] . ':? >';

Fixed:
return (isset($_output) ? $_output : '') . '< ?php case ' . $args['value'] . ':? >';


Line 179:
Original:
$this->_open_tag('case',array($args['break'],$compiler->tag_nocache));

Fixed:
$this->_open_tag('case',array(((isset($args['break']) ? $args['break'] : NULL)),$compiler->tag_nocache));


With these edits, I no longer get the undefined vars nor indexes. Hope you find this useful.

I had to separate the < ?php and ? > so this would post...

Jeremy Pyne said...

Ah, I must have warnings turned off. I'll check them out.

jdill said...

Seems that a lot of Jeremy's like switch statements.

Having problems with 3.0rc4.

exception 'SmartyCompilerException' with message 'Syntax Error in template "[my tpl]" on line 5 "{break}" cannot break 1 level(s)' in Smarty/sysplugins/smarty_internal_templatecompilerbase.php:404

Thanks!

Jeremy D

Timmah-T said...

Hey Jeremy, this is Tim Sabat from Wufoo. We use this plugin and love it. Do you mind if we host it on github? That way the issues may be more easily tracked.

Jeremy Pyne said...

Ok I added the plugin as a project on github. http://github.com/pynej/Smarty-Switch-Statement

Jeremy Pyne said...

I just tested the plugin again and it is working with smarty-3.0rc4. If you are still having problems keep in mind that you may need to manually load the plugin with the following line after you load smarty itself.

//Load smarty.
require("libs/Smarty.class.php");
//Create smarty.
$this->smartyObj = new Smarty();
//Other smarty setup such as cache_dir.
//Load extra plugins.
$this->smartyObj->loadPlugin('smarty_compiler_switch');

MackieChan said...

FYI, they seem to have changed plugins a bit in the newest (3.0.5) version. Can't get the plugin to work at all. I've tried various fixes, but no matter what it won't even compile.

To help you a little, I tried changing some $args (as in $args['var']) to $args[0] (as in $args[0]['var']) which seems to help, but break still won't work.

Shame cause it seems like it would be a great plugin.

Jeremy Pyne said...

I have updated the code to work with the newest smarty version out(3.0.5). (It required some changes in attribute handling and how filters were loaded. Also I was able to remove the prefilter, but the postfilter is still required and as a result so too is the manual loadPlugin() call to make it work right.

If your getting an error about "syntax error, unexpected T_INLINE_HTML, expecting T_CASE or T_DEFAULT or '}'" its because the plugin is getting loaded on demand and isn't pre-loaded.

If you are still having problems left me know.

Jeremy Simkins said...

I seem to be getting numerous php errors in the error log. When deleting the tmp folder that smarty generates to regenerate the template cache my error log fills with multiple undefined indexes.

It seems to be the same two lines that are causing the issue. I'm posting this for now but I may have a fix in a few minutes.

[13-Dec-2010 16:10:23]
File: /Users/mp2/Zend/workspaces/DefaultWorkspace7/Version-4/_framework/core/includes/third-party/Smarty/smarty_special_plugins/compiler.switch.php
Line: 156
Message: [8] Undefined index: break

[13-Dec-2010 16:10:23]
File: /Users/mp2/Zend/workspaces/DefaultWorkspace7/Version-4/_framework/core/includes/third-party/Smarty/smarty_special_plugins/compiler.switch.php
Line: 163
Message: [8] Undefined variable: _output

Jeremy Simkins said...
This comment has been removed by the author.
Jeremy Simkins said...

I was able to fix the _output error with a simple ternary conditional.

return (isset($_output) ? $_output : '') . '< ? php case ' . $attr['value'] . ':? >'; (added spaces to allow code to post)

I am skeptical to solve the break issue as I will need to step deeper into the code and I simply do not have the time currently.

I will see if you have a fix soon or I will try to post a fix at a later date.

Jeremy Simkins said...

Okay, it seems I was able to resolve this issue.

The lines that caused the issue were lines: 156, 163, 193, and 195. The fixes were similar as they were the same bugs.

On lines 156 and 193, replace $attr['break'] with (isset($attr['break']) ? $attr['break'] : NULL)

On lines 163 and 195, replace $_output with (isset($_output) ? $_output : '')

Doing these fixes prevents any errors from showing in the error log.

Hope this was useful.

itsjamie4u said...

Thanks J.Simkins,

your 4 changes work perfectly on the Nov 23rd 2010 v3.5 of this plugin...

thanks for the help.
-Jam



---changes---
On lines 156 and 193, replace $attr['break'] with (isset($attr['break']) ? $attr['break'] : NULL)

On lines 163 and 195, replace $_output with (isset($_output) ? $_output : '')

Jeremy Pyne said...

I guess I didn't have warning turned on. Fixed the warnings on in the code and updated github.

habermedya said...

please help me.

[12-Feb-2011 17:58:18] PHP Fatal error: Call to a member function prefilter() on a non-object in /home/mysite/public_html/libs/plugins/compiler.switch.php on line 94

lauren said...

I am a newbie to Smarty my question is that i have been started using Smarty2 can i upgrade easily to newer version.If yes then how this can be done or Can you give some good links that explain about that topic
digital id

Jeremy said...

I have fixed this script for Smarty 3.1.2.

I will post the fixes for the script later tonight. I just wanted to give a heads up.

Jeremy Dill said...

Hey Jeremy, I actually had to delete my 'sysplugins/smarty_internal_compile_break.php' in Smarty 3.1.2 to get this new version working. I am using your Version 3.6. Just an FYI. I think smarty is working ok without it.

Jeremy Dill said...

Correction - Smarty 3.1.12

Jonathan Elkins said...

Nice plug in. I'd like to give you a tip.