Django template philosophy shares quite a bit with Chunk. I just came across this nugget on the Django website where they describe the design decisions that went into their templating framework:
Separate logic from presentation
We see a template system as a tool that controls presentation and presentation-related logic – and that’s it. The template system shouldn’t support functionality that goes beyond this basic goal.
If we wanted to put everything in templates, we’d be using PHP. Been there, done that, wised up.
Couldn’t agree more.
Discourage redundancy
The majority of dynamic Web sites use some sort of common sitewide design – a common header, footer, navigation bar, etc. The Django template system should make it easy to store those elements in a single place, eliminating duplicate code.
This is the philosophy behind template inheritance.
Agreed. Chunk gets this done with “exec” and “include” but, same idea.
Be decoupled from HTML
The template system shouldn’t be designed so that it only outputs HTML. It should be equally good at generating other text-based formats, or just plain text.
Absolutely. I use Chunk all the time for templating plain-text e-mail, JSON, CSV, config files, XML etc.
XML should not be used for template languages
Using an XML engine to parse templates introduces a whole new world of human error in editing templates – and incurs an unacceptable level of overhead in template processing.
I think this is a dig at XSLT and funny XML-based templating solutions like Thymeleaf. I never understood the appeal of these either.
Assume designer competence
The template system shouldn’t be designed so that templates necessarily are displayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe of a limitation and wouldn’t allow the syntax to be as nice as it is. Django expects template authors are comfortable editing HTML directly.
Hear hear. Chunk keeps both options open, however. A file full of snippets probably won’t open in DreamWeaver but if you stay away from snippets and define one template per file, you should be able to use just about any HTML Editor out there.
Treat whitespace obviously
The template system shouldn’t do magic things with whitespace. If a template includes whitespace, the system should treat the whitespace as it treats text – just display it. Any whitespace that’s not in a template tag should be displayed.
Okay, so here I disagree. If you don’t do some “smart” handling of whitespace, your template gets contorted and unreadable when you actually do care about the whitespace in the final output.
Don’t invent a programming language
The template system intentionally doesn’t allow the following:
- Assignment to variables
- Advanced logic
The goal is not to invent a programming language. The goal is to offer just enough programming-esque functionality, such as branching and looping, that is essential for making presentation-related decisions.
The Django template system recognizes that templates are most often written by designers, not programmers, and therefore should not assume Python knowledge.
Wow. Couldn’t have put it better myself. This is what Chunk is all about. If you want to write code in your templates, go use PHP or JSP. Knock yourself out. But man, your templates are ugly and your whole team is going to suffer headaches from looking cross-eyed at your mishmosh code.
Safety and security
The template system, out of the box, should forbid the inclusion of malicious code – such as commands that delete database records.
This is another reason the template system doesn’t allow arbitrary Python code.
Bingo.
Extensibility
The template system should recognize that advanced template authors may want to extend its technology.
This is the philosophy behind custom template tags and filters.
Chunk is similarly extensible: write your own filters, make your own tag-command protocols.
Simple, powerful templates for Java
Q: Does the Java community really need yet another templating engine?
A: Not really, but back when I started Chunk, there wasn’t anything else out there like it. Now that it has matured, I am releasing it into the wild, and if somebody finds it useful, great!
Click below for an introduction to better code/layout separation:
http://www.x5software.com/chunk/
Features:
- Macros, Includes and Conditional Includes.
- Flexible null-handling; template designer may specify default tag values.
- Library of powerful predefined in-tag filters, including regex (regular expressions), sprintf.
- Expose a subset of obj methods to template with a single line of code.
- Define multiple snippets per template file.
- Support for theme layers with inheritance.
- Highly optimized codebase.
- Hooks for extending.
- Localization framework.
- Eclipse Template Editor plugin available with syntax highlighting & more.
Visit the Chunk project home on Google Code to download the Chunk Templates jar and get started.
I don’t know if Chunk is better than Velocity, I don’t know if Chunk is better than FreeMarker, but I’ve been using it for years and it’s gotten pretty cool.
Hackers are encouraged to contribute enhancements back to the community. Google is hosting the code on its SVN server so it’s easy to check out a copy of the source and make whatever improvements you need.
Ah, open source. The Magento core codebase, layouts and templates are right there, warts and all, just daring you to give in to temptation and ignore the “do not edit this file!” warning at the top of each distributed file. We all know the guilty pleasure of instant gratification that comes with tweaking a word, or a layout, or a core class directly in the source and seeing our fix immediately on the site. It seems especially rewarding after the hour or two it took just to hunt down the right cog in The Machine. And really, who has time to learn entire frameworks and build a module, just to tweak the way a breadcrumb gets output?
But then it’s 500 (or 5,000!) lines of “little tweaks” later and you need to upgrade. And you’re screwed. And a couple extra xml files and a separate tree of folders and files doesn’t seem like such a bad idea anymore.
Well, okay, time to roll up your sleeves and learn this durn extension framework that the brainiacs at Varien/Magento have so lovingly constructed.
Layouts and Templates and Blocks, Oh My
classyllama.com has a great article on how to modify one or two things in a core layout without (1) modifying it directly in core or (2) having to make a copy of the whole layout file into your theme just to tweak one line:
http://classyllama.com/development/magento-development/the-better-way-to-modify-magento-layout/
Now that I understand this layout stuff, I’m doing a lot less messing around directly in theme templates. By the way, if you are editing the factory-supplied Magento templates and layouts directly, for shame! Set up a theme and make all your changes in the theme.
Update: another great article on navigating the Magento layout framework:
http://alanstorm.com/layouts_blocks_and_templates
OO PHP? Isn’t that like oil and water?
The article linked below offers a lucid explanation of how to roll your own modules that extend the core Model, Controller, Resource, and Block classes (it’s a little different for each case) to override the core behavior in Magento. Not for beginners, you really need to have a handle on OO programming. Again, this is cool because you don’t have to edit a core file directly (where changes will get blown away in an upgrade) and you don’t have to copy the whole file just to tweak one function. The latter strategy prevents you from reaping the benefits of any bugfixes or new features in that file in the next upgrade, and could even cause serious problems/bugs as your copy gets out of sync with the core codebase.
http://prattski.com/2010/06/24/magento-overriding-core-files-blocks-models-resources-controllers/
For some reason that comprehensive article does not include instructions for overriding a function in a helper class (yet another special case). This article has an example for that:
http://blog.chapagain.com.np/magento-block-controller-model-helper-override/
Happy coding!
CSS officially needs to be replaced. Centering a dropdown menu should NOT be this hard:
http://matthewjamestaylor.com/blog/centered-dropdown-menus
Thank goodness I found that article or I would still be pulling my hair out.
In my day, used to be you could stick this in one or two tables and you were done. We didn’t have no stinkin’ separation of content and layout and we liked it.
We had a legacy order fulfillment library written in Perl, so although accessing the API is extremely easy in PHP, when we migrated to Magento I had to figure out how to connect to the SOAP API from Perl.
Turns out the most popular CPAN module for doing SOAP in Perl (SOAP::Lite) is not particularly fun to use (see “State of the SOAP” at http://www.soaplite.com/ for a three-year-old call for volunteers to refactor).
Nevertheless, I did eventually emerge victorious. There may be a much easier way but after a lot of head-scratching and trial and error, this worked for me, YMMV.
The soapify routine was stolen from this page:
http://www.soaplite.com/2004/01/building_an_arr.html
Many thanks to soapify author Sandeep Satavlekar.
For passing the filter args to sales_order.list, I had to make the call in PHP first and then reverse-engineer the encoding of the nested array that actually got passed. There may be a way to get SOAP::Lite to encode nested arrays like this by default (or encode nested arrays in some other standard SOAPy way that Magento would also accept) but I chose not to waste any more time on this than I already had.
Enjoy!
UPDATE: Was getting sporadic “Access Denied” errors. Turns out you can fix this just by turning on cookies. Apparently this only affects you if Magento is using DB sessions. See new get_soap_session below for how to turn on cookies.
UPDATE TO THE UPDATE: Nah, that didn’t fix it. Still searching for a fix… runs fine in a session, fails about 80% of the time from cron.
The complete working example script is after the jump...
#!/usr/bin/perl
# replace these values with the soap account you set up in the admin
my $user = 'username';
my $pass = 'password';
# replace with your domain and path (we installed magento at /shop/)
my $soap_url = 'http://YOURDOMAIN/MAGENTO_PATH/index.php/api/index/index/';
my ($soap,$session_id) = &get_soap_session($user,$pass,$soap_url);
# simple example (one arg of type string)
my $oid = '1000001';
my $order = &get_order($soap,$session_id,$oid);
# gnarly example (argument is nested arrays)
my $orders = &get_recent_invoiced_orders($soap,$session_id);
foreach my $ord (@$orders) {
my $due = $ord->{grand_total};
my $paid_or_authorized = $ord->{total_invoiced};
my $owed = $due - $paid_or_authorized;
# ignore if not yet paid
next if ($owed > .02);
&fulfill_order($ord);
}
exit 0;
Continue reading »