Wiki source for WikkaCakeExample


Show raw source

=====A WikkaCake Example=====

<<**{{color c="red" text="This page is deprecated."}}**
This example assumes ""CakePHP"" 1.1. An updated version for WikkaCake 1.3 is in the works.

**See also:** WikkaCake<<

===Overview===
If you have yet to read the WikkaCake page, I'd suggest starting there first. This is actually an extension of that page, and provides an example of a completely self-contained Wikka action that has been written using the [[http://www.cakephp.org | CakePHP]] framework. This is not a Cake tutorial. Instead, I will simply provide the code as-is and provide comments that are Wikka-specific.

If one has already set up and tested an embedded WikkaCake environment, then this application should run unmodified (in fact, it is the exact code that's currently running on my own machine).

All directory names are referenced from the top-level "caketest" directory.

This application is a simple database management app for saving, modifying, and deleting servers. It was developed for managing the public nameserver DB on the [[http://opennic.jdcomputers.com.au | OpenNIC wiki]]. A publicly accessible version will be available shortly once testing is completed.

**config/database.php**
%%(php)
var $default = array('driver' => 'mysql',
'connect' => 'mysql_pconnect',
'host' => 'localhost',
'login' => 'root',
'password' => 'root',
'database' => 'wikka_cake',
'prefix' => '');
%%
//Comments:// This is the setup I use on my personal machine (no, it's not externally accessible, so I'm not giving away any state secrets here). Obviously, you will need to modify accordingly. If you haven't done so, simply copy ##config/database.php.default## to ##config/database.php## and modify that. Eventually, this will go away once I work on seamlessly accessing the Wikka DB authentication params.

**public_access_servers.sql**
%%(sql)
CREATE TABLE IF NOT EXISTS public_access_servers (
id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
ip_addr VARCHAR(15) NOT NULL,
internic_hn VARCHAR(50),
opennic_hn VARCHAR(50),
owner VARCHAR(50) NOT NULL,
city VARCHAR(50),
state CHAR(2),
country CHAR(2) NOT NULL,
email VARCHAR(50),
last_verified DATE,
comments LONGTEXT);
%%
//Comments:// This is the DB schema upon which the following code is based. If you modify this, there's a good chance you'll need to modify one or more files below. Note that Cake expect, by default, a primary key called "id".

**models/server.php**
%%(php)
<?php
class Server extends AppModel
{
var $name = 'Server';
var $useTable = "public_access_servers";

var $validate = array(
'ip_addr' => VALID_NOT_EMPTY,
'owner' => VALID_NOT_EMPTY,
'country' => VALID_NOT_EMPTY
);
}
?>
%%
//Comments:// ##$useTable## reflects that fact that I've named my DB table in a non-conforming way.

**controllers/servers_controller.php**
%%(php)
<?php
class ServersController extends AppController
{
var $name = 'Servers';
var $layout = 'default';
//var $wikka = $this->params['wakka'];
//var $scaffold;

/*
function ServersController()
{
parent::__construct();
// This doesn't work, as the params array isn't yet
// available at time of class object construction!
//$this->wikka = parent::$this->params['wakka'];
}
*/

function index()
{
$this->set('servers', $this->Server->findAll());
}
function add()
{
if(false===$this->params['wakka']->IsAdmin())
{
$this->redirect($this->base);
}
if(true===isset($this->data['Servers']['action']) &&
false!==strpos($this->data['Servers']['action'], 'Cancel'))
{
$this->redirect($this->base);
exit;
}
uses('sanitize');
$sanitize = new Sanitize();
if(empty($this->data))
{
$this->render();
}
if(!empty($this->data))
{
$sanitize->cleanArray($this->data);
if($this->Server->save($this->data))
{
$this->flash('Your entry has been saved.', '', 1);
}
else
{
$this->set('errorMessage', 'Please correct errors below.');
$this->render();
}
}
}

function delete()
{
if(false===$this->params['wakka']->IsAdmin())
{
$this->redirect($this->base);
}

if(isset($this->params['url']['id']))
{
$this->Server->del($this->params['url']['id']);
}
$this->redirect($this->base);
exit;
}

function modify()
{
if(false===$this->params['wakka']->IsAdmin())
{
$this->redirect($this->base);
}

$id = null;
if(isset($this->params['url']['id']))
{
$id = $this->params['url']['id'];
}
if(empty($this->data))
{
$this->Server->id = $id;
$this->data = $this->Server->read();
}
else
{
uses('sanitize');
$sanitize = new Sanitize();
if(empty($this->data))
{
$this->render();
}
if(!empty($this->data))
{
$sanitize->cleanArray($this->data);
if($this->Server->save($this->data))
{
$this->flash('Your entry has been saved.', '', 1);
}
else
{
$this->set('errorMessage', 'Please correct errors below.');
$this->render();
}
}
}
}
}
?>
%%
//Comments:// Look back at the changes you made in your ##webroot/index.php## code. Remember this?

%%(php)
array('wakka'=>(object)$this)
%%

That is how the Wikka instance is passed into the Cake framework so it's accessible in the controller (where the business logic resides). The commented-out construction above indicates that due to the way the Cake core libraries are bootstrapped, the Wikka instance isn't available until *after* the constructor has been called. Nor can it be set as a ##var## (since only static assignments can be made to ##var##-declared variables). So you'll need to call your Wikka lib functions within each method from which you need access.

I could have chosen to use the data filters provided by Wikka, but for simplicity sake I used the Cake built-in "sanitize" class. Also, note that the ##$this->flash(...)## call doesn't redirect properly due to some interaction between Wikka and Cake. The link displays just fine, but one has to actually click the link for the redirect to occur.

**views/layouts/default.thtml**
%%(html)
<?php echo $content_for_layout; ?>
%%
//Comments:// We don't want Cake to output any additional HTML <head> sections, as this is already handled by Wikka.

**views/servers/index.thtml**
%%(html)
<h1>Public Access Servers</h1>
<br/>
<table border="1">
<tr>
<?php if(true===$this->params['wakka']->IsAdmin()): ?>
<th></th>
<?php endif; ?>
<th>IP Addr</th>
<th>InterNIC Hostname</th>
<th>OpenNIC Hostname</th>
<th>Owner</th>
<th>City</th>
<th>State</th>
<th>Country</th>
<th>Email</th>
<th>Last Verified</th>
<th>Comments</th>
</tr>
<?php foreach ($servers as $server): ?>
<tr>
<?php if(true===$this->params['wakka']->IsAdmin()): ?>
<td><a class="keys" href="<?php echo $html->base.'?action=delete&id='.$server['Server']['id'] ?>">X</a> 
<a class="keys" href="<?php echo $html->base.'?action=modify&id='.$server['Server']['id'] ?>">M</a></td>
<?php endif; ?>
<td><?php echo $server['Server']['ip_addr']; ?></td>
<td><?php echo $server['Server']['internic_hn']; ?></td>
<td><?php echo $server['Server']['opennic_hn']; ?></td>
<td><?php echo $server['Server']['owner']; ?></td>
<td><?php echo $server['Server']['city']; ?></td>
<td><?php echo $server['Server']['state']; ?></td>
<td><?php echo $server['Server']['country']; ?></td>
<td><?php echo preg_replace('/@/', ' <at> ', $server['Server']['email']); ?></td>
<td><?php echo $server['Server']['last_verified']; ?></td>
<td><?php echo $server['Server']['comments']; ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php
if(true===$this->params['wakka']->IsAdmin())
{
echo $html->link('Add server', $html->base.'?action=add');
}
?>
%%
//Comments:// Note that the Wikka instance is accessible in the views for whatever you might need it for. Also, because of the conflicting way in which Wikka and Cake handle the parsing of URLs, links must be generated using the format shown above. Attempting to format Cake links as per the Cake manual is sure to lead to abject failure.

**views/servers/add.thtml**
%%(html)
<h1>Add Server</h1>
<form method="post" action="<?php echo $html->base; ?>?action=add">
<p>
IP Addr:
<?php echo $html->input('Server/ip_addr', array('size'=>'15')) ?>
<?php echo $html->tagErrorMsg('Server/ip_addr', 'IP address is required.') ?>
</p><p>
Owner:
<?php echo $html->input('Server/owner', array('size'=>'50')) ?>
<?php echo $html->tagErrorMsg('Server/owner', 'Owner is required.') ?>
</p><p>
City:
<?php echo $html->input('Server/city', array('size'=>'50')) ?>
</p><p>
State/Province:
<?php echo $html->input('Server/state', array('size'=>'2')) ?>
</p><p>
Country:
<?php echo $html->input('Server/country', array('size'=>'2')) ?>
<?php echo $html->tagErrorMsg('Server/country', 'Country is required.') ?>
</p><p>
Email (will be obfuscated):
<?php echo $html->input('Server/email', array('size'=>'50')) ?>
</p><p>
Comments:
<?php echo $html->textarea('Server/comments', array('rows'=>'2')) ?>
</p><p>
<?php echo $html->submit('Save') ?>
<?php echo $html->submit('Cancel', array('name'=>'data[Servers][action]')) ?>
</p></form>
%%
//Comments:// Handling the Cancel buttons was somewhat tricky.

**views/servers/modify.thtml**
%%(html)
<h1>Modify Server</h1>
<form method="post" action="<?php echo $html->base; ?>?action=modify">
<?php echo $html->hidden('Server/id'); ?>
<p>
IP Addr:
<?php echo $html->input('Server/ip_addr', array('size'=>'15')) ?>
<?php echo $html->tagErrorMsg('Server/ip_addr', 'IP address is required.') ?>
</p><p>
Owner:
<?php echo $html->input('Server/owner', array('size'=>'50')) ?>
<?php echo $html->tagErrorMsg('Server/owner', 'Owner is required.') ?>
</p><p>
City:
<?php echo $html->input('Server/city', array('size'=>'50')) ?>
</p><p>
State/Province:
<?php echo $html->input('Server/state', array('size'=>'2')) ?>
</p><p>
Country:
<?php echo $html->input('Server/country', array('size'=>'2')) ?>
<?php echo $html->tagErrorMsg('Server/country', 'Country is required.') ?>
</p><p>
Email (will be obfuscated):
<?php echo $html->input('Server/email', array('size'=>'50')) ?>
</p><p>
Comments:
<?php echo $html->textarea('Server/comments', array('rows'=>'2')) ?>
</p><p>
<?php echo $html->submit('Save') ?>
<?php echo $html->submit('Cancel', array('name'=>'data[Servers][action]')) ?>
</p></form>
%%
//Comments:// Straightforward, using the same trick as in ##add.thtml## to differentiate between Save and Cancel button clicks.

===Summary===
So, there you have it! A functioning DB application using Wikka as the presentation framework and [[http://www.cakephp.org | CakePHP]] as a modular MVC framework. Once one removes the ##config/database.php## file, this could be zipped/tarred up and distributed as a plugin action.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki