Tutorial: Sahana Wiki Module
As an exercise to familiarize ourselves with the Sahana framework, we wrote a wiki module.
Contents |
Preparing
To follow along, you'll need:
- A working copy of Sahana
- An IDE such as Eclipse
- A MySQL browser such as phpMyAdmin (optional, but helpful), set up to work with your database
Set up the database
We'll be storing the articles for our wiki in a database. For our example we need just one table, which we'll callwiki_article
Run the following SQL on your database to create the table. If you have phpMyAdmin installed, click the SQL tab at the top once you're in your database.
create table wiki_article ( id mediumint(9) not null auto_increment, `name` varchar(64) not null, rev_date datetime default null, author varchar(60) default null, content text, primary key (id), key `name` (`name`), key author (author), fulltext key content (content) );
You can view this in the phpMyAdmin browser and see the structure of the table it created:
- id is a unique identifier for a revision of an article.
- rev_date is the date the revision was submitted.
- author is the ID of the Sahana user who submitted the revision.
- content stores the text in the article.
Creating the module
First, make the three files needed: main.inc, menu.inc, and conf.inc.
conf.inc is the simplest file, so do that first:
$conf['mod_wiki_name'] = _("Swikana"); $conf['mod_wiki_menuorder'] = 0;
These two lines are required for every module. Feel free to rename the module. Next, turn to main.inc:
include ($global ['approot']."inc/lib_menu.inc"); function shn_wiki_mainmenu(){ global $global; require_once $global['approot'].'/mod/wiki/menu.inc'; } function shn_wiki_default(){ shn_wiki_showPage("Main Page"); }The
mainmenu()
showPage
showPage
function shn_wiki_showPage($name = null, $revision = null){ global $global; }When we go to a wiki page, the URL will have the form
....index.php?mod=wiki&act=showPage&name=...
if(!$name) $name = $_REQUEST['name'];
To ensure that the name is in the wiki-style format with underlines instead of spaces, encode it:
$eName = shn_wiki_encodeName($name);We will have to define the
encodeName
$revSQL = ""; if($rev != null){ $revSQL = "AND rev_date = '$rev'"; }else if(isset($_REQUEST['rev']) && $_REQUEST['rev'] != null){ $revSQL = "AND rev_date = '{$_REQUEST['rev']}'"; }
Now it's time to query the database and output the page:
$res = $global['db']->getall("SELECT name, rev_date, content, author FROM wiki_article" . " WHERE name = '$eName' $revSQL ORDER BY rev_date desc LIMIT 1"); extract($res[0]); if (!$rev_date){ shn_wiki_showNonWiki($name); }else{ $dName = shn_wiki_decodeName($name); echo "<center><h1>$dName</h1></center>"; $content = shn_wiki_wikify($content); echo "<p>". nl2br($content) . "</p>"; $timestamp = strtotime($rev_date); $str = date("l, F j, Y",$timestamp); $user = $global['db']->execute("SELECT user_name FROM users WHERE p_uuid = '$author'"); echo "<p><small><em>Last Revised $str by {$user->fields['user_name']}</em></small></p>"; }Now, define the functions that are referenced above:
encodeName, showNonWiki, wikify, and decodeName
function shn_wiki_encodeName($name) { return urlencode(str_replace(" ", "_", $name)); }Simple enough.
decodeName
function shn_wiki_decodeName($name) { return urldecode(str_replace("_", " ", $name)); }
wikify
function shn_wiki_wikify($content) { $c = preg_replace("/\[\[([^\[\]\|]+)\]\]/", '<a href="?mod=wiki&act=showPage&name=$1">$1</a>', $content); $c = preg_replace("/\[\[([^\[\]]+)\|([^\[\]]+)\]\]/", '<a href="?mod=wiki&act=showPage&name=$2">$1</a>', $c); while(preg_match("/(href=\"[^\s]*)\s([^\s]*\")/", $c)) $c = preg_replace("/(href=\"[^\s]*)\s([^\s]*\")/","$1_$2",$c); return $c; }
showNonWiki
function shn_wiki_showNonWiki($name){ global $conf; echo "<h1>$name</h1>"; echo "<p>".sprintf($conf['mod_wiki_nonWIKI'], "?mod=wiki&act=editPage&name=$name")."</p>"; }We see
act=editPage
function shn_wiki_editPage($name = null){ global $global; if(!$name) $name = $_REQUEST['name']; $eName = shn_wiki_encodeName($name); $res = $global['db']->getall("SELECT name, rev_date, content FROM wiki_article" . " WHERE name = '$eName' ORDER BY rev_date DESC LIMIT 1"); extract($res[0]); $dName = shn_wiki_decodeName($name); if(!$rev_date) $heading= "New Page"; else $heading = "Edit Page"; ?> <center><h1><?=$heading?></h1></center> <br> <form method=POST action="index.php"> <input type="hidden" name="mod" value="wiki"> <input type="hidden" name="act" value="savePage"> <table class="layout" border="0"> <tr><<d width="110">Page Name:</td> <td> <input type=hidden name="page_name" style="width:300px;" value="<?echo "$name"?>"><?echo "$dName"?> <br></td> <tr><td><br> </td></tr> <tr><td>Page Content:</td> <td> <textarea name="page_content" style="width:300px; height:150px;"><?echo "$content"?></textarea><br></td> <tr><td><br> </td></tr> <tr><td align="center"><input type="submit" value="Submit" style="width:110px;"></td></tr> </table> </form><? }
Build the Menu
The wiki needs to have a menu to access areas such as the main page, creating a new page, and the page toolbox. We'll use Sahana's menu functions to add these.
Create the filemenu.inc
We'll open a PHP tag, and call Sahana's built-in functions to open a menu in the navigation bar and add menu items.
<?php shn_mod_menuopen(_('Wiki')); shn_mod_menuitem('showPage&name=Main_Page',_('Main Page')); /* * If this is an article page, show the toolkit */ if($_REQUEST['act'] == 'default'){ shn_sub_mod_menuopen(_('Page Toolkit')); shn_sub_mod_menuitem("editPage&name=Main_Page",_("Edit Page")); shn_sub_mod_menuitem("history&name=Main_Page",_("Page History")); shn_sub_mod_menuitem("deletePage&name=Main_Page",_("Delete Page")); shn_sub_mod_menuclose(); } if(isset($_REQUEST['name']) && $_REQUEST['name'] != null){ shn_sub_mod_menuopen(_('Page Toolkit')); shn_sub_mod_menuitem("editPage&name={$_REQUEST['name']}",_("Edit Page")); shn_sub_mod_menuitem("history&name={$_REQUEST['name']}",_("Page History")); shn_sub_mod_menuitem("deletePage&name={$_REQUEST['name']}",_("Delete Page")); shn_sub_mod_menuclose(); } shn_mod_menuitem('#" id="popupLink" onclick="javascript:popup()',_('New Page')); shn_mod_menuitem('recent',_('Recently Changed')); shn_mod_menuitem('all',_('List All Pages')); shn_mod_menuclose();
Then include Sahana's main menu, and close the PHP tag:
/* * Include the main sahana menu */ require_once $global['approot'].'/inc/handler_mainmenu.inc'; ?>
Then we add some javascript and HTML to achieve the new page pop-up:
<script> /** * Changes the "New Page" link's href to not do anything, makes the new page * popup visible, and focuses the 'name' field. */ function popup(){ document.getElementById('popupLink').href = "#"; document.getElementById('popup').style.visibility = "visible"; document.getElementById('name').focus(); return false; } /** * Closes the new page popup. */ function closeBox(){ document.getElementById('popup').style.visibility = "hidden"; return false; } </script> <style> #popup{ visibility: hidden; padding: 5px 5px 4px 5px; background: #E1DED7; position: absolute; left: 200px; top: 71px; border-right: 1px solid #000; border-bottom: 1px solid #000; } #popup form input{ border: 1px solid #369; background: #fff; padding: 5px; } #popup form input:focus{ background: #ffffcc; } </style>
<form id="popupForm" action="index.php"> <input type="hidden" name="mod" value="wiki" /> <input type="hidden" name="act" value="editPage" /> <strong>Enter a page name </strong><input id="name" name="name" type="text" /> <input type="submit" value="Make Page" /> <input type="button" onclick="javascript:closeBox()" name="cancel" value="Cancel" /> </form>
Using it
If everything worked, you can now navigate to your new wiki module in Sahana and create your first page. Filling in Main Page might be a good idea. You can create links to other pages by surrounding their names in [[double square brackets]]. You can link to pages that don't exist yet, then follow the links to create them.