Sunteți pe pagina 1din 7

QCubed Tutorial - Building a Wiki

In this tutorial, we will create a very basic wiki which will allow anyone to modify the wiki pages. The idea of having a Wiki created in QCubed has been a subject of conversation for many times. But in fact, a wiki is very easy to do in QCubed, so why not build one? For this tutorial, We assume that you have a working copy of QCubed installed.

Creating the database model


With QCubed it all starts from the database model. So to start, the database model is the first thing we will create. For our wiki, the database design is relatively simple, at least, to start with. In this tutorial, we will limit the database design to a single table. This table should hold the contents of the wiki pages. Each page is identified through a wiki word. This word is unique per page in the database. With each wikiword, we also have the contents of our page. So our basic table will hold 2 fields: title (the wiki word) and contents (the contents of the page). We also add an id to the table, as well as a unique key on the title.
CREATE TABLE `wiki`.`page` ( `id` int(10) unsigned NOT NULL auto_increment, `title` varchar(45) NOT NULL default '', `contents` text NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `title` USING BTREE (`title`) ) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;

Code generation
After we have created the table in our database, we can let QCubed perform code generation. you can do this now by going to the QCubed start page and use the link "_devtools/codegen.php". After Code generation, QCubed will have created the data objects for our page table, as well as some default CRUD functionality for the table. The html pages 'drafts' folder, where you will find the html pages for listing, creating, modifying and deleting 'page' records. For our wiki, we don't need any of the default generated pages, as we will create our own page to display the wiki page.

Creating our wiki page


Our wiki will consist of a single PHP script, which will handle all functionality of displaying and editing the wiki page. let's create this basic page called "wiki.php" and it's template: "wiki.tpl.php" wiki.php:
<?php // Include prepend.inc to load QCubed require('includes/prepend.inc.php'); class WikiForm extends QForm { protected function Form_Create() {

QCubed Tutorial - Building a Wiki

} } WikiForm::Run('WikiForm'); ?>

wiki.tpl.php:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html><head> <meta http-equiv="Content-Type" content="text/html; charset=<?php _p(QApplication::$EncodingType); ?>" <title>QCubed Wiki Example</title> <style type="text/css">@import url("<?php _p(__VIRTUAL_DIRECTORY__ . __CSS_ASSETS__); ?>/styles.css");< </head><body> <?php $this->RenderBegin(); ?> <?php $this->RenderEnd(); ?> </body></html>

For now, when you load this page, it will display a blank page, as we did not add anything to the page yet.

Adding controls
For our page to do something, we will need to add several controls. The first thing we want our page to do is to display the contents of the page we are at. If this page is not present, a default message should be displayed. Let's begin with adding this functionality.

Adding the database object.


QCubed has created many functions to retrieve the contents from our table. We will now add a member variable to our QWikiForm class to hold the data from the table.
... class WikiForm extends QForm { protected $objWikiPage; protected function Form_Create() { ...

The first time a Qcubed PHP script is loaded, it will call the Form_Create() function within the QForm class, so we put our initialization of the object in here. The initialization of the database object will retrieve the contents of page based on the URL. We can do this using the following code:
... protected function Form_Create() { $this->objWikiPage = Page::LoadByTitle(QApplication::QueryString('page')); } ...

Creating our wiki page

Let's break down this single line: * Page is an object which is created by QCubed during code generation. * LoadByTitle?() is a static function created by QCubed during code generation. The function takes one parameter (the page title) and will return a Page object, which will contain the conents of the database record. * QApplication::QueryString?() is an array in which QCubed has stored all $_GET[] and $_POST[] parameters that were used to access the PHP script After this line of code is executed, the objWikiPage member variable will contain a page object based. If the page object cannot be found (which will be the case in our situation, since we have no contents in our Wiki yet), the page object will be "null".

Adding the title and contents label


Our wiki page should display the title and the contents on our page. To do this, we will create 2 labels on the page (one for the title and one for the contents) by adding 2 member variables to the class, and initializing them in the Form_Create():
... protected $objWikiPage; protected $lblTitle; protected $lblContents; protected function Form_Create() { $this->objWikiPage = Page::LoadByTitle(QApplication::QueryString('page')); $this->lblTitle = new QLabel($this); $this->lblTitle->Text = QApplication::QueryString('page'); $this->lblContents = new QLabel($this); if ($this->objWikiPage) $this->lblContents->Text = $this->objWikiPage->Contents; else $this->lblContents->Text = "this page does not exit yet."; } ...

In our form create, we also assigned some logic to display the contents of the page based on the existance of the database record in the table. If the record fo the page does not exist, we display a message that says so. To display these labels, we also need to render them in the template file:
... <?php $this->RenderBegin(); ?> <? $this->lblTitle->Render() ?> <? $this->lblContents->Render() ?> <?php $this->RenderEnd(); ?> ...

If we would run this page now, we would see one line which displays the text "this page does not exist yet".

Adding the database object.

Retrieve initial page


The first time the wiki is loaded, no parameters will be passed to the url, as it will look like: "http://localhost/wiki/wiki.php" We need to change the behaviour of the application to load a default page (WikiStart) when no parameters have been passed through the URL:
... protected function Form_Create() { if (QApplication::QueryString('page') == '') $strPage = 'WikiStart'; else $strPage = QApplication::QueryString('page'); $this->objWikiPage = Page::LoadByTitle($strPage); $this->lblTitle = new QLabel($this); $this->lblTitle->Text = $strPage; $this->lblContents = new QLabel($this); if ($this->objWikiPage) $this->lblContents->Text = $this->objWikiPage->Contents; else $this->lblContents->Text = "this page does not exit yet."; } ...

When we now reload the page, we will see the page title "WikiStart" as well!

Editing the page


Add controls
Our next step would be to edit/create the page we are currently displaying. For this, we will need: - a text input field where we can edit the page - buttons to create/edit the page and to save/cancel the edit Again, we will create member variables within the WikiForm? class, and initialize them in Form_Create() function. Afterwards, we will also render them in the template file. Note that all these new controls have the property "visible" set to false (except for the btnEditPage). This will cause these controls NOT to be rendered. We only want to display them when we click the "btnEditPage" button.
... protected function Form_Create() { $this->txtEditContents = new QWriteBox($this); if ($this->objWikiPage) $this->txtEditContents->Text = $this->objWikiPage->Contents; else $this->txtEditContents->Text = "this page does not exit yet."; $this->txtEditContents->Visible = false; $this->btnEditPage = new QButton($this);

Retrieve initial page

$this->btnEditPage->Text = "Edit"; $this->btnSavePage = new QButton($this); $this->btnSavePage->Text = "Save"; $this->btnSavePage->Visible = false; $this->btnCancelEdit = new QButton($this); $this->btnCancelEdit->Text = "Cancel"; $this->btnCancelEdit->Visible = false; ... ...

<?php $this->RenderBegin(); ?> <? $this->lblTitle->Render(); ?><br> <? $this->lblContents->Render(); ?><br> <? $this->txtEditContents->Render(); ?><br> <br> <? $this->btnEditPage->Render() ?> <? $this->btnSavePage->Render() ?> <? $this->btnCancelEdit-> <?php $this->RenderEnd(); ?> ...

Assign actions
Now that we have the buttons, we can assign actions to them. When the edit button is clicked, the Edit button and lblContent should be hidden, and the txtEditContent, Save and Cancel should be displayed. When the cancel button is clicked, reverse should happen. When the Save button is clicked, the contents of the textbox should be saved to the database and copied over to the lable to display it. We then call the cancel button routine, which will take care of resetting the buttons and labels to the correct state.
$this->txtEditContents = new QWriteBox($this); if ($this->objWikiPage) $this->txtEditContents->Text = $this->objWikiPage->Contents; else $this->txtEditContents->Text = "this page does not exit yet."; $this->txtEditContents->Visible = false;

$this->btnEditPage = new QButton($this); $this->btnEditPage->Text = "Edit"; $this->btnEditPage->AddAction(new QClickEvent(), new QServerAction('btnEditPage_Click

$this->btnSavePage = new QButton($this); $this->btnSavePage->Text = "Save"; $this->btnSavePage->Visible = false; $this->btnSavePage->AddAction(new QClickEvent(), new QServerAction('btnSavePage_Click

$this->btnCancelEdit = new QButton($this); $this->btnCancelEdit->Text = "Cancel"; $this->btnCancelEdit->Visible = false; $this->btnCancelEdit->AddAction(new QClickEvent(), new QServerAction('btnCancelEdit_C } protected function btnEditPage_Click($strFormId, $strControlId, $strParameter) { $this->txtEditContents->Visible = true; $this->lblContents->Visible = false; $this->btnEditPage->Visible = false; $this->btnCancelEdit->Visible = true; $this->btnSavePage->Visible = true;

Add controls

} protected function btnSavePage_Click($strFormId, $strControlId, $strParameter) { if (!$this->objWikiPage) $this->objWikiPage = new Page(); $this->objWikiPage->Title = $this->lblTitle->Text; $this->objWikiPage->Contents = $this->txtEditContents->Text; $this->objWikiPage->Save(); $this->lblContents->Text = $this->objWikiPage->Contents; $this->btnCancelEdit_Click($strFormId, $strControlId, $strParameter); } protected function btnCancelEdit_Click($strFormId, $strControlId, $strParameter) { $this->txtEditContents->Visible = false; $this->lblContents->Visible = true; $this->btnEditPage->Visible = true; $this->btnCancelEdit->Visible = false; $this->btnSavePage->Visible = false; }

WikiWords?
All this will allow us to start editing the main "WikiStart" page. But a Wiki consists of more pages then just the front page. Links within a wiki are created by using WikiWords?. Whenever a wikiword is detected, it should be replaced with a link to the corresponding wiki page. To do this, we will use a regular expression to scan for wikiwords, and replace it with a link.

protected function FindWikiWords($contents) { $page = $_SERVER["SCRIPT_NAME"]; $contents = ereg_replace("( ){1}(([A-Z][a-z0-9]+){2,})", " <a href=\"" . $page . "?page=\\2\">\\2 return $contents; }

Every time we set the Text of the lblContents, we should call this function:
if ($this->objWikiPage) $this->lblContents->Text = $this->FindWikiWords($this->objWikiPage->Contents); else $this->lblContents->Text = "this page does not exit yet."; protected function btnSavePage_Click($strFormId, $strControlId, $strParameter) { if (!$this->objWikiPage) $this->objWikiPage = new Page(); $this->objWikiPage->Title = $this->lblTitle->Text; $this->objWikiPage->Contents = $this->txtEditContents->Text; $this->objWikiPage->Save(); $this->lblContents->Text = $this->FindWikiWords($this->objWikiPage->Contents); $this->btnCancelEdit_Click($strFormId, $strControlId, $strParameter); }

HtmlEntities?
The above function will work fine, but instead of displaying a link, it will display the HTML code within the Contents label. This is because by default, QCubed will perform a htmlentities() function on the text. If you do not want this, we need to disable this. This can be done by setting the property HtmlEntities? to false for the Assign actions 6

lblContents during initialization:


$this->lblContents = new QLabel($this); $this->lblContents->HtmlEntities = false; if ($this->objWikiPage) $this->lblContents->Text = $this->FindWikiWords($this->objWikiPage->Contents); else $this->lblContents->Text = "this page does not exit yet.";

End of part one


We now have a full operational wiki! next part: Improve wiki formatting add basic navigation improve look and feel by applying CSS styles improving our code adding ajax Go to Part 2

End of part one

S-ar putea să vă placă și