Extending CMS Made Simple
-
Upload
cmsmssjg -
Category
Technology
-
view
18.711 -
download
2
description
Transcript of Extending CMS Made Simple
Extending CMS Made SimplePresented by
Jeff Bosch and Samuel Goldstein
Jeff Bosch
● Core Development Team member● B.S. in Computer Science● Started A & J Progamming in 2007 for
custom web programming and implementation
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
OK, enough of that
● Why extend CMS Made Simple?● Add functionality● Make things easier for your clients● More money for you● Fame, fortune, glory
Ways to Extend CMSMS
● Core, core modules, and Smarty● User-Defined Tags● Tags (a.k.a. Plugins)● Modules
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
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 √
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
Menu Manager Template
<?xml version="1.0" encoding="UTF-‐8"?><urlset xmlns="hRp://www.sitemaps.org/schemas/sitemap/0.9">{if $count > 0}{foreach from=$nodelist item=node} <url> <loc>{$node-‐>url|escape:'html'}</loc> <lastmod>{$node-‐>modified|date_format:'%Y-‐%m-‐%dT%T-‐08:00'}</lastmod> </url>{/foreach}{/if}</urlset>
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'}
<IfModule mod_rewrite.c>RewriteEngine on#Sub-‐dir e.g: /cmsmsRewriteBase /RewriteCond %{REQUEST_FILENAME} !-‐f [NC]RewriteCond %{REQUEST_FILENAME} !-‐d [NC]RewriteRule ^sitemap.xml$ index.php?page=sitemap&showtemplate=false [L]</IfModule>
Add an .htaccess file
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>
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.
postfilter.registeredtrademarker.php
<?phpfuncQon smarty_cms_posPilter_registeredtrademarker($tpl_output, &$smarty){
global $gCms;$result = explode(':', $smarty-‐>_current_file);
if (count($result) > 0){
if ($result[0] == 'content'){$tpl_output = str_replace('CMS Made Simple','CMS Made Simple®', $tpl_output);}
}return $tpl_output;
}?>
Using the Filter
● Save your filter in the plugins directory● In the Admin, be sure to clear your
cache!● View your site.
You® filte®ed ®esults
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!
UDT “pagecounter”
global $gCms;
$db = $gCms-‐>GetDb();
$count = $db-‐>GetOne('select count(*) from '.cms_db_prefix().'content where acQve=1');
$smarty = $gCms-‐>GetSmarty();$smarty-‐>assign('page_count','Total pages: '.$count);
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}
Viewing your page
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
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
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.”
Exercise II, cont. UDTglobal $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);
Exercise II, cont. Template.{process_pagedata}<!DOCTYPE html PUBLIC "-‐//W3C//DTD XHTML 1.0 TransiQonal//EN" "hRp://www.w3.org/TR/xhtml1/DTD/xhtml1-‐transiQonal.dtd"><html xmlns="hRp://www.w3.org/1999/xhtml" xml:lang="en" ><head><Qtle>{sitename} -‐ {Qtle}</Qtle>{metadata}{cms_stylesheet}{season}</head><body><div id="header"><h1 class=”{$season}”>{sitename}</h1></div><div id="menu">{menu}</div><div id="content" class=”{$season}”> <h1>{Qtle}</h1> {content}</div></body></html>
Exercise II, cont. CSS
.winter {background-‐color: #bfc4ff;}
.spring {background-‐color: #bfffce;}
.summer {background-‐color: #fffabf;}
.autumn {background-‐color: #ffcabf;}
#header h1.summer {background: url(/uploads/images/beach.jpg);}
Hour IIHow's my timing?
Getting Started with Modules
● For the 1.x series, several ways to get started● From scratch● Skeleton module● Module Maker● MCFactory● etc
Skeleton Module
● Download from Forge or Module Manager
● Has simple functionality● install/upgrade● admin panel● database routines● form API calls
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
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
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
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
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
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.
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
Layout on filesystem
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
Step 1. Preparation
● Create directories● $CMS_ROOT/modules/Quotations● Quotations/templates● Quotations/lang
● Create base files:● Quotations.module.php● lang/en_US.php
Quotations.module.php<?phpclass QuotaQons extends CMSModule
{funcQon GetName()
{return 'QuotaQons';}
funcQon GetFriendlyName(){return $this-‐>Lang('friendlyname');}
funcQon IsPluginModule(){return true;}
funcQon GetVersion(){return '0.1';}
}?>
lang/en_US.php<?php$lang['friendlyname']='QuotaQon Module';?>
Database Schema
● We'll probably need● Unique ID● Quotation text● Quotation author● Submission date
method.install.php<?phpif (!isset($gCms)) exit;
$db = $this-‐>GetDb();$dict = NewDataDicQonary( $db );
$fields="quotaQon_id I KEY,quotaQon X,author C(80),submit_date DT
";
$sqlarray = $dict-‐>CreateTableSQL( cms_db_prefix()."module_quotaQons",$fields);$dict-‐>ExecuteSQLArray($sqlarray);
$db-‐>CreateSequence(cms_db_prefix()."module_quotaQon_seq");?>
Install it
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
SetParameters()funcQon SetParameters()
{$this-‐>RegisterModulePlugin();$this-‐>RestrictUnknownParams();$this-‐>CreateParameter('quotaQon_id','null',$this-‐>Lang('help_quotaQon_id'));$this-‐>SetParameterType('quotaQon_id', CLEAN_INT);$this-‐>CreateParameter('author','anonymous',$this-‐>Lang('help_author'));$this-‐>SetParameterType('author',CLEAN_STRING);$this-‐>CreateParameter('quotaQon','',$this-‐>Lang('help_quotaQon'));$this-‐>SetParameterType('quotaQon',CLEAN_STRING);$this-‐>CreateParameter('submit');$this-‐>SetParameterType('submit',CLEAN_STRING);}
funcQon GetHelp(){return $this-‐>Lang('help');}
Viewing Module Help
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
action.default.php<?phpif (!isset($gCms)) exit;
$smarty-‐>assign('form_start',$this-‐>CreateFormStart($id, 'default', $returnid));
$smarty-‐>assign('input_author',$this-‐>CreateInputTextWithLabel($id, 'author',isset($params['author'])?$params['author']:'', 10, 80, '',$this-‐>Lang('Qtle_author')));
$smarty-‐>assign('Qtle_quotaQon',$this-‐>Lang('Qtle_quotaQon'));
$smarty-‐>assign('input_quotaQon',$this-‐>CreateTextArea(false, $id,isset($params['quotaQon'])?html_enQty_decode($params['quotaQon'],ENT_QUOTES):'',
'quotaQon'));
$smarty-‐>assign('submit',$this-‐>CreateInputSubmit($id, 'submit', $this-‐>Lang('submit')));
echo $this-‐>ProcessTemplate('user_form.tpl');?>
user_form.tpl<div class="quotaQon_form">
{$form_start}<div>{$input_author}</div><div>{$Qtle_quotaQon}<br />{$input_quotaQon}</div><div>{$submit}</div></form>
</div>
Add the tag to a page
View the page
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.';?>
And check again
Input validation
if (isset($params['submit'])){if (empty($params['author']) || empty($params['quotaQon']))
{$smarty-‐>assign('message',$this-‐>Lang('error_empty_fields'));}
}
Added to top of action.default.php
Added to user_form.tpl
{if isset($message) && $message!=''}<div class="error">{$message}</div>{/if}
Try an empty submit
Store to databaseif (isset($params['submit']))
{if (empty($params['author']) || empty($params['quotaQon']))
{$smarty-‐>assign('message',$this-‐>Lang('error_empty_fi elds'));}
else{$db = $this-‐>GetDb();$quotaQon_id = $db-‐>GenID(cms_db_prefix(). 'module_quotaQon_seq');$res = $db-‐>Execute('insert into '.cms_db_prefi x().
'module_quotaQons (quotaQon_id,author,quotaQon,submiRed_date) values (?,?,?,NOW())',array($quotaQon_id,$params['author'],$params['quotaQon']));
if ($res === false){$smarty-‐>assign('message',$this-‐>Lang('db_error',$db-‐>ErrorMsg()));}
else{$smarty-‐>assign('message',$this-‐>Lang('added'));}
}}
Test it – add a quotation
action.display.php<?phpif (!isset($gCms)) exit;
$db=$this-‐>GetDb();$row = array();$res = $db-‐>Execute('select * from '.cms_db_prefix().
'module_quotaQons order by rand() limit 1');
if ($res && $row=$res-‐>FetchRow()){$smarty-‐>assign('quotaQon',$row);}
echo $this-‐>ProcessTemplate('display_quotaQon.tpl');?>
display_quotation.tpl<dl>
<dd>{$quotaQon.quotaQon}</dd><dt>{$quotaQon.author}</dt>
</dl>
Add the tag to page template
● Find a convenient spot● Add the tag:{QuotaQons acQon='display'}
Try it!
2.0 Module API2.0 Module Extensions:
Database:create_table($table, $fields)create_index($table, $name, $field)drop_table($table)
Preference: get($preference_name, $default_value = '')set($preference_name, $value)remove($preference_name = '')
Template: get_list($template_type = '')get($template_type, $template_name)get_from_file($template_name)set($template_type, $template_name, $content, $default = null)delete($template_type = '', $template_name = '')process_from_data( $data )process_from_database($template_type, $template_name = '', $id = '', $return_id = '',
$designaQon = '', $cache_id = '')process($template_name, $id = '', $return_id = '', $designaQon = '', $cache_id = '')
method.install.php<?phpif (!isset($gCms)) exit;
$this-‐>Database-‐>create_table('module_quotaQons', "quotaQon_id I KEY AUTO,language C(8),quotaQon X,author C(80),submiRer C(80),submit_date DT
");
$this-‐>Database-‐>create_index('module_quotaQons','Author', 'author');
$this-‐>Template-‐>set('summary', 'Default Template', $this-‐>Template-‐>get_from_file('orig_default_summary'));
$this-‐>Preference-‐>set('sort_by','author');
$this-‐>Permission-‐>create('Manage QuotaQons' );
?>
2.0 Module API2.0 Module Extensions (Group 2)
Permission:create($permission_name, $extra_attr = '', $hierarchical = false, $table = '')check($permission_name, $extra_attr = '', $hierarchical = false, $table = '')remove($permission_name, $extra_attr = '')
Form:form_start($params = array(), $check_keys = false)form_end input_text input_hidden input_checkbox input_submitinput_select input_options input_textarea
Redirect:module_url
Url:link content_linkreturn_link
action.default.php<?phpif (!isset($gCms)) exit;
$smarty-‐>assign('form_start',$this-‐>Form-‐>form_start(array('acQon'=>'default','return_id'=>$returnid)) );
$smarty-‐>assign('input_author',$this-‐>Form-‐>input_text(array('id'=>$id,'name'=> 'author','value'=>
isset($params['author'])?$params['author']:'', 'size'=>10,'maxlength=>80, 'lable'=>'Qtle_author')) );
$smarty-‐>assign('Qtle_quotaQon',$this-‐>Lang('Qtle_quotaQon'));
$smarty-‐>assign('submit',$this-‐>Form-‐>input_submit('name'=> 'submit', 'value'=>'submit')));
echo $this-‐>Template-‐>process_from_database('summary');?>
2.0 Smarty Tags{has_permission perm="Modify Templates"}{/has_permission}
{tabs}{tab_content name='users'}
{tab_header name='users'}{/tab_header}
{/tab_content}{/tabs}
{tr}users{/tr}
2.0 Module Smarty TagsBlocks:{mod_form}{/mod_form}{mod_formrow}{/mod_formrow}{mod_label}{/mod_label}{mod_select}{/mod_select}
FuncQons:{mod_checkbox}{mod_dropdown}{mod_helptext}{mod_hidden}{mod_lang}{mod_link}{mod_opQons}{mod_password}{mod_submit}{mod_template}{mod_textarea}{mod_textbox}{mod_validaQon_errors}
2.0 Module Form{mod_validaQon_errors for=$blog_post}
{mod_form acQon=$form_acQon}{mod_label name="blog_post[Qtle]"}Title{/mod_label}:<br />{mod_textbox name="blog_post[Qtle]" value=$blog_post-‐>Qtle size="40"}{mod_label name="blog_post[content]"}Post{/mod_label}:<br />{mod_textarea name="blog_post[content]" value=$blog_post-‐>content cols="40"
rows="10" wysiwyg=true}<legend>{tr}Categories{/tr}</legend>{foreach from=$categories item='one_category'}
{assign var=category_id value=$one_category-‐>id}{assign var=category_name value=$one_category-‐>name}{mod_checkbox name="blog_post[category][$category_id]"
selected=$blog_post-‐>in_category($category_id)} {$category_name}<br />{/foreach}
{mod_label name="blog_post[status]"}{tr}Status{/tr}{/mod_label}:<br />{mod_dropdown name="blog_post[status]" items=$cms_mapi_module-‐>get_statuses()
selected_value=$blog_post-‐>status}
2.0 Module Form (Part 2){mod_label name='post_date_Month'}{tr}Post Date{/tr}{/mod_label}:<br />{html_select_date prefix=$post_date_prefix Qme=$blog_post-‐>post_date-‐
>Qmestamp() start_year=2000 end_year=2020} {html_select_Qme prefix=$post_date_prefix Qme=$blog_post-‐>post_date-‐>Qmestamp()}
{mod_hidden name="blog_post[author_id]" value=$blog_post-‐>author_id}{mod_submit name="submitpost" value='Submit' translate=true} {if $blog_post-‐>id gt 0}
{mod_hidden name="blog_post_id" value=$blog_post-‐>id}{mod_submit name="cancelpost" value='Cancel' translate=true}
{/if}{mod_submit name="submitpublish" value='Publish' translate=true}
{/mod_form}
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
method.install.php<?phpif (!isset($gCms)) exit;$db = $this-‐>GetDb();$dict = NewDataDicQonary( $db );
$fields="quotaQon_id I KEY,language C(8),quotaQon X,author C(80),submiRer C(80),submit_date DT
";
$sqlarray = $dict-‐>CreateTableSQL( cms_db_prefix()."module_quotaQons",$fields);$dict-‐>ExecuteSQLArray($sqlarray);
$db-‐>CreateSequence(cms_db_prefix()."module_quotaQon_seq");$this-‐>CreatePermission('Manage QuotaQons', 'Manage QuotaQons');?>
method.upgrade.php<?phpif (!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';
Perform the upgrade
Now implement admin panel 1.x
● Add method to main module:
function HasAdmin(){return ($this->CheckPermission('Manage Quotations'));}
action.defaultadmin.php<?phpif (!isset($gCms)) exit;if (!$this-‐>CheckPermission('Manage QuotaQons')) exit;
$db=$this-‐>GetDb();$rows = array();$res = $db-‐>Execute('select * from '.cms_db_prefix().'module_quotaQons order by submit_date desc');while ($res && $row=$res-‐>FetchRow())
{$row['edit'] = $this-‐>CreateLink($id, 'admin_edit', '',
$this-‐>Lang('edit'), array('quotaQon_id'=>$row['quotaQon_id']));$row['delete'] = $this-‐>CreateLink($id, 'admin_delete', '',
$this-‐>Lang('delete'), array('quotaQon_id'=>$row['quotaQon_id']));array_push($rows,$row);}
$smarty-‐>assign('quotaQons',$rows);echo $this-‐>ProcessTemplate('admin_display_list.tpl');?>
admin_display_list.tpl{if isset($message) && $message!=''}<div class="pagewarning">{$message}</div>{/if}<table>{foreach from=$quotaQons item=q}
<tr><td>{$q.quotaQon_id}</td><td>{$q.quotaQon|truncate:80}</td><td>{$q.author}</td><td>{$q.edit}</td><td>{$q.delete}</td>
</tr>{/foreach}</table>
Admin View
action.admin_delete.php<?phpif (!isset($gCms)) exit;if (!$this-‐>CheckPermission('Manage QuotaQons')) exit;
if (isset($params['quotaQon_id'])){$db = $this-‐>GetDb();$res = $db-‐>Execute('delete from '.cms_db_prefix().
'module_quotaQons where quotaQon_id=?',array($params['quotaQon_id']));
$smarty-‐>assign('message',$this-‐>Lang('quotaQon_deleted'));}
echo $this-‐>DoAcQon('defaultadmin', $id, $params, $returnid);?>
Delete Quotation
Be kind to users
● Add some safety – modify default admin link to delete
● And add to language file$lang['really_delete']='Really delete this quotaQon by %s?';
$row['delete'] = $this-‐>CreateLink($id, 'admin_delete', '',$this-‐>Lang('delete'), array('quotaQon_id'=>$row['quotaQon_id']),$this-‐>Lang('really_delete',$row['author']));
That's better
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
action.admin_edit.php<?phpif (!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
action.admin_edit.php, cont{$res = $db-‐>Execute('select * from '.cms_db_prefi x().'module_quotaQons where quotaQon_id=?',
array($params['quotaQon_id']));if ($res && $row=$res-‐>FetchRow())
{$params['author']=$row['author'];$params['quotaQon']=$row['quotaQon'];}
}$smarty-‐>assign('form_start',$this-‐>CreateFormStart($id, 'admin_edit', $returnid));
$smarty-‐>assign('input_author',$this-‐>CreateInputTextWithLabel($id, 'author',isset($params['author'])?$params['author']:'', 10, 80, '',$this-‐>Lang('Qtle_author')));
$smarty-‐>assign('Qtle_quotaQon',$this-‐>Lang('Qtle_quotaQon'));
$smarty-‐>assign('input_quotaQon',$this-‐>CreateTextArea(false, $id,isset($params['quotaQon'])?html_enQty_decode($params['quotaQon'],ENT_QUOTES):'', 'quotaQon'));
$smarty-‐>assign('submit',$this-‐>CreateInputHidden($id,'quotaQ on_id',$params['quotaQon_id']).$this-‐>CreateInputSubmit($id, 'submit', $this-‐>Lang('submit')));
echo $this-‐>ProcessTemplate('user_form.tpl');?>
Editing
And edited
action.defaultadmin.php 2.0if (!isset($gCms)) die("Can't call acQons directly!");
if ( !$this-‐>Permission-‐>check('Modify Site Preferences') )CmsResponse::redirect('index.php?'.CMS_SECURE_PARAM_NAME.'='.
$_SESSION[CMS_USER_KEY]);
if (isset($params['submitprefs']) ){
if( !CmsAcl::check_core_permission('Modify Site Preferences', $user) )die('permission denied');
$password_minlength = (int)coalesce_key($params,'password_minlength',6);$this-‐>Preference-‐>set('password_minlength',$password_minlength);
}$smarty-‐>assign('groups',cms_orm('CmsGroup')-‐>find_all());$smarty-‐>assign('users',cms_orm('CmsUser')-‐>find_all());
$smarty-‐>assign('acQve_tab_for_modules', coalesce_key($params,'selected_tab','users'));$smarty-‐>assign('form_acQon','defaultadmin');
echo $this-‐>Template-‐>process('defaultadmin.tpl',$id,$return_id);
defaultadmin.tpl 2.0{has_permission perm="Modify Templates"}
<div style="text-‐align: right; width: 80%;"><a href="listmodtemplates.php" Qtle="{tr}modify_templates{/tr}">{tr}modify_templates{/tr}</a></div><br/>{/has_permission}
{tabs}{has_permission perm='Modify Users'}
{tab_content name='users'}{tab_header name='users'}{tr}users{/tr}{/tab_header}{mod_template template='users_tab.tpl'}
{/tab_content}{/has_permission}
{has_permission perm='Modify Site Preferences'}{tab_content name='prefs'}
{tab_header name='prefs'}{tr}preferences{/tr}{/tab_header}{mod_template template='prefs_tab.tpl'}
{/tab_content}{/has_permission}
{/tabs}