Tutorial: Sahana Wiki Module

(Build the Wiki)
(Build the Menu)
Line 168: Line 168:
  <input type="hidden" name="mod" value="wiki" />
  <input type="hidden" name="mod" value="wiki" />
  <input type="hidden" name="act" value="editPage" />
  <input type="hidden" name="act" value="editPage" />
-
  <strong>Enter a page name </strong><input id="name" name="name" type="text" />
+
  &lt;strong&gt;Enter a page name &lt;/strong&gt;<input id="name" name="name" type="text" />
  <input type="submit" value="Make Page" />
  <input type="submit" value="Make Page" />
  <input type="button" onclick="javascript:closeBox()" name="cancel" value="Cancel" />
  <input type="button" onclick="javascript:closeBox()" name="cancel" value="Cancel" />
  </form>
  </form>
  </div>
  </div>

Revision as of 20:12, 6 June 2008

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 call . We will be storing past revisions of articles, so our database needs to take this into account.

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:

Image:wiki_tablestructure.png

  • 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 function delegates to menu.inc for organizational purposes. is the function used to display any wiki page. Make the function:
function shn_wiki_showPage($name = null, $revision = null){
 global $global;
}
When we go to a wiki page, the URL will have the form . When this happens, the showPage function will be called with no parameters. We capture it with:
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 function eventually. Next, we check the revision date:
$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>";
}

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 file in the wiki directory. Add the following lines.

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>