Ray Yates
: mivascript at, pcinet d0t com
06/28/201209:41 a.m.
The following is true as of Miva Script 5.16 -- Templates are compiled compatible with Empresa 5.05 This means for compatibility, they maintain a bug in the earlier version of the virtual machine.
Problem:
The act of testing a value in null structure or array causes the array to no longer be null.
Example: mvt:if expr="( l.settings:breadcrumbs[1]:code EQ l.settings:product:code )"
Implications:
If you use a foreach loop on what you expected to be an empty array the code inside the loop will execute. If you test the value first (e.g. ISNULL l.settings:breadcrumbs ) the test will return true and again the code will execute.
If you run the script below you will get.
Result:
g.test NULL
g.test is not NULL
<mvt:if expr = "g.test">
g.test is not NULL
<mvt:else>
g.test NULL
</mvt:if><br><mvt:if expr = "( g.test[1]:code EQ l.settings:anyvalue )"></mvt:if><mvt:if expr = "g.test">
g.test is not NULL
<mvt:else>
g.test NULL
</mvt:if><br>
Scott
: cyberfunkr at, yahoo d0t com
05/29/201213:48 p.m.
Here is a self contained example of how miva_template_compile() works. There are many comments throughout the code so is should be easy to follow along. You can also compile the script with the -D DEBUG parameter to see when everything is called and what is passed around.
Key points are:
-The first few lines are variable assignments that should be changed to match your system.
-The code/html/template is compiled each run though in the example. I didn't make an auxiliary file to display just the compiled templates.
-You must set a global variable of "g.Module_Feature_TUI_MGR" to the file that contains two required function: TemplateManager_Component_Render_Start() and TemplateManager_Component_Render_End().
-A lot of the parameters that are required for these functions are very Miva Merchant-centric and should have a null variable passed around (no hard coded strings) or use them for your own data needs.
-To output your file, call the Template_Render() function.
[admin note -- See this forum post for a zip file]
http://extranet.mivamerchant.com/forums/showthread.php?109160-Good-source-on-how-miva_template_compile%28%29-works
<MIVA STANDARDOUTPUTLEVEL = ""><MvCOMMENT>
|
| These variables will likely need to be changed to match your filesystem setup
|
</MvCOMMENT><MvASSIGN NAME = "g.default"MEMBER = "signature"VALUE = "{'test_scott'}"><MvCOMMENT> Any random string of characters. Not sure how to reference later.</MvCOMMENT><MvASSIGN NAME = "g.default"MEMBER = "path"VALUE = "{'templates/'}"><MvCOMMENT> Where to store the compiled templates. </MvCOMMENT><MvASSIGN NAME = "g.Module_Feature_TUI_MGR"VALUE = "{'/test/mivascript/test_template.mvc'}"><MvCOMMENT> Required variable as it is hard coded into the template system.
Set it to file with the TemplateManager_Component_Render_Start()
and TemplateManager_Component_Render_End() functions.
Should be set to the location of this file to work.</MvCOMMENT><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><MvASSIGN NAME = "g.Developer"VALUE = "{'Scott McCollough'}"><!DOCTYPE><html xmlns = "http://www.w3.org/1999/xhtml"><head><meta http-equiv = "Content-Type"content = "text/html; charset=iso-8859-1"><title>Template Render Tutorial</title><style type = "text/css">
li.title { color:green; font-weight: bold; }
</style></head><body><MvCOMMENT>
| Set filename for the page to be created
</MvCOMMENT><MvASSIGN NAME = "l.filename"VALUE = "{'hello'}"><MvCOMMENT>
| Compile the item
</MvCOMMENT><MvASSIGN NAME = "l.item"VALUE = "{ Create_Item_Navigation( l.filename )}"><MvCOMMENT>
| Compile the page that will call the item
</MvCOMMENT><MvASSIGN NAME = "l.page"VALUE = "{ Create_Page_Test( l.filename )}"><MvCOMMENT>
| Show the output
</MvCOMMENT><MvEVAL EXPR = "{ Render( l.filename )}"></body></html><MvEXIT><MvCOMMENT>
|
| Compiling functions
|
</MvCOMMENT><MvFUNCTION NAME = "Create_Page_Test"PARAMETERS = "filename"STANDARDOUTPUTLEVEL = ""><MvCOMMENT>
| An array with the name of all the possible items
</MvCOMMENT><MvASSIGN NAME = "l.sourceitems"INDEX = "1"VALUE = "{'nav-item'}"><MvASSIGN NAME = "l.sourceitems"INDEX = "2"VALUE = "{'font-style'}"><MvCOMMENT>
| Page Template Source
</MvCOMMENT><MvCAPTURE VARIABLE = "l.source"><MIVA STANDARDOUTPUTLEVEL = "text, html"><mvt:comment>
This is just straight HTML code
</mvt:comment><p>Hello world.</p><mvt:comment>
This is an entity encoded variable with the value set in the Render() function
</mvt:comment><p>This is a &mvte:test:variable;.</p><mvt:comment>
This is an attribute encoded variable with the value set in the Render() function
</mvt:comment>
This is &mvta:test:hex;.</p><mvt:comment>
This is an item. It is passed to TemplateManager_Component_Render_Start() and TemplateManager_Component_Render_End().
Each of those functions pass the item name to a matching ComponentModule_Render_* function where it is MvIF'd for what to do.
The value/array is set in the Render() function.
</mvt:comment><mvt:item name = "{'nav-item'}"><mvt:comment>
This is an item. It is passed to TemplateManager_Component_Render_Start() and TemplateManager_Component_Render_End().
The open tag calls TemplateManager_Component_Render_Start() and the close tag calls TemplateManager_Component_Render_End(). This is useful for wrapping text with other tags.
Each of those functions pass the item name to a matching ComponentModule_Render_* function where it is MvIF'd for what to do.
This also includes a param to further qualify how the item will process.
The value is globally set in the first few lines.
</mvt:comment><p>g.Module_Feature_TUI_MGR = <mvt:item name = "font-style"param = "bold">&mvte:global:Module_Feature_TUI_MGR;</mvt:item></p><MIVA STANDARDOUTPUTLEVEL = ""></MvCAPTURE><MvIFDEF NAME = "DEBUG"><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><p><strong>Pre Compile:</strong><br>l.signature =<MvEVAL EXPR = "{ encodeentities( g.default:signature )}"><br>l.filename =<MvEVAL EXPR = "{ encodeentities( l.filename )}"><br>l.source =<MvEVAL EXPR = "{ encodeentities( l.source )}"><br>l.sourceitems =<MvEVAL EXPR = "{ encodeentities( miva_array_serialize( l.sourceitems ))}"></p><MIVA STANDARDOUTPUTLEVEL = ""></MvIFDEF><MvIF EXPR = "{ NOT miva_template_compile( g.default:signature, l.source, l.sourceitems, g.default:path $ l.filename $'.mvc', l.errors )}"><MvEVAL EXPR = "{'<br />Compile Error: '$ l.errors }"></MvIF><MvIFDEF NAME = "DUMP"><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><p><strong>Dump:</strong><MvASSIGN NAME = "l.dump"VALUE = "{ miva_template_compile_dump( l.source, l.errors )}"><br>l.source =<MvEVAL EXPR = "{ encodeentities( l.source )}"><br>l.errors =<MvEVAL EXPR = "{ encodeentities( l.errors )}"></p><MIVA STANDARDOUTPUTLEVEL = ""></MvIFDEF></MvFUNCTION><MvFUNCTION NAME = "Create_Item_Navigation"PARAMETERS = "filename"STANDARDOUTPUTLEVEL = ""><MvCOMMENT>
| Item Template Source
</MvCOMMENT><MvCAPTURE VARIABLE = "l.source"><MIVA STANDARDOUTPUTLEVEL = "text, html"><ul><mvt:foreach iterator = "line"array = "array"><mvt:if expr = "l.settings:line:type EQ 'title'"><li class = "title">&mvte:line:name;</li><mvt:else><li>&mvte:line:name;</li></mvt:if></mvt:foreach></ul><MIVA STANDARDOUTPUTLEVEL = ""></MvCAPTURE><MvIFDEF NAME = "DEBUG"><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><p><strong>Pre Compile:</strong><br>l.signature =<MvEVAL EXPR = "{ encodeentities( g.default:signature )}"><br>l.filename =<MvEVAL EXPR = "{ encodeentities( l.filename )}"><br>l.source =<MvEVAL EXPR = "{ encodeentities( l.source )}"><br>l.sourceitems =<MvEVAL EXPR = "{ encodeentities( miva_array_serialize( l.sourceitems ))}"></p><MIVA STANDARDOUTPUTLEVEL = ""></MvIFDEF><MvIF EXPR = "{ NOT miva_template_compile( g.default:signature, l.source, l.sourceitems, g.default:path $'nav-item'$ '.mvc', l.errors )}"><MvEVAL EXPR = "{'<br />Compile Error: '$ l.errors }"></MvIF><MvIFDEF NAME = "DUMP"><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><p><strong>Dump:</strong><MvASSIGN NAME = "l.dump"VALUE = "{ miva_template_compile_dump( l.source, l.errors )}"><br>l.source =<MvEVAL EXPR = "{ encodeentities( l.source )}"><br>l.errors =<MvEVAL EXPR = "{ encodeentities( l.errors )}"></p><MIVA STANDARDOUTPUTLEVEL = ""></MvIFDEF></MvFUNCTION><MvCOMMENT>
|
| Rendering functions
|
</MvCOMMENT><MvFUNCTION NAME = "Render"PARAMETERS = "filename"STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><MvCOMMENT>
| This is where we load up all the values for variables/items used in the page to be rendered
</MvCOMMENT><MvASSIGN NAME = "l.settings:test:variable"VALUE = "{'&variable'}"><MvASSIGN NAME = "l.settings:test:hex"VALUE = "{'/hexed/'}"><MvASSIGN NAME = "l.array_count"VALUE = "{ Load_Navigation( l.settings:array )}"><MvCOMMENT>
| This is where we output the actual page
</MvCOMMENT><p><strong>Render:</strong><hr><MvEVAL EXPR = "{[ g.default:path $ l.filename $'.mvc'].Template_Render( l.page, l.settings )}"><hr><p></MvFUNCTION><MvFUNCTION NAME = "Load_Navigation"PARAMETERS = "array var"STANDARDOUTPUTLEVEL = ""><MvASSIGN NAME = "l.count"VALUE = ""><MvASSIGN NAME = "l.count"VALUE = "{ l.count + 1 }"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "name"VALUE = "Links"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "type"VALUE = "title"><MvASSIGN NAME = "l.count"VALUE = "{ l.count + 1 }"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "name"VALUE = "Home"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "type"VALUE = "link"><MvASSIGN NAME = "l.count"VALUE = "{ l.count + 1 }"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "name"VALUE = "Email"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "type"VALUE = "link"><MvASSIGN NAME = "l.count"VALUE = "{ l.count + 1 }"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "name"VALUE = "Forums"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "type"VALUE = "link"><MvASSIGN NAME = "l.count"VALUE = "{ l.count + 1 }"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "name"VALUE = "More Links"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "type"VALUE = "title"><MvASSIGN NAME = "l.count"VALUE = "{ l.count + 1 }"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "name"VALUE = "Store"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "type"VALUE = "link"><MvASSIGN NAME = "l.count"VALUE = "{ l.count + 1 }"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "name"VALUE = "Account"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "type"VALUE = "link"><MvASSIGN NAME = "l.count"VALUE = "{ l.count + 1 }"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "name"VALUE = "Logoff"><MvASSIGN NAME = "l.array"INDEX = "{ l.count }"MEMBER = "type"VALUE = "link"><MvFUNCTIONRETURN VALUE = "{ l.count }"></MvFUNCTION><MvCOMMENT>
|
| Manditory functions for templating to work
| This must be in a central location, with g.Module_Feature_TUI_MGR set to it's path
| As seen in the original code, this function then MvDO's whatever module was passed-in via the settings variable
| Techinically, actions could be done here if there is only a controlled set of files (no modules loaded and unloaded)
|
</MvCOMMENT><MvFUNCTION NAME = "TemplateManager_Component_Render_Start"PARAMETERS = "settings var, item, param"STANDARDOUTPUTLEVEL = ""><MvCOMMENT> This is the original code from MM
<MvIF EXPR = "{ NOT miva_member_exists( l.settings:_mgr:lookup, l.item ) }">
<MvFUNCTIONRETURN>
</MvIF>
<MvREFERENCE NAME = "l.item_settings" VARIABLE = "{ 'l.settings:' $ l.item }">
<MvREFERENCE NAME = "l.module" VARIABLE = "{ 'l.settings:_mgr:lookup:' $ l.item $ ':module' }">
<MvDO FILE = "{ g.Module_Root $ l.module:module }" NAME = "l.null" VALUE = "{ ComponentModule_Render_Start( l.module, l.item, l.settings, l.item_settings, l.param ) }">
</MvCOMMENT><MvIFDEF NAME = "DEBUG"><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><p><strong>TemplateManager_Component_Render_Start:</strong><br>l.settings =<MvEVAL EXPR = "{ encodeentities( miva_array_serialize( l.settings ))}"><br>l.item =<MvEVAL EXPR = "{ encodeentities( l.item )}"><br>l.param =<MvEVAL EXPR = "{ encodeentities( l.param )}"></p><MIVA STANDARDOUTPUTLEVEL = ""></MvIFDEF><MvEVAL EXPR = "{[ g.Module_Feature_TUI_MGR ].ComponentModule_Render_Start( l.module, l.item, l.settings, l.item_settings, l.param )}"></MvFUNCTION><MvFUNCTION NAME = "TemplateManager_Component_Render_End"PARAMETERS = "settings var, item, param"STANDARDOUTPUTLEVEL = ""><MvCOMMENT> This is the original code from MM
<MvIF EXPR = "{ NOT miva_member_exists( l.settings:_mgr:lookup, l.item ) }">
<MvFUNCTIONRETURN>
</MvIF>
<MvREFERENCE NAME = "l.item_settings" VARIABLE = "{ 'l.settings:' $ l.item }">
<MvREFERENCE NAME = "l.module" VARIABLE = "{ 'l.settings:_mgr:lookup:' $ l.item $ ':module' }">
<MvDO FILE = "{ g.Module_Root $ l.module:module }" NAME = "l.null" VALUE = "{ ComponentModule_Render_End( l.module, l.item, l.settings, l.item_settings, l.param ) }">
</MvCOMMENT><MvIFDEF NAME = "DEBUG"><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><p><strong>TemplateManager_Component_Render_End:</strong><br>l.settings =<MvEVAL EXPR = "{ encodeentities( miva_array_serialize( l.settings ))}"><br>l.item =<MvEVAL EXPR = "{ encodeentities( l.item )}"><br>l.param =<MvEVAL EXPR = "{ encodeentities( l.param )}"></p><MIVA STANDARDOUTPUTLEVEL = ""></MvIFDEF><MvEVAL EXPR = "{[ g.Module_Feature_TUI_MGR ].ComponentModule_Render_End( l.module, l.item, l.settings, l.item_settings, l.param )}"></MvFUNCTION><MvCOMMENT>
|
| This pair of functions would be included in each of the modules
| It is used to determine which action each item should perform based on item name, param, and values from l.item_settings
|
</MvCOMMENT><MvFUNCTION NAME = "ComponentModule_Render_Start"PARAMETERS = "module var, item, all_settings var, item_settings var, param"STANDARDOUTPUTLEVEL = ""><MvIFDEF NAME = "DEBUG"><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><p><strong>ComponentModule_Render_Start:</strong><br>l.module =<MvEVAL EXPR = "{ encodeentities( l.module )}"><br>l.item =<MvEVAL EXPR = "{ encodeentities( l.item )}"><br>l.all_settings =<MvEVAL EXPR = "{ encodeentities( miva_array_serialize( l.all_settings ))}"><br>l.item_settings =<MvEVAL EXPR = "{ encodeentities( miva_array_serialize( l.item_settings ))}"><br>l.param =<MvEVAL EXPR = "{ encodeentities( l.param )}"></p><MIVA STANDARDOUTPUTLEVEL = ""></MvIFDEF><MvIF EXPR = "{ l.item EQ 'nav-item'}"><MvEVAL EXPR = "{[ g.default:path $ l.item $'.mvc'].Template_Render( l.page, l.all_settings )}"><MvELSEIF EXPR = "{ l.item EQ 'font-style'}"><MvIF EXPR = "{ l.param EQ 'bold'}"><MvEVAL EXPR = "{'<strong>'}"></MvIF></MvIF></MvFUNCTION><MvFUNCTION NAME = "ComponentModule_Render_End"PARAMETERS = "module var, item, all_settings var, item_settings var, param"STANDARDOUTPUTLEVEL = ""><MvIFDEF NAME = "DEBUG"><MIVA STANDARDOUTPUTLEVEL = "text, html, compresswhitespace"><p><strong>ComponentModule_Render_End:</strong><br>l.module =<MvEVAL EXPR = "{ encodeentities( l.module )}"><br>l.item =<MvEVAL EXPR = "{ encodeentities( l.item )}"><br>l.all_settings =<MvEVAL EXPR = "{ encodeentities( miva_array_serialize( l.all_settings ))}"><br>l.item_settings =<MvEVAL EXPR = "{ encodeentities( miva_array_serialize( l.item_settings ))}"><br>l.param =<MvEVAL EXPR = "{ encodeentities( l.param )}"></p><MIVA STANDARDOUTPUTLEVEL = ""></MvIFDEF><MvIF EXPR = "{ l.item EQ 'nav-item'}"><MvELSEIF EXPR = "{ l.item EQ 'font-style'}"><MvIF EXPR = "{ l.param EQ 'bold'}"><MvEVAL EXPR = "{'</strong>'}"></MvIF></MvIF></MvFUNCTION>