View Full Version : l.module:features
RayYates
06-19-08, 04:28 PM
I trying to write a mm5 module with these features
component,data_store,util,vis_store,vis_util
When I install the module I see it listed Under the Utility section but their is no checkbox. What am I doing wrong?
I don't fully get util, vis_util, vis_store
I'm not using the left navigation function provided under util
In the docs see vis_store contains the familiar (from mm4)...
Module_Store_Validate(module var)
Module_Store_Update(module var)
Module_Store_Tabs(module var)
Module_Store_Content(module var, tab, load_fields)
...but my tab and content is not showing up.
I'm unclear on the purpose of the vis_util section; It seems to duplicate vis_store.
Module_Utility_Content(module var, tab, load_fields)
Module_Utility_Tabs(module var)
Module_Utility_Update(module var)
Module_Utility_Validate(module var)
I'm don't think I need both but can not get either to work.
Please help.
aGorilla
06-19-08, 04:42 PM
Try putting 'util' first.
Kent Multer
06-19-08, 06:49 PM
Under MM5, the familiar Module_Store_XXX functions work differently. They show up on the "store" admin page, the one whose link is the store name on the left-side menu. These functions also appear in the Pages section of admin.
If you want your modules to work the way they did in MM4, then you change the Module_Store_XXX functions to Module_Utility_XXX (or Module_System_XXX, whatever) -- AND, as Bill said, you need to put the "primary" feature first in the list.
RayYates
06-19-08, 07:20 PM
Got it. So far so good.
One more thing... How do I add a new component item to the page items list during installation?
Is there an API call?
Thx guys
Kent Multer
06-19-08, 09:17 PM
It's not trivial; you have to work your way thru several different databases. Here's some code that I've used in several modules, so I think it's bug free ...
<MvFUNCTION NAME="InstallComponent" PARAMETERS="itemcode, pagecodes" STANDARDOUTPUTLEVEL="">
<MvASSIGN NAME="l.xx" VALUE="{ Module_Description(l.module) }">
<MvASSIGN NAME="l.ci" VALUE="{ [g.Module_Feature_TUI_MGR
].TemplateManager_Create_Item(l.itemcode, l.module:code ) }">
<MvIF EXPR="{ NOT l.ci }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t create \"' $ l.itemcode $ '\" item<br>' }">
<MvFUNCRETURN VALUE="0">
<MvELSE>
<MvEVAL EXPR="{ 'Added \"' $ l.itemcode $ '\" item to store<br>' }">
</MvIF>
<MvASSIGN NAME="l.li" VALUE="{ [g.Module_Feature_TUI_DB].Item_Load_Code(l.itemcode, l.item) }">
<MvIF EXPR="{ NOT l.li }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t load \"' $ l.itemcode $ '\" item<br>' }">
<MvFUNCRETURN VALUE="0">
</MvIF>
<MvASSIGN NAME="l.stbl" VALUE="{ g.Store_Table_Prefix }">
<MvIF EXPR="{ l.pagecodes EQ '*' }">
<MvASSIGN NAME="l.pagecodes" VALUE="">
<MvASSIGN NAME="l.v" VALUE="{ View('CHKMpages', 'SELECT (code) FROM [s]Pages', '') }">
<MvWHILE EXPR="{ NOT CHKMpages.d.eof }">
<MvASSIGN NAME="l.pagecodes" VALUE="{ Append(l.pagecodes, CHKMpages.d.code) }">
<MvSKIP NAME="Merchant" VIEW="CHKMpages">
</MvWHILE>
</MvIF>
<MvWHILE EXPR="{ gettoken(l.pagecodes, ',', l.n + 1) }">
<MvASSIGN NAME="l.n" VALUE="{ l.n + 1 }">
<MvASSIGN NAME="l.pcode" VALUE="{ gettoken(l.pagecodes, ',', l.n) }">
<MvASSIGN NAME="l.lp" VALUE="{ [g.Module_Feature_TUI_DB].Page_Load_Code(l.pcode, l.page) }">
<MvIF EXPR="{ NOT l.lp }">
<MvEVAL EXPR="{ 'NOTE: couldn\'t load ' $ l.pcode $ ' page<br>' }">
<MvELSE>
<MvASSIGN NAME="l.ai" VALUE="{ [g.Module_Feature_TUI_MGR
].TemplateManager_Page_Assign_Item(l.page, l.item:code) }">
<MvIF EXPR="{ NOT l.ai }">
<MvEVAL EXPR="{ 'NOTE: couldn\'t add \"' $ l.item:code
$ '\" item to ' $ l.page:code $ ' page<br>' }">
<MvELSE>
</MvIF>
<MvEVAL EXPR="{ '\"' $ l.item:code $ '\" item assigned to ' $ l.page:code $ ' page<br>' }">
</MvIF>
</MvWHILE>
<MvFUNCRETURN VALUE="1">
</MvFUNCTION>
<MvFUNCTION NAME="UninstallComponent" PARAMETERS="itemcode" STANDARDOUTPUTLEVEL="">
<MvASSIGN NAME="l.xx" VALUE="{ Module_Description(l.module) }">
<MvASSIGN NAME="l.li" VALUE="{ [g.Module_Feature_TUI_DB].Item_Load_Code(l.itemcode, l.item) }">
<MvIF EXPR="{ NOT l.li }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t load \"' $ l.itemcode $ '\" item<br>' }">
<MvFUNCRETURN VALUE="0">
</MvIF>
<MvASSIGN NAME="l.xx" VALUE="{ View('CHKMpages', 'SELECT * FROM [s]Pages', '') }">
<MvWHILE EXPR="{ NOT CHKMpages.d.eof }">
<MvASSIGN NAME="l.lp" VALUE="{ [g.Module_Feature_TUI_DB].Page_Load_Code(CHKMpages.d.code, l.page) }">
<MvIF EXPR="{ NOT l.lp }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t load ' $ CHKMpages.d.code $ ' page<br>' }">
<MvELSE>
<MvASSIGN NAME="l.xx" VALUE="{ View('CHKMpxi',
'SELECT * FROM [s]PageXItem WHERE (page_id = ' $ l.page:id $ ') AND (item_id = ?)', l.item:id) }">
<MvIF EXPR="{ NOT CHKMpxi.d.eof }">
<MvASSIGN NAME="l.ai" VALUE="{ [g.Module_Feature_TUI_MGR
].TemplateManager_Page_Unassign_Item(l.page, l.item:code) }">
<MvIF EXPR="{ NOT l.ai }">
<MvEVAL EXPR="{ 'NOTE: couldn\'t deassign \"' $ l.item:code
$ '\" item from ' $ CHKMpages.d.code $ ' page<br>' }">
<MvELSE>
<MvEVAL EXPR="{ '\"' $ l.item:code $ '\" Item deassigned from ' $ CHKMpages.d.code $ ' page<br>' }">
</MvIF>
</MvIF>
</MvIF>
<MvSKIP NAME="Merchant" VIEW="CHKMpages">
</MvWHILE>
<MvASSIGN NAME="l.di" VALUE="{ [g.Module_Feature_TUI_MGR].TemplateManager_Delete_Item(l.item) }">
<MvIF EXPR="{ NOT l.di }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t delete \"' $ l.item:code $ '\" item<br>' }">
<MvFUNCRETURN VALUE="0">
<MvELSE>
<MvEVAL EXPR="{ 'Removed \"' $ l.item:code $ '\" item from store<br>' }">
</MvIF>
<MvFUNCRETURN VALUE="1">
</MvFUNCTION>
RayYates
06-19-08, 10:35 PM
FANTASTIC :) This makes a lot of sense but I have two questions.
These functions are referring to two external functions.
View() and Append()
If I could impose on you just a bit further, would you be so kind as to post them as well?
Kent Multer
06-19-08, 10:48 PM
Oops, sorry. Here are those two, as well as the Unview() function which is a companion to View() --
<MvFUNCTION NAME="Append" PARAMETERS="list, item" STANDARDOUTPUTLEVEL="">
<MvIF EXPR="{ (len(l.list) EQ 0) }">
<MvFUNCRETURN VALUE="{ l.item }">
</MvIF>
<MvFUNCRETURN VALUE="{ l.list $ ',' $ l.item }">
</MvFUNCTION>
<MvFUNCTION NAME="View" PARAMETERS="vname, query, key" STANDARDOUTPUTLEVEL="">
<MIVA MvOPENVIEW_Error="nonfatal, nodisplay">
<MvIF EXPR="{ miva_variable_value('g._ViewOpen:' $ l.vname) }">
<MvCLOSEVIEW NAME="Merchant" VIEW="{ l.vname }">
<MvASSIGN NAME="{ 'g._ViewOpen:' $ l.vname }" VALUE="">
</MvIF>
<MvASSIGN NAME="l.query" VALUE="{ glosub(l.query, '[s]', g.Store_Table_Prefix) }">
<MvIF EXPR="{ len(l.key) }">
<MvOPENVIEW NAME="Merchant" VIEW="{ l.vname }"
QUERY="{ l.query }"
FIELDS="l.key">
<MvELSE>
<MvOPENVIEW NAME="Merchant" VIEW="{ l.vname }"
QUERY="{ l.query }">
</MvIF>
<MvIF EXPR="{ g.MvOPENVIEW_Error }">
<MvEVAL EXPR="{ 'ERROR on query \"' $ l.query $ '\" -- ' $ g.MvOPENVIEW_Error $ '<br>' }">
<MvFUNCRETURN VALUE="0">
</MvIF>
<MvASSIGN NAME="{ 'g._ViewOpen:' $ l.vname }" VALUE="1">
<MvFUNCRETURN VALUE="1">
</MvFUNCTION>
<MvFUNCTION NAME="UnView" PARAMETERS="vname" STANDARDOUTPUTLEVEL="">
<MvIF EXPR="{ miva_variable_value('g._ViewOpen:' $ l.vname) }">
<MvCLOSEVIEW NAME="Merchant" VIEW="{ l.vname }">
<MvASSIGN NAME="{ 'g._ViewOpen:' $ l.vname }" VALUE="">
</MvIF>
</MvFUNCTION>
Kent,
Is that removing the
<mvt:item name="foo" param="l.settings:product:code" /> from the page template code? I have been doing that with a lot more convoluted code than you are using above.
Kent Multer
06-19-08, 11:34 PM
The previous code doesn't actually insert or remove the tag in the page template. As you can imagine, that's quite a bit more complex.
Here's a piece of code from my Currency Magic module. This gets run after the "currencymagic" item has been added to the store. This code assigns the item to every page, and it modifies the templates to insert the mvt:item tag just before the category_tree tag on each page. It creates new versions of the templates it changes.
I'm not including the source for my LoadView() function, but I think you can figure out something equivalent. It just reads the Pages database and stores the data for all the pages into the l.pages array.
<MvASSIGN NAME="l.li" VALUE="{ [g.Module_Feature_TUI_DB].Item_Load_Code('currencymagic', l.item) }">
<MvIF EXPR="{ NOT l.li }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t load template item<br>' }">
<MvFUNCRETURN VALUE="0">
</MvIF>
<MvASSIGN NAME="l.stbl" VALUE="{ g.Store_Table_Prefix }">
<MvASSIGN NAME="l.pages" VALUE="{ LoadView(l.stbl $ 'Pages', 'SELECT * FROM ' $ l.stbl $ 'Pages;') }">
<MvWHILE EXPR="{ l.pages[l.n + 1]:code }">
<MvASSIGN NAME="l.n" VALUE="{ l.n + 1 }">
<MvASSIGN NAME="l.lp" VALUE="{ [g.Module_Feature_TUI_DB].Page_Load_Code( l.pages[l.n]:code, l.page ) }">
<MvIF EXPR="{ NOT l.lp }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t load ' $ l.pages[l.n]:code $ ' page<br>' }">
<MvFUNCRETURN VALUE="0">
</MvIF>
<MvASSIGN NAME="l.ai" VALUE="{ [g.Module_Feature_TUI_MGR
].TemplateManager_Page_Assign_Item(l.page, l.item:code) }">
<MvIF EXPR="{ NOT l.ai }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t add item to ' $ l.page:code $ ' page<br>' }">
<MvFUNCRETURN VALUE="0">
</MvIF>
<MvASSIGN NAME="l.lt" VALUE="{ [g.Module_Feature_TUI_DB
].ManagedTemplate_Load_ID(l.page:templ_id, l.template) }">
<MvIF EXPR="{ NOT l.lt }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t load template<br>' }">
<MvFUNCRETURN VALUE="0">
</MvIF>
<MvASSIGN NAME="l.lv" VALUE="{ [g.Module_Feature_TUI_DB
].ManagedTemplateVersion_Load_Template_Current(l.pa ge:templ_id, l.version) }">
<MvIF EXPR="{ NOT l.lv }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t load template version<br>' }">
<MvFUNCRETURN VALUE="0">
</MvIF>
<MvASSIGN NAME="l.source" VALUE="{ l.version:source }">
<MvASSIGN NAME="l.tfirst" VALUE="{ '<mvt:item name=\"category_tree\" />' IN l.source }">
<MvIF EXPR="{ l.tfirst }">
<MvASSIGN NAME="l.newsource" VALUE="{ substring(l.source, 1, l.tfirst - 1)
$ '<mvt:item name=\"currencymagic\" />' $ substring(l.source, l.tfirst, len(l.source)) }">
<MvASSIGN NAME="l.cv" VALUE="{ [g.Module_Feature_TUI_MGR
].TemplateManager_Create_ManagedTemplateVersion(l.t emplate, 'Currency Magic installation',
l.newsource, l.page:settings, l.errmsg) }">
<MvIF EXPR="{ (NOT l.cv) OR len(l.errmsg) }">
<MvEVAL EXPR="{ 'ERROR: couldn\'t modify page ' $ l.page:code $ '<br>' }">
<MvIF EXPR="{ len(l.errmsg) }">
<MvEVAL EXPR="{ 'Error message: ' $ l.errmsg $ '<br>' }">
</MvIF>
<MvELSE>
<MvEVAL EXPR="{ l.page:code $ ' page modified<br>' }">
</MvIF>
</MvIF>
</MvWHILE>
I was hoping you found the easy way of removing the tags. The code I wrote is so convoluted I only put it on a couple modules thus far.
Kent Multer
06-20-08, 12:10 AM
There's an easy way? For removing tags, I basically use the same code I posted above, to create new template versions, but deleting the tag instead of inserting it. If you know a better way, please tell!
That is what I do. But the tags are not always easy to identify. I have so many that take variable parameters that you can't just look for a specific string. You have to find <mvt:item name="code passed as a parameter to the function Then find the end of that tag "/>". Then strip out the characters between the location at the beginning and the location at the end. Then recompile the page.
RayYates
06-20-08, 01:10 PM
Thanks Kent,
One again, you've saved me an enormous amount of time. Works like a charm.
Kent Multer
06-20-08, 05:43 PM
Actually, much of that was based on code that other people provided to me; so it seems only fair to pass it along. :)
eMediaSales
06-24-08, 12:57 AM
Here's what I use to create items, assign to pages, unassign from pages and delete items:
<MvCOMMENT> *************** CREATE ITEMS *************** </MvCOMMENT>
<MvIF EXPR = "{ NOT [ g.Module_Feature_TUI_DB ].Item_Load_Code( 'itemcode', l.item ) }">
<MvIF EXPR = "{ NOT [ g.Module_Feature_TUI_MGR ].TemplateManager_Create_Item( 'itemcode', l.module:code ) }">
<MvFUNCTIONRETURN VALUE = "{ [ g.Module_Library_Utilities ].Error( 'MER-EMSSB-00121', 'Unable to create item itemcode' ) }">
</MvIF>
</MvIF>
<MvCOMMENT> *************** ASSIGN TO PAGES *************** </MvCOMMENT>
<MvIF EXPR = "{ [ g.Module_Feature_TUI_DB ].Page_Load_Code( 'ACED', l.page ) }">
<MvIF EXPR = "{ NOT [ g.Module_Feature_TUI_MGR ].TemplateManager_Page_Assign_Item( l.page, 'itemcode' ) }">
<MvFUNCTIONRETURN VALUE = "{ [ g.Module_Library_Utilities ].Error( 'MER-EMSSB-00133', 'Error assigning itemcode to ACED page' ) }">
</MvIF>
</MvIF>
Now to reverse the process, remember do your best not to throw any errors on either side of install/uninstall - it will leave your refcounts in the modules / moduleXstore databases fouled up with only a database edit to save you. Do your best to fail gracefully and/or recover at a later spot:
<MvCOMMENT> *** REMOVE ITEMS FROM PAGE *** </MvCOMMENT>
<MvIF EXPR = "{ [ g.Module_Feature_TUI_DB ].Page_Load_Code( 'ACED', l.page ) }">
<MvASSIGN NAME="l.discard" VALUE="{ [ g.Module_Feature_TUI_MGR ].TemplateManager_Page_Unassign_Item( l.page, 'itemcode' ) }">
</MvIF>
<MvCOMMENT> *** DELETE ITEMS *** </MvCOMMENT>
<MvIF EXPR = "{ [ g.Module_Feature_TUI_DB ].Item_Load_Code( 'itemcode', l.item ) }">
<MvDO FILE = "{ g.Module_Feature_TUI_MGR }" NAME = "l.deleted" VALUE = "{ TemplateManager_Delete_Item( l.item ) }">
</MvIF>
Vary itemcode and the page code (ACED in the examples above) as necessary. It is also helpful to scan ALL pages in the store and make sure your items are removed, otherwise again sometimes refcounts can get messed up.
As far as Bill's template code insertions and deletions, this is as simple as a glosub IF you only have hardcoded specific params. But many modules don't have this benefit (think toolkit where it can literally be *anything*) it's nearly impossible. I've resorted to providing install instructions for most template capable modules....
Hope this helps a bit -
james
vBulletin® v3.7.4, Copyright ©2000-2009, Jelsoft Enterprises Ltd.