Good Morning
An Introduction to
Module Development
An Introduction to
Module Development
Or: How To Create Modules Without Becoming a
           Bitter, Angry Little Man
What is a module?


• adds functions or capabilities to CMSMS
• allows more complexity than a plug-in or
  user-defined tag...
Why a module instead
of a plug-in or UDT?
• multi-language
• install / uninstall / upgrade
• trigger / handle events
• pro...
What else does the
   module API offer?
• database abstraction (ADODB)
• templating system (Smarty)
• user-input sanitizin...
Module API, cont.

• admin-side permission system
• admin-side tools for tabbed interfaces
• form utilities
• ... and more...
Types of modules
• plug-ins (e.g., News, Search, FormBuilder)
• content-type modules (e.g., Cataloger)
• infrastructure mo...
Types of modules
    • plug-ins (e.g., News, Search, FormBuilder)
    • content-type modules (e.g., Cataloger)
    • infra...
Ready? Let’s go!

• “Hello World” module
• create the directory:
  $CMSROOT/modules/HelloWorld
• create the initial module...
HelloWorld.module.php
<?php

class   HelloWorld extends CMSModule

       {


       function GetName()

       
   {

   ...
Congratulations!
• you’re done!
• next steps:
 • publish Hello World on the Developer’s
    Forge
 • check in to svn or gi...
Uh-oh!
• our first Bitter Angry Little Man alert!
• 3 people filed bug reports / feature requests:
 • “why English only?”
 •...
Solving problems

• reject issue about `World’ capitalization
  (“works for me!”)
• solve other problem by using language ...
modules/HelloWorld/lang/en_US.php
<?php

/* CMSROOT/modules/HelloWorld/lang/en_US.php */

$lang['hello_world_string'] = 'H...
HelloWorld.module.php
<?php

class   HelloWorld extends CMSModule

       {


       function GetName()

       
   {

   ...
Translation
• by adding module to Translation Center, it
   can be translated into any language
• add by setting up extern...
HelloWorld/lang/ext/de_DE.php
<?php

$lang['hello_world_string'] = 'Hallo Welt! Grüße!';

?>
Success!

• localized version of the module is available
 • checked into the repository and published
    on the Forge
  •...
Uh-Oh!
• another Bitter Angry Little Man alert!
• more bug reports / feature requests:
 • “I want the message in <h2> tags...
Solutions

• output should use a template to allow
  different formatting
• module should use the DoAction method to
  pro...
Templates
• create
  CMSROOT/modules/HelloWorld/templates
  directory
• create your template: hello.tpl
• templates use th...
HelloWorld/templates/hello.tpl
{*
smarty template.
CMSROOT/modules/HelloWorld/templates/hello.tpl
*}

<h2>{$mod->Lang('hel...
Changes to HelloWorld.module.php

   function DoAction($action, $id, $params, $returnid=-1)

   
   {

   
   $this->smart...
Where we’re at

• output is now templated. Site developer
  could edit the hello.tpl to make it output the
  message in an...
Multiple actions


• build out the DoAction method
• initially, we’ll implement it in-line in the
   module
DoAction in HelloWorld.module.php

    function DoAction($action, $id, $params, $returnid=-1)

    
   {

    
   switch (...
DoAction


• special action: default
• we’ll see another special action later
• other parameters will be explained later
Adds to HelloWorld.module.php

   function _do_hello($id, $params, $returnid)

   
   {

   
   $this->smarty->assign_by_r...
HelloWorld/templates/goodbye.tpl
{* smarty template.
CMSROOT/modules/HelloWorld/templates/goodbye.tpl *}

<h2>{$mod->Lang(...
Update lang file
<?php

/* CMSROOT/modules/HelloWorld/lang/en_US.php */

$lang['hello_world_string'] = 'Hello World!';
$lan...
Take a breath

• what we’ve covered so far:
 • basic module file
 • localization
 • templates
 • multiple actions
Oh Noes!
• another Bitter Angry Little Man alert!
• 12 people filed bug reports:
 • “I have one installation that accepts t...
Solutions

• we should have the module report its
  version
 • this opens up a can of worms: module
    installation, upgr...
Reporting version

• module method “GetVersion”
• version-related module methods
 • install
 • upgrade
 • uninstall
Adds to module
function GetVersion()

     {

     return '1.0';

     }

     
function Install()

     {
       $this->A...
update lang file
<?php

/* CMSROOT/modules/HelloWorld/lang/en_US.php */

$lang['hello_world_string'] = 'Hello World!';
$lan...
Working backwards

• separate files
 • method.install.php
 • method.upgrade.php
 • method.uninstall.php
Separate file features

• global handle to CMS is defined: $gCms
• security tip: test for the global, so people
  can’t call...
method.install.php
<?php

// security measure
if (!isset($gCms)) exit;

$this->CreatePreference('use_random_phrase','y');
...
method.upgrade.php
<?php

// safety measure
if (!isset($gCms)) exit;

switch($oldversion)
{
 case "0.0.0.1":
  $this->Crea...
method.unistall.php
<?php

// safety measure
if (!isset($gCms)) exit;

$this->RemovePreference('use_random_phrase');

$thi...
Separate actions

• DoAction can also be split into multiple files
• this keeps memory footprint smaller, code
  organizati...
action.action_name.php

• has $gCms defined
• has $id, $params, and $returnid defined
  (more on these later)
• has $smarty ...
action.default.php
<?php

// safety first
if (!isset($gCms)) exit;

$this->_do_hello($id, $params, $returnid)

?>
action.goodbye.php
<?php

// safety first
if (!isset($gCms)) exit;

$this->_do_goodbye($id, $params, $returnid)

?>
Wha??

• where’s our “Hello World?”
• action “hello” is not the same as action
  “default”
• we can either implement actio...
Another deep breath
• what we’ve accomplished:
 • keeping track of module versions
 • providing a clean approach to module...
Uh-Oh!
• Bitter Angry Little Man alert!
• 16 people filed feature requests:
 • “I should be able to load in multiple
    me...
The database

• handle to database available via GetDb()
  method
• supports ADODB functionality
• hides a lot of the comp...
Adds to method.install.php
// get database handle
$db = &$this->GetDb();

// mysql-specific, but ignored by other database
...
Don’t forget!

• implement similar code in the
  method.upgrade.php
• bump the module’s version number to 1.1
• and implem...
Revised function
function _do_hello($id, $params, $returnid)
  {
  $db = &$this->GetDb();
  if ($this->GetPreference('use_...
Revised template/hello.tpl
{* smarty template.
CMSROOT/modules/HelloWorld/templates/hello.tpl *}

<h2>{$phrase}</h2>
Fear & loathing

• Angry bitter little man alert!
 • 23 users complained about not being able
    to change the preference...
Solution


• need to create an admin area for the module
• and need to create an input form
Creating an admin


• HasAdmin() method returns true
• our other magic action: defaultadmin
• separated file: action.defaul...
Additions to HelloWorld.module.php
function HasAdmin()
  {
  return true;
  }

function VisibleToAdminUser()
  {
  return ...
action.defaultadmin.php
<?php
if (!isset($gCms)) exit;

if (! $this->CheckPermission('Manage All Content')) exit;

if (iss...
templates/adminpanel.tpl
{if isset($message)}<p class="pagemessage">{$message}</p>{/if}
{$start_form}

       <div class="...
Create a user-side form


• very much like the admin side
action.add.php
<?php
if (!isset($gCms)) exit;

if (isset($params['phrase']) && !empty($params['phrase']))

       {

     ...
add.tpl
{if isset($message)}<p class="pagemessage">{$message}</p>{/if}
{$start_form}

       <fieldset><legend>{$mod->Lang(...
What we’ve covered
   API Covered               API Not Covered



                       10%




                 90%
Resources

• the Wiki
  http://wiki.cmsmadesimple.org/index.php/Developers

• Skeleton module
  http://dev.cmsmadesimple.o...
Bitter, angry little man

• hitting a moving target; keeping up to date
• lots of complaints about the flavors of free
  ic...
Preparing for CMSMS 2.0
• beware of direct access to API class
  variables! e.g., use $this->GetDb(), don’t use
  $this->d...
Calguy’s cardinal rules
• Do not use members of the module object,
  use accessors
• Split everything up into logical clas...
Calguy’s rules, cont.
• Cache data where practical data may be read
  (if it's feasible/expected that the
  more than one ...
Calguy’s rules, cont.

• Use ADODB’s parameter cleansing stuff,
  don't build in all the params yourself.
• Keep your code...
Closing
Closing


• Thanks for your attention
Closing


• Thanks for your attention
• Goodbye cruel world...
Appendix


• module directory structure
• source listings
• random notes
Module directory structure
RegTM Module source
<?php
# extremely simple filter module; adds registered trademark symbol to your company's name

class ...
RegTM Module source, cont.
    function MinimumCMSVersion()
    {
      return "1.6";
    }

 function SetParameters()
 
{...
User Warning Module source
<?php
# extremely simple event-handler module; sends email to admins giving them warning when a...
User Warning Module source, cont.
function MinimumCMSVersion()
{
  return "1.6";
}

function GetDependencies()
{
  return ...
User Warning Module source, cont.
 function DoEvent( $originator, $eventname, &$params )

{

 if ($originator == 'Core' &&...
Contact me


• sjg@cmsmodules.com
• drop by next time you’re in L.A.
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Geek Moot '09 -- Introduction to CMS Module Development
Upcoming SlideShare
Loading in …5
×

Geek Moot '09 -- Introduction to CMS Module Development

14,515 views
14,374 views

Published on

A basic introduction to creating modules for <a>CMS Made Simple</a>.

Published in: Technology
1 Comment
7 Likes
Statistics
Notes
  • For more information on CMSMS Module development, check out the Development Cookbook at http://www.packtpub.com/cms-made-simple-development-cookbook/book
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
14,515
On SlideShare
0
From Embeds
0
Number of Embeds
1,406
Actions
Shares
0
Downloads
110
Comments
1
Likes
7
Embeds 0
No embeds

No notes for slide
  • Geek Moot '09 -- Introduction to CMS Module Development

    1. 1. Good Morning
    2. 2. An Introduction to Module Development
    3. 3. An Introduction to Module Development Or: How To Create Modules Without Becoming a Bitter, Angry Little Man
    4. 4. What is a module? • adds functions or capabilities to CMSMS • allows more complexity than a plug-in or user-defined tag (UDT)
    5. 5. Why a module instead of a plug-in or UDT? • multi-language • install / uninstall / upgrade • trigger / handle events • provide infrastructure and functions for other modules
    6. 6. What else does the module API offer? • database abstraction (ADODB) • templating system (Smarty) • user-input sanitizing • persistent preferences • access to CMS configurations • dependencies management
    7. 7. Module API, cont. • admin-side permission system • admin-side tools for tabbed interfaces • form utilities • ... and more ...
    8. 8. Types of modules • plug-ins (e.g., News, Search, FormBuilder) • content-type modules (e.g., Cataloger) • infrastructure module support (e.g., CMSMailer, nuSOAP) • administrative (e.g., ModuleManager) • event handlers (e.g., UserWarning*) • filters (e.g., RegTM*)
    9. 9. Types of modules • plug-ins (e.g., News, Search, FormBuilder) • content-type modules (e.g., Cataloger) • infrastructure module support (e.g., CMSMailer, nuSOAP) • administrative (e.g., ModuleManager) • event handlers (e.g., UserWarning*) • filters (e.g., RegTM*) * modules written for this presentation, source in appendix
    10. 10. Ready? Let’s go! • “Hello World” module • create the directory: $CMSROOT/modules/HelloWorld • create the initial module file: HelloWorld.module.php
    11. 11. HelloWorld.module.php <?php class HelloWorld extends CMSModule { function GetName() { return 'HelloWorld'; } function IsPluginModule() { return true; } function DoAction($action, $id, $params, $returnid=-1) { echo 'Hello World!'; } } ?>
    12. 12. Congratulations! • you’re done! • next steps: • publish Hello World on the Developer’s Forge • check in to svn or git • mention the new module in the Forum • wait for fame and fortune to roll in
    13. 13. Uh-oh! • our first Bitter Angry Little Man alert! • 3 people filed bug reports / feature requests: • “why English only?” • “Capitalizing ‘World’ is grammatically incorrect.” • “I want to use this module in German!”
    14. 14. Solving problems • reject issue about `World’ capitalization (“works for me!”) • solve other problem by using language files: • create directory HelloWorld/lang • create initial language file: en_US.php
    15. 15. modules/HelloWorld/lang/en_US.php <?php /* CMSROOT/modules/HelloWorld/lang/en_US.php */ $lang['hello_world_string'] = 'Hello World!'; ?>
    16. 16. HelloWorld.module.php <?php class HelloWorld extends CMSModule { function GetName() { return 'HelloWorld'; } function IsPluginModule() { return true; } function DoAction($action, $id, $params, $returnid=-1) { echo $this->Lang('hello_world_string'); } } ?>
    17. 17. Translation • by adding module to Translation Center, it can be translated into any language • add by setting up externals in svn • instructions at http://forum.cmsmadesimple.org/index.php/topic,2639.0.html • results in lang/ext directory containing translation files
    18. 18. HelloWorld/lang/ext/de_DE.php <?php $lang['hello_world_string'] = 'Hallo Welt! Grüße!'; ?>
    19. 19. Success! • localized version of the module is available • checked into the repository and published on the Forge • downloaded all over the world • surely, fame and fortune must follow
    20. 20. Uh-Oh! • another Bitter Angry Little Man alert! • more bug reports / feature requests: • “I want the message in <h2> tags” • “text should be in <p> tags!” • “I also want ‘goodbye world’ as an option!”
    21. 21. Solutions • output should use a template to allow different formatting • module should use the DoAction method to provide alternate functionality
    22. 22. Templates • create CMSROOT/modules/HelloWorld/templates directory • create your template: hello.tpl • templates use the Smarty markup language • you will learn to read and love the Smarty manual at http://www.smarty.net/manual/en/
    23. 23. HelloWorld/templates/hello.tpl {* smarty template. CMSROOT/modules/HelloWorld/templates/hello.tpl *} <h2>{$mod->Lang('hello_world_string')}</h2>
    24. 24. Changes to HelloWorld.module.php function DoAction($action, $id, $params, $returnid=-1) { $this->smarty->assign_by_ref('mod',$this); $this->ProcessTemplate('hello.tpl'); }
    25. 25. Where we’re at • output is now templated. Site developer could edit the hello.tpl to make it output the message in any way they wanted • we still have only one action - the module will only display the “hello world” string
    26. 26. Multiple actions • build out the DoAction method • initially, we’ll implement it in-line in the module
    27. 27. DoAction in HelloWorld.module.php function DoAction($action, $id, $params, $returnid=-1) { switch ($action) { case 'default': case 'hello': { $this->_do_hello($id, $params, $returnid); break; } case 'goodbye': { $this->_do_goodbye($id, $params, $returnid); break; } } }
    28. 28. DoAction • special action: default • we’ll see another special action later • other parameters will be explained later
    29. 29. Adds to HelloWorld.module.php function _do_hello($id, $params, $returnid) { $this->smarty->assign_by_ref('mod',$this); echo $this->ProcessTemplate('hello.tpl'); } function _do_goodbye($id, $params, $returnid) { $this->smarty->assign_by_ref('mod',$this); echo $this->ProcessTemplate('goodbye.tpl'); }
    30. 30. HelloWorld/templates/goodbye.tpl {* smarty template. CMSROOT/modules/HelloWorld/templates/goodbye.tpl *} <h2>{$mod->Lang('goodbye_world_string')}</h2>
    31. 31. Update lang file <?php /* CMSROOT/modules/HelloWorld/lang/en_US.php */ $lang['hello_world_string'] = 'Hello World!'; $lang['goodbye_world_string'] = 'Goodbye you cruel old planet.'; ?>
    32. 32. Take a breath • what we’ve covered so far: • basic module file • localization • templates • multiple actions
    33. 33. Oh Noes! • another Bitter Angry Little Man alert! • 12 people filed bug reports: • “I have one installation that accepts the ‘hello’ and ‘goodbye’ actions, and another that’s the older version, and I’m confused.” • “I have different versions on my sites and can’t tell them apart easily.”
    34. 34. Solutions • we should have the module report its version • this opens up a can of worms: module installation, upgrades, uninstallation • which opens up another can of worms: separating files
    35. 35. Reporting version • module method “GetVersion” • version-related module methods • install • upgrade • uninstall
    36. 36. Adds to module function GetVersion() { return '1.0'; } function Install() { $this->Audit( 0,$this->GetName(),$this->Lang('installed', $this->GetVersion()) ); } function Uninstall() { $this->Audit( 0,$this->GetName(),$this->Lang('uninstalled') ); } function Upgrade($oldversion, $newversion) { $this->Audit( 0,$this->GetName(),$this->Lang('upgraded', $newversion) ); }
    37. 37. update lang file <?php /* CMSROOT/modules/HelloWorld/lang/en_US.php */ $lang['hello_world_string'] = 'Hello World!'; $lang['goodbye_world_string'] = 'Goodbye you cruel old planet.'; $lang['installed'] = 'Hello World version %s installed.'; $lang['uninstalled'] = 'Hello World has been uninstalled.'; $lang['upgraded'] = 'Hello World upgraded to version %s.'; ?>
    38. 38. Working backwards • separate files • method.install.php • method.upgrade.php • method.uninstall.php
    39. 39. Separate file features • global handle to CMS is defined: $gCms • security tip: test for the global, so people can’t call the file directly and cause trouble • other variables pre-defined based on method that’s been split out
    40. 40. method.install.php <?php // security measure if (!isset($gCms)) exit; $this->CreatePreference('use_random_phrase','y'); // entry in admin log $this->Audit( 0,$this->GetName(), $this->Lang('installed', $this->GetVersion()) ); ?>
    41. 41. method.upgrade.php <?php // safety measure if (!isset($gCms)) exit; switch($oldversion) { case "0.0.0.1": $this->CreatePreference('use_random_phrase','y'); } $this->Audit( 0, $this->GetName(), $this->Lang('upgraded', $newversion)); ?>
    42. 42. method.unistall.php <?php // safety measure if (!isset($gCms)) exit; $this->RemovePreference('use_random_phrase'); $this->Audit( 0,$this->GetName(), $this->Lang('uninstalled', $this->GetVersion()) ); ?>
    43. 43. Separate actions • DoAction can also be split into multiple files • this keeps memory footprint smaller, code organization more logical • each file is called action.action_name.php • these files also have special pre-set variables
    44. 44. action.action_name.php • has $gCms defined • has $id, $params, and $returnid defined (more on these later) • has $smarty defined
    45. 45. action.default.php <?php // safety first if (!isset($gCms)) exit; $this->_do_hello($id, $params, $returnid) ?>
    46. 46. action.goodbye.php <?php // safety first if (!isset($gCms)) exit; $this->_do_goodbye($id, $params, $returnid) ?>
    47. 47. Wha?? • where’s our “Hello World?” • action “hello” is not the same as action “default” • we can either implement action “hello” by creating action.hello.php, or change our model such that this is the default.
    48. 48. Another deep breath • what we’ve accomplished: • keeping track of module versions • providing a clean approach to module upgrades and uninstalls • breaking module into separate files for better memory management • set preferences, logged to the admin log
    49. 49. Uh-Oh! • Bitter Angry Little Man alert! • 16 people filed feature requests: • “I should be able to load in multiple messages, not just ‘hello’ and ‘goodbye’!” • “Yeah, and they should have the option of displaying randomly according to that new preference you created!”
    50. 50. The database • handle to database available via GetDb() method • supports ADODB functionality • hides a lot of the complexity for table creation. see http://phplens.com/lens/adodb/docs-datadict.htm
    51. 51. Adds to method.install.php // get database handle $db = &$this->GetDb(); // mysql-specific, but ignored by other database $taboptarray = array( 'mysql' => 'TYPE=MyISAM' ); // database-independent table creation $dict = NewDataDictionary( $db ); $flds = "phrase_id I KEY AUTO, phrase C(255)"; $sqlarray = $dict->CreateTableSQL( cms_db_prefix(). 'module_hello', $flds, $taboptarray); $dict->ExecuteSQLArray($sqlarray); $db->Execute('insert into '.cms_db_prefix(). 'module_hello (phrase) values (?)', array($this->Lang('hello_world_string') ));
    52. 52. Don’t forget! • implement similar code in the method.upgrade.php • bump the module’s version number to 1.1 • and implement code that uses the phrases from the database
    53. 53. Revised function function _do_hello($id, $params, $returnid) { $db = &$this->GetDb(); if ($this->GetPreference('use_random_phrase','y') == 'y') { $count = $db->GetOne('select count(phrase) from '. cms_db_prefix().'module_hello'); $rand_line = rand(1,$count) - 1; $res = $db->SelectLimit('select phrase from '. cms_db_prefix().'module_hello',1,$rand_line); if ($res && $row=$res->FetchRow()) { $phrase = $row['phrase']; } } else { $phrase = $db->GetOne('select phrase from '.cms_db_prefix(). 'module_hello where phrase_id=1'); } $this->smarty->assign('phrase',$phrase); echo $this->ProcessTemplate('hello.tpl'); }
    54. 54. Revised template/hello.tpl {* smarty template. CMSROOT/modules/HelloWorld/templates/hello.tpl *} <h2>{$phrase}</h2>
    55. 55. Fear & loathing • Angry bitter little man alert! • 23 users complained about not being able to change the preference • 47 users complained about the lack of a form to add phrases
    56. 56. Solution • need to create an admin area for the module • and need to create an input form
    57. 57. Creating an admin • HasAdmin() method returns true • our other magic action: defaultadmin • separated file: action.defaultadmin.php
    58. 58. Additions to HelloWorld.module.php function HasAdmin() { return true; } function VisibleToAdminUser() { return $this->CheckPermission('Manage All Content'); }
    59. 59. action.defaultadmin.php <?php if (!isset($gCms)) exit; if (! $this->CheckPermission('Manage All Content')) exit; if (isset($params['random']) && !empty($params['random'])) { $this->SetPreference('use_random_phrase',$params['random']); $smarty->assign('message',$this->Lang('preference_set')); } $smarty->assign('start_form', $this->CreateFormStart($id, 'defaultadmin', $returnid)); $smarty->assign('input_pref',$this->CreateInputHidden($id,'random','n'). $this->CreateInputCheckbox($id, 'random', 'y', $this->GetPreference('use_random_phrase','y')). $this->Lang('title_use_random_phrase')); $smarty->assign('submit', $this->CreateInputSubmit($id, 'submit', lang('submit'))); echo $this->ProcessTemplate('adminpanel.tpl'); ?>
    60. 60. templates/adminpanel.tpl {if isset($message)}<p class="pagemessage">{$message}</p>{/if} {$start_form} <div class="pageoverflow"> <p class="pagetext">{$input_pref}</p> <p class="pageinput">{$submit}</p> </div> </form>
    61. 61. Create a user-side form • very much like the admin side
    62. 62. action.add.php <?php if (!isset($gCms)) exit; if (isset($params['phrase']) && !empty($params['phrase'])) { $db = &$this->GetDb(); $db->Execute('insert into '.cms_db_prefix(). 'module_hello (phrase) values (?)', array($params['phrase'])); $smarty->assign('message',$this->Lang('phrase_added')); } $smarty->assign('start_form', $this->CreateFormStart($id, 'add', $returnid)); $smarty->assign('input_phrase', $this->CreateInputText($id,'phrase', $this->Lang('add_phrase_here'),40,255)); $smarty->assign('submit', $this->CreateInputSubmit($id, 'submit', $this->Lang('submit'))); $smarty->assign_by_ref('mod',$this); echo $this->ProcessTemplate('add.tpl'); ?>
    63. 63. add.tpl {if isset($message)}<p class="pagemessage">{$message}</p>{/if} {$start_form} <fieldset><legend>{$mod->Lang('add_a_phrase')}</legend> <div> <p>{$input_phrase}</p> <div> <div> <p>{$submit}</p> </div> </fieldset> </form>
    64. 64. What we’ve covered API Covered API Not Covered 10% 90%
    65. 65. Resources • the Wiki http://wiki.cmsmadesimple.org/index.php/Developers • Skeleton module http://dev.cmsmadesimple.org/projects/skeleton • IRC freenode.net #cms
    66. 66. Bitter, angry little man • hitting a moving target; keeping up to date • lots of complaints about the flavors of free ice cream available • give an inch, they’ll ask for a mile • using module for what it was never meant to do
    67. 67. Preparing for CMSMS 2.0 • beware of direct access to API class variables! e.g., use $this->GetDb(), don’t use $this->db • no more PHP 4.x-isms • callbacks are going away! use the event system. • lots more – ORM, etc, so beware!
    68. 68. Calguy’s cardinal rules • Do not use members of the module object, use accessors • Split everything up into logical classes • No separate entry points, use actions • Use the permissions model liberally • Use separate files for actions, tabs, install/ upgrade/uninstall actions
    69. 69. Calguy’s rules, cont. • Cache data where practical data may be read (if it's feasible/expected that the more than one time in a request). • Use DEFINES or class constants rather than hardcoded strings • Separate logic from display... use Smarty • Provide the data to Smarty, let Smarty display it.
    70. 70. Calguy’s rules, cont. • Use ADODB’s parameter cleansing stuff, don't build in all the params yourself. • Keep your code clean. • Get off my lawn, you kids!
    71. 71. Closing
    72. 72. Closing • Thanks for your attention
    73. 73. Closing • Thanks for your attention • Goodbye cruel world...
    74. 74. Appendix • module directory structure • source listings • random notes
    75. 75. Module directory structure
    76. 76. RegTM Module source <?php # extremely simple filter module; adds registered trademark symbol to your company's name class RegTM extends CMSModule { var $company_name = 'CMS Made Simple'; function GetName() { return 'RegTM'; } function GetFriendlyName() { return 'RegTM'; } function GetVersion() { return '0.1'; } function GetAuthor() { return 'SjG'; } function GetAuthorEmail()
    77. 77. RegTM Module source, cont. function MinimumCMSVersion() { return "1.6"; } function SetParameters() { $this->AddEventHandler( 'Core', 'ContentPostRender', true ); } function DoEvent( $originator, $eventname, &$params ) { if ($originator == 'Core' && $eventname == 'ContentPostRender') { $params['content'] = str_replace($this->company_name, $this->company_name.'<sup>&reg;</sup>', $params['content']); } } } // end ?>
    78. 78. User Warning Module source <?php # extremely simple event-handler module; sends email to admins giving them warning when a user is deleted. class UserWarning extends CMSModule { function GetName() { return 'UserWarning'; } function GetFriendlyName() { return 'UserWarning'; } function GetVersion() { return '0.1'; } function GetAuthor() { return 'SjG'; } function GetAuthorEmail() { return 'sjg@cmsmodules.com';
    79. 79. User Warning Module source, cont. function MinimumCMSVersion() { return "1.6"; } function GetDependencies() { return array('CMSMailer'=>'1.73'); } function SetParameters() { $this->AddEventHandler( 'Core', 'DeleteUserPre', true ); }
    80. 80. User Warning Module source, cont. function DoEvent( $originator, $eventname, &$params ) { if ($originator == 'Core' && $eventname == 'DeleteUserPre') { $db = $this->GetDB(); $user = $params['user']; $result = $db->Execute('select * from '.cms_db_prefix().'users where user_id <>?', array($user->id)); if ($result) { $mail =& $this->GetModuleInstance('CMSMailer'); if ($mail != FALSE) { $mail->reset(); $mail->SetSubject('Admin User Deleted'); $mail->SetBody('FYI: CMS admin user "'.$user->firstname.' '.$user->lastname. '" ('.$user->username.') has been terminated.'); } while ($row = $result->FetchRow()) { $mail->AddAddress($row['email'],$row['first_name'].' '.$row['last_name']); } $sent = $mail->Send(); } } } } // end
    81. 81. Contact me • sjg@cmsmodules.com • drop by next time you’re in L.A.

    ×