Hi,
I am currently developing two components: the Networkit (social networking) component, and a Loop ("foreach") and Case snippet combo that I am trying to turn into an easier FormIt form generator. Both of these projects have encountered a partial caching problem with placeholders. This may actually not be a problem at all and part of the design, but in both cases I think it would make sense for the partial caching to work.
The Loop/ Case Issue:
Here is my FormIt call code, which works perfectly when the Loop snippet and [[$field]] chunks are called uncached:
[[!FormIt? &hooks=`recaptcha,spam,email,redirect` &emailTpl=`ContactFormReport` &emailTo=`[[++emailsender]]` &emailSubject=`New message from [[++site_name]] [[*pagetitle]] page.` &redirectTo=`7` &submitVar=`submitForm` &validate=`[[Loop? &separator=`:required,` &idx=`0` &loop=`first==last==company==address==city==state==zip==phone==primary_color==floor_area==
grout_joint_filling_of_cut_control_joints==repair_of_holes_and_cracks==
edge_tint_border==start-up_maintenance_program==email:email==message`]]:required, blank:blank`]]
<div>[[+fi.error.error_message]] [[!+fi.validation_error_message]] [[+fi.error.recaptcha]]</div>
<form id="submitForm" action="[[~[[*id]]]]" method="post"><fieldset><div class="wrap">
<input name="blank" type="hidden" />
[[!Loop? &tpl=`field` &ph=`name,req,label` &static=`type==text` &loop=`
first==last==company==address==address2==city==state==zip==email==phone==fax==floor_area
||1==1==1==1====1==1==1==1==1====1
||======================Floor Area (sq.ft.)
` ]]
[[!$field? &name=`existing_floor_covering` &type=`checkbox` &label=`Yes` &message=`Existing floor covering` &numeric=`0`]]
[[!$field? &name=`type_of_covering` &type=`text`]]
[[!$field? &name=`primary_color` &type=`select` &req=`1` &options=`Natural==Color`]]
[[!Loop? &ph=`name,message` &static=`req==1||type==radio` &tpl=`field` &loop=`grout_joint_filling_of_cut_control_joints==repair_of_holes_and_cracks==edge_tint_border==start-up_maintenance_program||Grout/ joint filling of cut & control joints?==Patching of blemishes/ cracks/ tenches?==Edge tine border?==Start-up maintenance program?`]]
[[!$field? &name=`message` &req=`1` &type=`textarea`]]
<div class="captcha">
[[+fi.error.recaptcha]]
[[!+formit.recaptcha_html]]
</div>
[[!$field? &type=`submit` &name=`submitForm` &value=`Send This Message` &message=` `]]
</div></fieldset></form>
And here is the [[$field]] chunk:
<div>
<label for="[[+name]]">[[+req:notempty=`* `]][[+message:default=`[[+label:default=`[[+name:replace=`_== `:ucwords]]`]]`]]</label>
[[Case? &subject=`[[+type:default=`text`]]`
&case1=`text` &then1=`
<input id="[[+name]]" class="[[+type]] [[+class]][[!+fi.error.[[+name]]:notempty=` error`]]" name="[[+name]]" type="[[+type]]" value="[[!+fi.[[+name]]]]" />
`
&case2=`textarea` &then2=`
<textarea id="[[+name]]" class="[[+type]] [[+class]][[!+fi.error.[[+name]]:notempty=` error`]]" name="[[+name]]">[[+fi.[[+name]]]]</textarea>
`
&case3=`checkbox` &then3=`
<input name="[[+name]]" type="hidden" value="[[+default]]" />
[[$fieldBool? &type=`checkbox` &name=`[[+name]]` &label=`[[+label]]` &message=`[[+label]]`]]
`
&case4=`radio` &then4=`
[[!+fi.error.[[+name]]:notempty=`<span class="left error">`]]
<input type="hidden" name="[[+name]]" />
[[$fieldBool? &name=`[[+name]]` &label=`Yes` &message=`Yes`]]
[[$fieldBool? &name=`[[+name]]` &label=`No` &message=`No`]]
[[!+fi.error.[[+name]]:notempty=`</span>`]]
`
&case5=`submit` &then5=`
<input id="[[+name]]" class="button" name="[[+name]]" type="[[+type]]" value="[[+label:default=`Submit`]]" />
`
&case6=`select` &then6=`
<select name="[[+name]]" id="[[+name]]" class="[[!+fi.error.[[+name]]:notempty=`error`]]">
<option name="[[+name]]" value="[[+default]]">[[+label]]</option>
[[Loop? &tpl=`fieldOption` &static=`name==[[+name]]` &ph=`label` &loop=`[[+options]]` ]]
</select>
`
]]
[[!+fi.error.[[+name]]]]
</div>
The Loop snippet code is available here:
http://modxcms.com/forums/index.php/topic,60559.0.html
And the Case snippet code is available here:
http://modxcms.com/forums/index.php/topic,61045.0.html
What doesn’t work when [[Loop]] and [[$field]] are called cached: Everything works EXCEPT [[!+fi.error.[[+name]]:notempty=`error`]]. Even the "[[!+fi.error.[[+name]]]]" placeholders are generated properly as "This field is required".
When it actually works: If the [[$field]] template does NOT use a [[Case]] snippet, everything works as expected, including the [[!+fi.error.[[+name]]:notempty=`error`]].
Why the Loop and [[$field]] snippets should be cached: Because only static input goes in! Partial caching means that the uncached placeholder [[!+fi.error.[[+name]]:notempty=`error`]] should be generated every time from scratch, but everything else can be cached. There is no need to re-generate a text input field! It will always remain a text input field!
The NetworkIt Issue:
This snippet is pretty complicated, but basically the idea is that a resource with a GET parameter for userid similar to "wall_userid" will output a bunch of information about that user, including FormIt calls that will send messages to the user, a list of messages to/ from the user, etc....
To avoid having to call [[!getUrlParam? &name=`wall_userid`]] or a similar snippet over and over on the page, I use [[!Profile? &user=`[[!getUrlParam? &name=`wall_userid`]]` &prefix=`public.`]] at the top of the template so that I can just use [[+public.fullname]] instead of [[!getUrlParam:userinfo=`fullname`? &name=`wall_userid`]]. And yes, I know I can just make a short snippet like [[!getUser:userinfo=`fullname`]] or [[!getUser? &info=`fullname`]], but I would need to call that as often as 20 times a page or more, so it makes sense to use placeholders instead to avoid database queries, especially if the site will have a huge user database.
Here’s the problem: I want to use caching for the page for every single user. Normally, [[Profile? &user=`1`]] would be cached, [[Profile? &user=`2`]] would be cached, etc.... But, I am forced to call Profile (and thus all placeholders) uncached.
Calling Profile uncached is a tolerable situation, but I can’t use caching on other snippets either. For example: [[Gravatar? &email=`[[!+public.email]]`]] SHOULD be cached for every email, because (assuming the email doesn’t change), there is no need to re-generate the gravatar URL every time. However, snippets with placeholder inputs only work if called uncached. By comparison, [[Gravatar? &email=`[[!getUrlParam? &name=`wall_userid`]]`]] works perfectly well cached.
Here is the cached portion of the resource for Gravatar (modified slightly for anonymity):
'[[Gravatar? &email=`2` &size=`40`]]' => 'http://www.gravatar.com/avatar.php?gravatar_id=XXXXX&size=40&rating=G&default=wavatar',
'[[Gravatar? &email=`13` &size=`40`]]' => 'http://www.gravatar.com/avatar.php?gravatar_id=YYYYY&size=40&rating=G&default=wavatar',
'[[Gravatar? &email=`28` &size=`40`]]' => 'http://www.gravatar.com/avatar.php?gravatar_id=ZZZZZ&size=40&rating=G&default=wavatar',
Of course, I would probably need to set up a custom caching system that is user-based and not document-based, but it would still need to use placeholders for the easiest implementation.
The main goal of this snippet is to allow a site with hundreds or thousands of users to output hundreds or thousands of messages. If I can’t call the [[getMessages? &user=`[[!+public.id]]`]] cached, the website would slow down to a crawl. So, is using a [[!getUser:userinfo=`XXX`]] snippet (which also has an overhead) all over the page my only alternative to enable caching? Shouldn’t there be some sort of method in MODx to force SOME placeholders to be evaluated FIRST, thus enabling cached snippets?
Any recommendations?