Home | Wiki | OI 1.x Docs | OI 2.x Docs |
OpenInteract2::ContentGenerator::TT2Plugin - Custom OpenInteract functionality in templates
# Create the TT object with the OI plugin my $template = Template->new( PLUGINS => { OI => 'OpenInteract2::ContentGenerator::TT2Plugin' }, ... ); my ( $output ); $template->process( 'package::template', \%params, \$output );
# In the template (brief examples, see below for more) [% OI.show_all_actions.join( "\n" ) -%] [% OI.action_execute( 'error_display', error_msg = error_msg ) -%] [% OI.box_add( 'contact_tools_box', title = 'Contact Tools', weight = 2 ) -%] [% object_info = OI.object_description( object ) %] This is a [% object_info.name %] object. Is the object in the class? [% OI.class_isa( object, 'SPOPS::DBI' ) ? 'yes' : 'no' %] Is the SPOPS object writable? [% IF OI.can_write( object ) %]You're special![% END %] [% action = OI.action %] Action that called this template: [% action.name %] Security for action: [% action.security_level %] found, [% action.security_required %] required Properties of action: [% action_prop = action.properties %] [% FOREACH key = action_prop.keys %] [% key %] = [% action_prop.$key %] [% END %] Parameters of action: [% action_param = action.param %] [% FOREACH key = action_param.keys %] [% key %] = [% action_param.$key %] [% END %] Today is [% OI.date_format( 'now', '%Y-%m-%d %l:%M %p' ) %] the [% OI.date_format( 'now', '%j' ) %] day of the year [% d = OI.date_into_object( object.updated_on, '%Y-%m-%d' ) -%] [% OI.action_execute( 'date_select', month_value = d.month, day_value = d.day, year_value = d.year, blank = 1, field_prefix = 'updated_on' ) -%] [% OI.limit_string( object.description, 30 ) %] var person_last_name = '[% OI.javascript_quote( person.last_name ) %]'; [% OI.limit_sentences( news.news_item, 3 ) %] [% score = grade.score / test.total %] Your grade is: [% OI.percent_format( score ) %] You have [% OI.money_format( account.balance ) %] left to spend. Hello [% OI.uc_first( person.first_name ) %] <textarea name="news_item">[% OI.html_encode( news.news_item ) %]</textarea> Item: [% OI.html_decode( news.news_item ) %] # Works, but not as useful... [% edit_url = OI.make_url( BASE = '/User/show/', user_id = OI.login.user_id, edit = 1, show_all = 'yes' ) %] <a href="[% edit_url %]">Edit your information</a> # Preferred way to generate URLs for actions [% edit_url = OI.make_url( ACTION = 'user', TASK = 'show', user_id = OI.login.user_id, edit = 1, show_all = 'yes' ) %] <a href="[% edit_url %]">Edit your information</a> [% image_url = OI.make_url( IMAGE = '/images/foo.gif' ) %] <img src="[% image_url %]"> Take a look at that! [% static_url = OI.make_url( STATIC = '/generated/report-q1-2003.pdf' ) %] <a href="[% static_url %]">Latest report</a> [% theme = OI.theme_properties %] Background color of page: [% theme.bgcolor %] [% new_theme = OI.theme_fetch( 5 ) %] Background color of page from other theme: [% new_theme.bgcolor %] [% IF OI.logged_in -%] Hello [% OI.login.full_name %]. Your groups are: [% OI.login_group.join( ', ' ) -%] [% ELSE -%] You are not logged in. [% END -%] Your last search: [% OI.session.latest_search %] <a href="[% OI.return_url %]">Refresh</a> [% IF object.tmp_security_level >= OI.security_level.write -%] you can edit this object! [% END %]
This implements a Template Toolkit Plugin. For more information about plugins, see Template::Manual::Plugins.
Normally a plugin is instantiated like this:
[% USE OI %] [% object_info = OI.object_description( object ) %]
But since this plugin will probably be used quite a bit by OpenInteract template authors, it is always already created for you if you use the OpenInteract2::ContentGenerator::TT2Process module.
It can be used outside of the normal OpenInteract processing by doing something like:
my $template = Template->new( PLUGINS => { OI => 'OpenInteract2::ContentGenerator::TT2Plugin' } ); $template->process( $text, { OI => $template->context->plugin( 'OI' ) } ) || die "Cannot process template! ", $template->error();
This is done for you in OpenInteract2::ContentGenerator::TT2Process so you can simply do:
OpenInteract2::Setup->setup_static_environment_options(); OpenInteract2::ContentGenerator::TT2Process->initialize( CTX->server_config ); print OpenInteract2::ContentGenerator::TT2Process->handler( {}, { foo => 'bar' }, { name => 'mypkg::mytemplate' });
And everything works. (See OpenInteract2::ContentGenerator::TT2Process for more information.)
Most of the interesting information is in METHODS AND PROPERTIES.
The following OpenInteract properties and methods are available through this plugin, so this describes how you can interface with OpenInteract from a template.
show_all_actions()
You can get a listing of all actions available via the plugin by doing:
[% actions = OI.show_all_actions -%] [% actions.join( "\n" ) %]
action_param( $name )
Returns the value(s) for the parameter $name
in the action that
spawned this template process. If no action spawned the process
returns undef
.
The benefit this gives you above calling param
on the return value
for action()
is that multivalued parameters are returned in an
arrayref rather than an array. Zero or one values are returned by
themselves, everything else in an arrayref.
Example:
[% FOREACH error_msg = OI.action_param( 'error_msg' ) -%] Another error: [% error_msg %] [% END %]
action_execute( $name, \%params )
NOTE: This replaces the comp()
method from OI 1.x
Creates an action of name $name
and returns the output of
execute
. All the normal action rules apply.
Example:
[% OI.action_execute( 'error_display', error_msg = error_msg ) %]
See OpenInteract2::Action for more information about actions.
box_add( $box, \%params )
Adds a box to the list of boxes that will be processed by the 'boxes' component. (This is usually found in the 'base_main' template for your site.) You can add just a simple box name or parameters for the box as well. See the 'base_box' package for more information about boxes.
Examples:
[% OI.box_add( 'object_modify_box', object = news ) %]
[% OI.box_add( 'object_modify_box', object = news, title = 'Change it!', weight = 1 ) %]
object_description( $spops_object )
Returns a hashref with metadata about any SPOPS object. Keys of the
hashref are class
, object_id
(and oid
), id_field
, name
,
title
, url
, url_edit
. (See SPOPS for details about
what is returned.)
[% desc = OI.object_description( news ) %] [% IF news.tmp_security_level >= OI.security_level.write %] <a href="[% desc.url_edit %]">Edit</a> [% END %]
class_isa( $class|$object, $isa_class )
Returns a true value if $class
or $object
is a $isa_class
.
Example:
[% IF OI.class_isa( news, 'MySite::NewsCustom' ) %] [% news.display_custom_news() %] [% ELSE %] [% news.display_news() %] [% END %]
(Of course, this is a bad example since you would deal with this through your normal OO methods.)
can_write( $spops_object )
Returns true if the object is writeable by the current user, false if not.
action()
Returns the OpenInteract2::Action object that
called this template. If the template was called from a component or
using the generate_content()
method of the action object.
date_format( $date_string[, $format ] )
Formats the date from string $string
using the strftime format
$format
. If you do not supply $format
, a default of
%Y-%m-%e %l:%M %p
is used.
Examples:
[% mydate = '2000-5-1 5:45 PM' %] Date [% mydate %] is day number [% OI.date_format( mydate, '%j' ) %] of the year.
displays:
Date 2000-5-1 5:45 PM is day number 122 of the year.
and
Today is day number [% OI.date_format( 'now', '%j' ) %] of the year.
displays:
Today is day number 206 of the year.
For reference, here are supported strftime
formatting sequences
(cribbed from DateTime):
%% PERCENT %a day of the week abbr %A day of the week %b month abbr %B month %C century number (0-99) %d numeric day of the month, zero padded (01..31) %D MM/DD/YY (confusing for everybody but USA...) %e same as %d, space padded ( 1..31) %F %Y-%m-%d (ISO 8601 date) %g year corresponding to ISO week number w/o century (0-99) %G year corresponding to ISO week number %h same as %b %H hour, 24 hour clock, zero padded (00-23) %I hour, 12 hour clock, zero padded (01-12) %j day of the year (001-366) %k hour, 24 hour clock, space padded ( 0-23) %k hour, 12 hour clock, space padded ( 1-12) %m month number (01-12) %M minute (00-59) %n NEWLINE %N nanoseconds (%[3|6|9]N gives 3, 6, or 9 digits) %p AM or PM (or locale equivalent) %P %p in lowercase %r time format: 09:05:57 PM (%I:%M:%S %p) %R time format: 21:05 (%H:%M) %s seconds since the Epoch, UCT %S seconds (00-60) %t TAB %T time format: 21:05:57 (%H:%M:%S) %u weekday number, Monday = 1 (1-7) %U week number, Sunday as first day of week (00-53) %V week number, ISO 8601 (01-53) %w weekday number, Sunday = 0 (0-6) %W week number, Monday as first day of week (00-53) %y year (2 digits) %Y year (4 digits) %z timezone in ISO 8601 format (+0500, -0400, etc.) %Z timezone brief (PST, EST, etc.)
date_into_object( $date_string, [ $date_format ] )
Takes apart $date_string
and returns a DateTime
object. You can call a number of methods on this object to get
individual pieces of a date. (See the docs for
DateTime for a complete list.)
Note that you can pass 'now' or 'today' as $date_string
and get the
current time.
Example:
[% mydate = '2000-5-1 5:45 PM' %] [% dt = OI.date_into_object( mydate, '%Y-%m-%d %I:%M %p' ) %] Date: [% mydate %] Year: [% dt.year %] Month Num/Name: [% dt.month %] / [% dt.month_name %] Day/Name/of Year: [% dt.day_of_month %] / [% dt.day_name %] / [% dt.day_of_year %] Hour: [% dt.hour %] Minute: [% dt.minute %]
displays:
Date: 2000-5-1 5:45 PM Year: 2000 Month Num/Name: 5 / May Day/Name/of Year: 1 / Monday / 121 Hour: 5 Minute: 45
For reference, here are supported strptime
parsing sequences
(cribbed from
DateTime::Format::Strptime):
%% PERCENT %a day of the week abbr %A day of the week %b month abbr %B month %C century number (0-99) %d numeric day of the month (1..31) %D MM/DD/YY (confusing for everybody but USA...) %e same as %d %g year corresponding to ISO week number w/o century (0-99) %G year corresponding to ISO week number %h same as %b %H hour, 24 hour clock (0-23) %I hour, 12 hour clock (1-12) %j day of the year (1-366) %m month number (1-12) %M minute (0-59) %n whitespace %N nanoseconds %p AM or PM (or locale equivalent) %q time zone name from Olsen database %r time format: 09:05:57 PM (%I:%M:%S %p) %R time format: 21:05 (%H:%M) %s seconds since the Epoch, UCT %S seconds (0-60) %t whitespace %T time format: 21:05:57 (%H:%M:%S) %u weekday number, Monday = 1 (1-7) %U week number, Sunday as first day of week (0-53) %w weekday number, Sunday = 0 (0-6) %W week number, Monday as first day of week (0-53) %y year (2 digits) %Y year (4 digits) %z timezone in ISO 8601 format (+0500, -0400, etc.) %Z timezone brief (PST, EST, etc.)
limit_string( $string, $length )
Returns a string of max length $length
. If the function removes
information from the string, it appends '...' to the string. Note that
we currently do not try to be nice with word endings.
Example:
[% string = 'This is a really long news title and we have strict space constraints' %] [% OI.limit_string( string, 25 ) %]
displays:
This is a really long new...
javascript_quote( $string )
Performs necessary quoting to use $string
as Javascript
code. Currently this only involves escaping the "'" character, but it
can easily expand as necessary.
Example:
[% book_title = "it's nothing" %] var newArray = new Array( '[% OI.javascript_quote( book_title ) %]' );
displays:
var newArray = new Array( 'it\'s nothing' );
We could probably use a filter for this.
limit_sentences( $string, $num_sentences )
Limits $string
to $num_sentences
sentences. If the resulting
text is different -- if the function actually removes one or more
sentences -- we append '...' to the resulting text.
Example:
[% sentence_text = 'This is the first. This is the second. This is the third. This is the fourth.' %] Sentences: [% OI.limit_sentences( sentence_text, 2 ) %]
displays:
Sentences: This is the first. This is the second. ...
percent_format( $number[, $places ] )
Formats $number
as a percentage to $places
. If not specified
$places
defaults to '2'.
Example:
[% grade = 44 / 66 %] Grade: [% OI.percent_format( grade, 2 ) %]
displays:
Grade: 66.67%
money_format( $number[, $places ] )
Displays $number
as US dollars to $places
. If not specified,
$places
defaults to 2.
Example:
[% monthly_salary = 3000 %] [% yearly_salary = monthly_salary * 12 %] Your yearly salary: [% OI.money_format( yearly_salary, 0 ) %]
displays:
Your yearly salary: $36000
byte_format( $number )
Displays $number
as a number of bytes. If the number is less than
1024 it displays directly, between 1024 and 1024**2 as KB, between
1024**2 and 1024**3 as MB and greater than that as GB.
Example:
The file sizes are: [% OI.byte_format( 989 ) %] [% OI.byte_format( 2589 ) %] [% OI.byte_format( 9019 ) %] [% OI.byte_format( 2920451 ) %] [% OI.byte_format( 920294857 ) %] [% OI.byte_format( 3211920294857 ) %]
displays:
The file sizes are: 989 bytes 2.5 KB 8.8 KB 2.8 MB 877.7 MB 2991.3 GB
uc_first( $text )
Simply upper-case the first letter of the text passed in. Note that we do not do every word, just the first.
Example:
[% first_name = 'yahoo' %] Hi there, [% OI.uc_first( first_name ) %]
displays:
Hi there, Yahoo
html_encode( $text )
Encodes $text
so that it can be displayed in a TEXTAREA or in other
widgets.
Example:
[% news_item = "<p>This is the first paragraph</p>" %] <textarea name="news_item" cols="50" rows="4" wrap="virtual">[% OI.html_encode( news_item ) %]</textarea>
displays:
<textarea name="news_item" cols="50" rows="4" wrap="virtual"><p>This is the first paragraph</p></textarea>
html_decode( $text )
Decodes $text
with HTML entities to be displayed normally.
Example:
[% news_item = '<p>This is the first paragraph</p>' %] [% OI.html_decode( news_item ) %]
displays:
<p>This is the first paragraph</p>
make_url( \%params )
Creates a URL given a number of parameters, taking care to perform any
necessary transformations. See the create()
, create_image()
and
create_static()
methods of OpenInteract2::URL
for what this means.
Parameters:
All parameters except those listed below are assumed to be used as GET keys and values and will be appended to the URL appropriately.
To specify a URL to an OI resource you can use one of two methods:
BASE: The base for the URL. This is normally what gets transformed with a location prepended to it or a session tag appended (or whatever). (Compatibility Note: In OI 1.x this was 'base' instead.)
Examples:
[% user_show_url = OI.make_url( BASE = '/User/show/', user_id = user.user_id ) %] <a href="[% user_show_url %]">blah</a>
displays (when under the normal location of '/'):
<a href="/User/show/?user_id=5">blah</a>
displays (when under a different location '/oi'):
<a href="/oi/User/show/?user_id=5">blah</a>
The second method, preferred for generating URLs to actions, is a combination of:
ACTION: The action to which the task and parameters are being sent. This should exist in the action table -- if it doesn't no URL is returned.
TASK: The optional task in the action to which the parameters are being sent. If unspecified the URL will wind up going to the default task for the action.
Examples, assuming that the 'user' task is mapped to the '/User' URLspace.
[% user_show_url = OI.make_url( ACTION = 'user', TASK = 'show', user_id = user.user_id ) %] <a href="[% user_show_url %]">blah</a>
displays (when under the normal location of '/'):
<a href="/User/show/?user_id=5">blah</a>
displays (when under a different location '/oi'):
<a href="/oi/User/show/?user_id=5">blah</a>
You can also create URLs for images and static resources:
IMAGE: Specifies the image URL to which the image deployment context gets prepended.
STATIC: Specifies the static URL to which the static deployment context gets prepended.
If you do not specify either BASE
or ACTION
and TASK
, a
javascript URL is returned that alerts you to your error. (Note: this
may change...)
page_title( $title )
Set the HTML title for the top-level page. This isn't used as often as
other directives, but like use_main_template
below it can come in
very handy.
Example:
[% username = OI.login.full_name; OI.page_title( "Personalized Astrology Reading for $username" ); %]
use_main_template( $template_name )
Tell OpenInteract to use a particular main template. The
$template_name
should be in 'package::name' format.
Example:
[% OI.use_main_template( 'mypkg::main' ) -%]
theme_fetch( $new_theme_spec, \%params )
Retrieves the properties for theme $new_theme_spec
, which can be an
ID (normal) or a name listed in the 'default_objects' of your server
configuration. If the latter we'll use the ID associated with that
name.
If the key set_for_request
is set to 'yes' in \%params
then this
new theme will be used for the remainder of the request. This includes
the main template along with all graphical elements.
Returns: hashref with all properties of the given theme.
Examples:
[% new_theme = OI.theme_fetch( 5 ) %] Background color of page from other theme: [% new_theme.bgcolor %] [% new_theme = OI.theme_fetch( 5, set_for_request = 'yes' ) %] Background color of page from other theme: [% new_theme.bgcolor %] Hey, the new theme is now set for the rest of the request!
theme_properties()
A hashref with all the properties of The current theme. You will probably use this a lot.
Example:
[% theme = OI.theme_properties %] <tr bgcolor="[% theme.head_bgcolor %]">
The exact properties in the theme depend on the theme. See the 'base_theme' package for more information.
login()
The user object representing the user who is currently logged in.
Example:
[% login = OI.login %] <p>Hi [% login.full_name %]! Anything new?</p>
login_group()
An arrayref of groups the currently logged-in user belongs to.
Example:
[% login_group = OI.login_group %] <p>You are a member of groups: [% FOREACH group = login_group %] [% th.bullet %] [% group.name %]<br> [% END %] </p>
logged_in()
True/false determining whether the user is logged in or not.
Example:
[% IF OI.logged_in %] <p>You are very special, logged-in user!</p> [% END %]
is_admin()
True/false depending on whether the user is an administrator. The definition of 'is an administrator' depends on the authentication class being used -- by default it means that the user is the superuser or a member of the 'site admin' group. But you can modify this based on your needs, and make the result available to all templates with this property.
Example:
[% IF OI.is_admin %] <p>You are an administrator -- you have the power! It feels great, eh?</p> [% END %]
session()
Contains all information currently held in the session. Note that other handlers may during the request process have modified the session. Therefore, what is in this variable is not guaranteed to be already saved in the database. However, as the request progresses OpenInteract will sync up any changes to the session database.
Note that this information is read-only. You will not get an error if you try to set or change a value from the template, but the information will persist only for that template.
Example:
[% session = OI.session %] <p>Number of items in your shopping cart: [% session.num_shopping_cart_items %]</p>
return_url()
What the 'return url' is currently set to. The return url is what we come back to if we have to do something like logout.
<a href="[% OI.return_url %]">Logout and return to this page</a>
Note that this should be an absolute URL -- you should be able to plug it directly into a tag without worrying about the server context.
security_level()
A hashref with keys of 'none', 'read', and 'write' which gives you the value used by the system to represent the security levels.
Example:
[% IF obj.tmp_security_level < OI.security_level.write %] ... do stuff ... [% END %]
security_scope()
A hashref with the keys of 'user', 'group' and 'world' which gives you
the value used by the system to represent the security scopes. This
will rarely be used but exists for completeness with
security_level
.
[% security_scope = OI.security_scope %] [% FOREACH scope = security_scope.keys %] OI defines [% scope %] as [% security_scope.$scope %] [% END %]
server_config()
Returns the server configuration object (or hashref) -- whatever is returned by calling in normal code:
CTX->server_config; The ID of the site admin group is: [% OI.server_config.default_objects.site_admin_group %]
None known.
Custom plugins
Make it easy for websites to create their own plugins that can be accessed through the 'OI.' plugin. For instance, a package owner could define a set of additional behaviors to go along with a package. In a file distributed with the package, the plugins could be listed:
conf/template_plugins.dat: ------------------------------ OpenInteract2::Plugin::MyPackage1 OpenInteract2::Plugin::MyPackage2 ------------------------------
And stored within the server-wide configuration object. Then when we
call load()
in this plugin, we could do something similar to the
_populate
method in Slash::Display::Plugin::Plugin
where we peek
into the @EXPORT_OK
array and copy the code refs into a hash which
we can then check via AUTOLOAD
.
One problem with that is name collision -- two packages might both define a 'do_stuff' action, and in this case the last one would win. No good.
Maybe we prepend the package name to the action? Also no good -- the whole idea is to make the template environment transparent....
Template::Plugin::URL for borrowed code
Slashcode (http://www.slashcode.com) for inspiration
Copyright (c) 2002-2003 Chris Winters. All rights reserved.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Chris Winters <chris@cwinters.com>
Generated from the OpenInteract 1.99_03 source.