I have a relatively large legacy Perl/CGI/DBI web application which generates HTML on-the-fly piece by piece. We are reworking the HTML being produced, to come in to compliance with HTML 5 / CSS 3. This would be a good time to move to some sort of template system. We do NOT want to engage in a complete rewrite, and thus do NOT want to migrate to a framework such as Catalyst.
I'm thinking that Perl Template Toolkit might be our lowest-impact means. I'm re-reading the venerable Badger Book to study up on feasibility.
My question is this. Has anyone here migrated "old school" Perl web code to Template Toolkit? Are there any tricks you can share for minimizing the rewrite/rework needed? We have not 100% decided on Template Toolkit, either. If there is an alternative which we should consider?
What problem, specifically, are we trying to solve? We're generating invalid HTML and need to clean that up. Since we're cleaning, we want to produce fully-valid HTML 5 and, to the extent practicable, valid CSS3 and Javascript. We use jQuery, jQuery UI widgets, and AJAX via jQuery. We have typical Page Controller MVC architecture except no View layer as such. We'd like to go to some sort of template system but don't want to rewrite everything (or much of anything!) to migrate.
Thank You!
Ed Barnard, Cannon Falls MN
Here's what I've found, as I've moved my practice from CGI.pm to TT, and what I've also learned along the way using HTML::Mason, HTML::Template, Text::Template, and working with ERB and HAML in Rails.
The more logic you have in in your displays, especially if it is written in a display specific language, the less fun you're going to have.
I've come to prefer HAML for the reduction in size of the contents of my templates [ In HAML, closing tags are implied by indentation ]
Perform as much of the logic to compute the various dynamic bits of the page before you drop into the template, in the application's native language. [ call view methods, before engaging in rendering ].
In relation to (3), by using methods, instead of inline display/rendering logic, you can make your templates declarative, so while you might be performing logic in the middle of the render, your templates don't have a bunch of IF/THEN/ELSE logic causing clutter.
Let's imagine a reasonably small, contrived web page made up of a header, and footer and a body. Let's assume that the footer is completely static, the body changes every time a new page loads, but the header only changes when a user logs in/out.
You can imagine the header containing code like this:
<header>
[% IF $user.is_logged_in THEN %]
Hello [% $user.name %] - Log Out
[% ELSE %]
Please Log In
[% END %]
</header>
But you're better off in the long term doing this in header.tt:
<header>
[% user_info($user) |html %]
</header>
and this in View::Helpers::Header.pm:
sub user_info {
my $user = shift;
if ($user->{is_logged_in} ) {
return "Hello $user->{name} - " . logout_link($user->{id});
}
else {
return "Please " . login_link();
}
}
sub logout_link {
my $userid = shift;
return qq(Log Out)
}
You can, of course, implement the view helpers in TT rather than pure Perl, and I don't have any kind of numbers for you, but if you've done all of your logic in Perl already, you can refactor the Perl into modules (if it isn't there already), instead of re-coding them in TT.
As part of your test suite, consider an HTML validator like HTML::Lint or HTML::Tidy.
Related
What I'm aiming to do!
I'm creating a template for a site in typo3, and i'd like to get rid of typo3's default content zones, and replace them with my own.
I.E. On the page menu.
to remove left, content, border
and to keep/add. Header. Main. Right.
The problem!
I've found snippets around the web, and bluntly, what I'm expecting to happen, isn't happening. Where every post seems to be "Thank you, great success! ++", the code I paste isn't throwing any errors, and isn't doing anything, well, at all.
My attempt
Via the typo3 documentation http://typo3.org/documentation/snippets/sd/24/
I call mod.SHARED.colPos_list in order to choose the three sections to display
t3lib_extMgm::addPageTSConfig('
mod.SHARED.colPos_list = 0,1,3
');
And I edit the TCA in extTables.php to set them to my specs.
$TCA["tt_content"]["columns"]["colPos"]["config"]["items"] = array (
"1" => array ("Header||Header||||||||","1"),
"0" => array ("Main||Main||||||||","0"),
"3" => array ("Right||Right||||||||","3"),
);
extTables.php is being called as as a die(); cuts the page.
I've cleared the cache and deleted typo3temp, logged out and in again.
But nothing happens.
My main guess, is, is this feature anything to do with templavoila? I removed it as I felt like trying out the new(er) typo3 fluid templating system, and didn't feel that I needed a GUI editor.
Any ideas?
Well - the more pages and content elements you got the more problems you will have to face when using TemplaVoila. Having comma separated values in XML structures saved to a single database field will be a performance killer as soon as you want to collect content from more than one page (uncached teaser menus or the like). Handling of references and "unused elements" is questionable as well. Of course it will work for small to medium sites, but concept wise a clean approach looks different.
Backend layouts are available since TYPO3 4.5 and work flawlessly since they just represent a normalized relation between elements and pages based on colPos. If you need more, Grid Elements will take this principle to the next level, offering even nested structures but still based on normalized relations, which will make your life much easier when it comes to DB cleaning and other maintenance tasks.
Find an introduction to backend layouts here: http://www.youtube.com/watch?v=SsxfNd4TYbk
Instead of removing default columns you can just rename them...
TIP: Use TemplaVoila extension for templating, you'll find much more flexibility there.
I have been using plain forms and input fields in coldfusion for some time now but recently discovered that cfinput tags will automagically prevent some xss attacks for me. This has made me wonder, if there is any disadvantages to using cffrom and cfinput over normal form and input tags in coldfusion.
The only disadvantage I have found in the short time looking into it is that it adds 2 external style sheets and 1 script tag to the page.
so in short:
What are the advantages and disadvantages of using CFFORM over FORM in coldfusion?
I prefer to write my own JS around my forms. I started out with cfform back in the day, but eventually wanted to do more robust things (validations, etc) than cfform was able to handle. That forced me to learn JS, and I've been very happy writing my own JS since.
So I guess I'd say one big drawback is that you're restricted to what cfform can handle. Depending on your situation, that might be fine.
Another drawback that I ran into a long time ago (which to be fair, may have been addressed since), is that the JS generated by cfform would conflict or interfere with my hand-written JS.
It'll certainly come down to preference. It's neither "right" nor "wrong" to use cfform or regular forms. For me, I prefer to be able to do whatever manipulation I need to do manually, as there are no restrictions/limitations.
I have a love-hate relationship with <cfform> & <cfinput>.
To have the same xss protection that CFFORM provides, just wrap htmlEditFormat() around value="" in regular like so:
<input name="x" value="#htmlEditFormat(x)#">
For even better XSS protection, use OWASP Enterprise Security API (.jar included in one of the CF9 latest hotfixes)
I love how I can do ajaxified form easily without writing JS, but I hate how it generates lots of ugly JavaScript and loads up lots of JS and css files for something rather simple. So I've decided to use cfform for internal sites only and not for public facing site (performance issue).
Other then the ajax features, the checked attribute that accepts CF boolean and populating select with query object are features that cfinput and cfselect provide which can be quite useful.
Use the right tool for the right job. If you found the feature of <cfform> useful, use it. Just know its limitations, and decide for yourself.
I have been using ColdFusion for almost 14 years. The reason that CF is such a kick-ass product is that empowers new users to get a lot of work done quickly with not much understanding and it enables rocket scientists to build really powerful and secure applications quickly too.
CFFFORM, CFINPUT, CFLAYOUT, CFPOD are tags that are created for new users. Basically, they are training wheels. If you're new to web development, you should give this tags a try. As you gain experience, you'll want to drop these tags and move onto other techniques to create more robust applications.
There's nothing wrong with these tags, just like there's nothing wrong with training wheels. You just need to know that there's an appropriate tool for each job. Actually, there are lots of appropriate tools for each job.
Currently, I am developing a ColdFusion 9 / jQuery / SQL Server intranet that builds external web sites. I am doing it without using a single form tag. And, I am doing it completely in CFSCRIPT. Whoa!
Using jQuery, you don't need forms. You just need inputs. Here's how I create an input in CFSCRIPT.
<cfscript>
Options = "";
for (i = 1; i lte 10; i++) {
Options = Options & wrapOption("Some choice #i# ", i);
}
SelectBox = wrapSelect(Options, "MySelectID");
writeOutput(SelectBox);
SecretDiv = wrapDiv("", "", "MyDivID");
writeOutput(SecretDiv);
</cfscript>
The user defined functions to create the HTML are in my UDF_Library.cfm file:
// WRAP SELECT
function wrapSelect(SelectContent, Class, ID) {
LOCAL.SelectContent = ARGUMENTS.SelectContent;
LOCAL.Properties = "";
// CLASS
if (isDefined("ARGUMENTS.Class")) {
LOCAL.Properties = LOCAL.Properties & " class='#ARGUMENTS.Class#'";
}
// ID
if (isDefined("ARGUMENTS.ID")) {
LOCAL.Properties = LOCAL.Properties & " id='#ARGUMENTS.ID#'";
}
LOCAL.Item = "<select #LOCAL.Properties#>#LOCAL.SelectContent#</select>";
return LOCAL.Item;
}
// WRAP OPTION
function wrapOption(Content, Value, Selected) {
LOCAL.Content = ARGUMENTS.Content;
LOCAL.Properties = " value='#ARGUMENTS.Value#'";
// SELECTED
if (isDefined("ARGUMENTS.Selected") and (ARGUMENTS.Selected eq "selected")) {
LOCAL.Properties = LOCAL.Properties & " selected";
}
LOCAL.Item = "<option #LOCAL.Properties#>#LOCAL.Content#</option>";
return LOCAL.Item;
}
// CREATE DIV
function wrapDiv(Content, Class, ID) {
LOCAL.Properties = "";
// CLASS
if (isDefined("ARGUMENTS.Class")) {
LOCAL.Properties = LOCAL.Properties & " class='#ARGUMENTS.Class#'";
}
// ID
if (isDefined("ARGUMENTS.ID")) {
LOCAL.Properties = LOCAL.Properties & " id='#ARGUMENTS.ID#'";
}
LOCAL.Item = "<div #LOCAL.Properties#>#ARGUMENTS.Content#</div>";
return LOCAL.Item;
}
I use jQuery and refer to every element by its class or ID. If you do that, you can submit the data in each element to an ajax call like this:
<script type="text/javascript">
$(document).ready(function() {
$("#MySelectID").change(function() {
MyID = $("#MySelectID").val();
$("#MySecretDiv").load("CoolQuery.cfm?UserID"+MyID);
});
});
</script>
The point is, that as long as you are using CFFORM and CFINPUT, you can't do all the really powerful jQuery stuff. But, you need those tags to get started.
2012 is going to be a kick-ass year for the power of ColdFusion and jQuery!!!
Good luck!
I haven't used ColdFusion's CFInput in a long while. I've been using the jQuery Validation plugin so that I can perform validation on other things like:
is the element visible? (ie, hide a section if not essential, but eliminate the requirement if not shown.)
is a checkbox checked? (ie, you checked "other", now fill-in-the-blank is required.)
is it a valid date/time value? (ie, I additionally use the DateJS library to assist in this)
perform ajax query to determine if username is unique
is the URL entered valid?
compare password1 with password2
custom rules based on a combination of things
Most validation rules can be added inline to the class parameter:
<input type="text" name="Name" class="required">
<input type="text" name="Birthdate" class="required date">
<input type="text" name="Email" class="required email">
<input type="text" name="Website" class="url">
I prefer to use jQuery because sometimes I need to add this same logic to a non-ColdFusion based form and I don't have to worry about the fact the CFInput is a ColdFusion-Only tag.
Here's a link with more information regarding the jQuery Validation library:
http://bassistance.de/jquery-plugins/jquery-plugin-validation/
The main motivation in this is that I was very tired or using php tags to write php views that were very ugly. Consider this approach:
<?php
<ul>
<?php echo foreach($products as $product): ?>
<li><?php echo $product->getName()?><li>
</ul>
This is the basic approach of trivial MVC with views, but I was tired of that, so I use phpQuery instead:
<?php
$ul = pq('<ul />');
foreach($products as $product) {
$ul->append(pq('<li />')
->html($product->getName())
);
}
echo $ul;
This is much cleaner. Unfortunately, phpQuery does not seem active on development. The thing is, phpQuery is programmed in a procedural way and is really hard to understand and maintain and contains some bugs that make it rather useless in most DOM manipulation cases. I was thinking of writing an OO approach to DOM writing based on jQuery using Zend Framework's component Zend_Dom_Query, with the same approach of phpQuery: same interface as jQuery.
After some search on the net on PHP HTML Generators, I cannot seem to find much that has been done on that part, and my question is, is using OO with PHP to generate HTML a performance bottleneck, since all static HTML would be server side generated?
I know there is the HAML approach, but I like the idea of DOM manipulation, so that it is possible to inject html at any time anywhere during the script execution. DOM manipulation on the server side leads to view script inheritence like this:
//a parent index.phtml
$container = pq('<div />')
->addClass('.container')
->html($this->_("Hello World!"));
$this->setRenderReturn($container);
//a child index.phtml
$container = $this->renderParent(__FILE__); //retrieves the parent just like the conventional parent:: in php scripts
$container->addClass('anotherClass');
$this->setRenderReturn($container);
Also, in case I missed a PHP library that does just that, I would gladly appreciate if someone could point me to it.
In direct answer to your question...
is using OO with PHP to generate HTML a performance bottleneck, since all static HTML would be server side generated?
Yes.
You should have a look at Twig and particularly the extensions added in Symfony 2. It supports template inheritance as well as named sections for overwriting / inserting markup.
related to this question Zend_Form - Array based elements?
$form = new Zend_Form();
$subForm = new Zend_Form_SubForm();
$subForm->addElement('Text', '1')
->addElement('Text', '2');
$form->addSubForm($subForm, 'element');
$var = '1'; $var2 = '2';
echo $form->getSubForm('element')->$var;
echo $form->getSubForm('element')->$var2;
If I use this way output will wrongly be (or at least not quite expected)
<input type="text" value="" id="1" name="1">
If I use echo $form output will correctly be
<input type="text" value="" id="element-1" name="element[1]">
but I loose flexibility then
I am not saying it's a bug or something just not sure what proper syntax will be.
Thanks
So the answer is rather late, but I recently ran across this issue and though I'd share the reason and possible solutions.
From my research, there are at least 7 bugs in Zend's ticketing system dealing with this problem - though the descriptions vary dramatically.
(SO has prevented me from pasting all of the links, so I'll link one and give you the ticket IDs for the others: ZF-9386, ZF-3567, ZF-9451, ZF-7836, ZF-9409, ZF-7679)
http://framework.zend.com/issues/browse/ZF-10007
The one that best describes the issue, and possible fixes, is 10007 - however, ZF themselves have inexplicably chose not to fix it until 2.0.
The problem stems from the fact that when explicitly using:
$this->form->a->b->c->d notation, d will forget every one of it's ancestor subforms, except for it's immediate "c". When you have a big form with custom behavior, this is quite burdensome because you may want to render the whole subform "d" without calling out it's specific descendents, but you may want it in a certain spot or the Zend Decoraters may not be able to pull it without a bunch of work or at all.
I should think this would be a common problem in the subform world, since by definition you're working with complex forms and excepting the most generic of forms hardly any of it would be linear or clearly separated by dt/dd or other clean markup.
There are three ways I found to deal with this issue.
The first is the fine patch contributed in 10007 - this won't work for me because it only works with printing a subform directly and not individual elements - which is about 50% of my use case. Not knowing ZF well enough, I did not pursue extending this functionality to elements as well.
The second is to forgo all custom html around the elements and add enough decorators to satisfy the layout. Although mine are structured well with TRs/TDs, etc., I just couldn't justify the time nor the decision to 100% ZFify our most complex forms - because someday it could be that ZF would not be the best choice.
The third is a much more cut and dry tradeoff, which is what I chose: I would forgo the convience of being able to echo the $this->form->a->b->c->d subform, and instead individually echo all of my elements in their apppropriate spots (like echo $this->form->a->b->c->d->element1 and echo $this->form->a->b->c->d->element2). This keeps my HTML out of the decorators which has its tradeoffs, but keeps my forms in ZF, which is all I want. With this solution, you can now call setElementsBelongsTo() on the d subform and use array notation to get the submission to behave properly, like so:
$objSubFormD->setElementsBelongTo('[a][b][c]').
Please be mindful that I've dumbed down these examples almost beyond practicality so the (dis)advantages may not be immediately clear for each one, I've only given what I perceive to be options and what I chose as a solution. I also feel my solution gives me the best upgrade path to ZF 2.0.
I'm currently using Zend_Filter_StripTags in a commenting system, but stuff kinda breaks when '<3' is entered. StripTags doesn't seem to be smart enough to realize that it's not an HTML tag, and creating the filter as "new Zend_Filter_StripTags(array('3'))" doesn't seem to work either.
Should I pass the input through a regexp first, or is there a way to get Zend_Filter_StripTags to straighten up and fly right?
Ended up writing a Zend_Filter class that was basically a wrapper for HTMLPurifier. Works perfectly, because HTMLPurifier is a LOT smarter than striptags.
I'm not familiar with Zend much, but if you want stuff like <3 to be allowed, just do htmlspecialchars instead of strip_tags on it.
What you want is Zend_Filter_HtmlEntites most likely.
See: Zend_Filter_HtmlEnties
The problem with htmlspecialchars and Zend_Filter_HtmlEntities is that if you're trying to strip out all html tags ( like 'a' and 'img', etc ), then instead of stripping them, you end up with that markup in your output.
Take comments on a blog for example. If you use htmlspecialchars or Zend_Filter_HtmlEntities, in a comment where someone tries to use html to enter a link you end up with that markup showing up when you display the comment. But if you use strip_tags or Zend_Filter_StripTags you end up mangling the comment, as neither is smart enough to realize that '<3' isn't a tag, and just strips everything from '<3' until the end of the comment ( or until it finds '>' ).
It would be nice if Zend had something like HTMLPurifier, where it actually checks and validates the input before stripping tags. This means that stuff like '<3' gets left alone, where as stuff like 'Awesome Site' becomes 'Awesome Site'.
This is a problem I'm trying to work around, and at the moment it seems like I'm going to end up writing my own Zend_Filter class that's basically a wrapper for HTMLPurifier.