How to add functionality to CMS Made Simple using Tags, User-Defined Tags, and Modules. Also includes some previews of how the module API will change with version 2.0
2. Jeff Bosch
● Core Development Team member
● B.S. in Computer Science
● Started A & J Progamming in 2007 for
custom web programming and
implementation
3. Samuel Goldstein
● Core Development Team member since 2004
● Principal at 1969 Communications
● Background
● Programming since 1980, starting with TRS-80
● Aerospace in the '90s
● Dot-com roller coaster
● Hey! Buy my book!
● CMS Made Simple Developer's Cookbook from Packt Publishing
4. OK, enough of that
● Why extend CMS Made Simple?
● Add functionality
● Make things easier for your clients
● More money for you
● Fame, fortune, glory
5. Ways to Extend CMSMS
● Core, core modules, and Smarty
● User-Defined Tags
● Tags (a.k.a. Plugins)
● Modules
6. How do I decide on an
approach?
● There is not always an “absolute best”
approach
● Don't neglect non-technical
considerations (e.g., your specific users)
● The following chart may also help
7. Approaches
Smarty Tag UDT Module
No installation required √ √
Multiple actions √* √
Create databases / preferences √* √
Act as Smarty modifier √
Help displayed in Admin area √ √
Admin panel √
Post on Developer's Forge, share via Module √
Manager
Localization/Translation √
8. Let's get started!
● Build a Google Site Map using Core and
Core Modules
● We'll use Menu Manager in a hidden page
● We'll create a custom Menu Manager
template
● And a mod_rewrite trick
10. Calling the Template
● Create page named “sitemap”
● Set alias to “sitemap” too
● Uncheck “Show in Menu”
● Insert tag into your page content:
{menu template='sitemap' show_all='1' collapse='0'}
12. Test it!
● Go to http://yoursite.com/sitemap.xml
<?xml version="1.0" encoding="UTF-‐8"?>
<urlset xmlns="hRp://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>hRp://cms_book.viajante/</loc>
<lastmod>2009-‐05-‐13T10:12:18-‐08:00</lastmod>
</url>
<url>
<loc>hRp://cms_book.viajante/index.php?page=how-‐cmsms-‐works</loc>
<lastmod>2009-‐05-‐12T20:11:52-‐08:00</lastmod>
</url>
…
</urlset>
13. OK, how about a Tag?
● Only tags can serve as Smarty modifiers
● Here's a tag that vigorously defends our
intellectual property!
● Appends a ® symbol to every instance of
“CMS Made Simple” in page content.
17. OK, how about a UDT?
● UDTs can do all sorts of things:
● Talk to the database
● Talk to modules
● Deal with events
● Interact with Smarty
● Let's try a few of those things!
18. UDT “pagecounter”
global $gCms;
$db = $gCms-‐>GetDb();
$count = $db-‐>GetOne('select count(*) from '.cms_db_prefi x().'content where acQve=1');
$smarty = $gCms-‐>GetSmarty();
$smarty-‐>assign('page_count','Total pages: '.$count);
19. Then, add a content page
● Set the title and menu text
● In the content, call the UDT with
{pagecounter}
● And output the Smarty variable with
{$page_count}
21. Exercise I
● What approach would you use to implement each
of the following?
● Convert your page content into Pirate Speak
● A form for users to submit movie reviews, with an
Admin panel allowing the site maintainer to approve
or reject reviews for display
● Putting the title of the most-recently added page into
a Smarty variable
22. Exercise I, cont.
● Display a special image file only on the site's
home page
● Display the Admin account email address on a
page (but obscured to prevent spammers
from harvesting it)
● Display a poll, and show the results after the
user votes
● Display links to all pages that are below the
current page in the site hierarchy
23. Exercise II
● Create a UDT for changing site layout
seasonally.
● Set a variable which can be used to change
the stylesheet classes of the site.
● For simplicity, call January-March “winter,”
April-June “spring,” July-September
“summer,” and October-December
“autumn.”
24. Exercise II, cont. UDT
global $gCms;
$month = date('n'); // returns month as number between 1 and 12, inclusive
$smarty = $gCms-‐>GetSmarty();
if ($month < 4)
$season = 'winter';
else if ($month < 7)
$season = 'spring';
else if ($month < 10)
$season = 'summer';
else
$season = 'autumn';
$smarty-‐>assign('season', $season);
28. Getting Started with Modules
● For the 1.x series, several ways to get
started
● From scratch
● Skeleton module
● Module Maker
● MCFactory
● etc
29. Skeleton Module
● Download from Forge or Module
Manager
● Has simple functionality
● install/upgrade
● admin panel
● database routines
● form API calls
30. Skeleton Module, cont.
● Once you've installed, edit the files to
adapt to your own purposes
● Well commented
● Somewhat dated: last updated for CMS
MS 1.6.5
● Still has correct structure, but may lack
more recent improvements and features
31. Structure of a 1.x module
● Modules extend the CMSModule class
● Magic of OO:
● Automatically inherits a lot of functionality
(e.g., Database and Form APIs, Smarty,
Translation, etc)
● Most methods already inherit acceptable
defaults
32. Minimal 1.x Module
● File lives in
$CMS_ROOT/modules/module_name
● Filename is module_name.module.php
● Module class must match file name
● Need to implement 3 methods:
● GetName
● DoAction
● IsPluginModule
33. Minimal 1.x module, cont.
● GetName simply returns module name;
must match class and filename
● IsPluginModule returns boolean.
● DoAction is, unsurprisingly, where the
real action takes place
34. DoAction
● Called with a few parameters:
● $action, “reason for calling.” Two built-in:
“default” and “defaultadmin”
● $id, a prefix for use in forms
● $params, a hash of parameters
● $returnid, reference to the page containing
the tag
35. Other important methods
● Install, upgrade, uninstall. These methods
called as expected, and allow for
housekeeping
● SetParameters. Sets up parameter
filtering, URL routes,
● Lang. Translates strings.
36. Minimal 1.x module, cont.
● For performance reasons, methods are
split out into multiple files
● String translations are stored in external
files
● Templates may be stored as files or in the
database
38. Enough Abstraction!
● We will create a basic module that
demonstrates core APIs
● “Quotations Module” requirements:
● Presents form to user, handles input safely
● Displays random quotation to user
● Allows admin to delete records
45. Consider parameters
● Form will submit quotation and author
● Viewing will require quotation_id
● Module will also be a plugin module, so
we want to give it its own tag {quotation}
● Let's create SetParameters method
48. OK, let's get serious.
● Need to create the form
● Need to handle the inputs
● This will be the module's default action
● Create action.default.php
53. Update our lang file
<?php
$lang['friendlyname']='QuotaQon Module';
$lang['Qtle_author']='QuotaQon Author';
$lang['Qtle_quotaQon']='QuotaQon';
$lang['submit']='Submit';
$lang['help_quotaQon_id']='ID for a specific quotaQon';
$lang['help_author']='QuotaQon author';
$lang['help_quotaQon']='QuotaQon text';
$lang['help']='This module is for the presentaQon of quotaQons.';
?>
55. Input validation
Added to top of action.default.php
if (isset($params['submit']))
{
if (empty($params['author']) || empty($params['quotaQ on']))
{
$smarty-‐>assign('message',$this-‐>Lang('error_empty_fi elds'));
}
}
Added to user_form.tpl
{if isset($message) && $message!=''}<div class="error">{$message}</div>{/if}
71. OK, let's add an admin panel
● First, we need to add a permission to
control access
● This should be done in the installer
● Steps:
● Change installer
● Bump the module version number
● Create the upgrade method
73. method.upgrade.php
<?php
if (!isset($gCms)) exit;
switch($old_version)
{
case "0.1":
$this-‐>CreatePermission('Manage QuotaQons', 'Manage QuotaQons');
}
$this-‐>Audit( 0, $this-‐>Lang('friendlyname'), $this-‐>Lang('upgraded',$this-‐>GetVersion()));
?>
Added to lang file:
$lang['upgraded']='Upgraded to version %s';
81. Be kind to users
● Add some safety – modify default admin
link to delete
$row['delete'] = $this-‐>CreateLink($id, 'admin_delete', '',
$this-‐>Lang('delete'), array('quotaQon_id'=>$row['quotaQon_id']),
$this-‐>Lang('really_delete',$row['author']));
● And add to language file
$lang['really_delete']='Really delete this quotaQon by %s?';
83. Let admin edit quotations
● We can re-use the form template
● Just need to create the admin-side logic
● Note that the logic is not identical, since
we'll be updating the database rather than
adding a new record
84. action.admin_edit.php
<?php
if (!isset($gCms)) exit;
if (!$this-‐>CheckPermission('Manage QuotaQ ons')) exit;
$db = $this-‐>GetDb();
if (isset($params['submit']))
{
if (empty($params['author']) || empty($params['quotaQ on']))
{
$smarty-‐>assign('message',$this-‐>Lang('error_empty_fi elds'));
}
else
{
$res = $db-‐>Execute('update '.cms_db_prefi x().'module_quotaQons set author=?,quotaQon=? where quotaQon_id=?',
array($params['author'],$params['quotaQ on'],$params['quotaQon_id']));
if ($res === false)
{
$smarty-‐>assign('message',$this-‐>Lang('db_error',$db-‐>ErrorMsg()));
}
else
{
$smarty-‐>assign('message',$this-‐>Lang('quotaQ on_edited'));
}
return $this-‐>DoAcQon('defaultadmin', $id, $params, $returnid);
}
}
else