|
<?php
//------------------------------------------------------------------- // gRESTbookData.php: handle the data for gRESTbook //------------------------------------------------------------------- // For more info, see: http://muellerware.org/projects/gRESTbook/ //------------------------------------------------------------------- // Copyright (c) 2007 Patrick Mueller // Using the MIT license: // http://www.opensource.org/licenses/mit-license.php //------------------------------------------------------------------- // 2007/03/xx - Patrick Mueller - pmuellr@yahoo.com //-------------------------------------------------------------------
// json encoder/decoder from Zend Framework require_once 'Zend/Json.php';
//------------------------------------------------------------------- // This class models the data associated with the gRESTbook // application. //------------------------------------------------------------------- class GRESTbookEntry { // first three fields are meta-data; end up in the URL or // headers of HTTP requests/responses public $id; // integer: id of the entry public $dateModified; // integer: epoch seconds when entry modified public $eTag; // string: hash of author::message
// next two fields are the business data for the class public $author; // string: author of the entry public $message; // string: message of the entry //--------------------------------------------------------------- // Create from a JSON string - return a new instance of this // class given a JSON string, but only sets the author and // message fields; remaining fields from HTTP request info. // Throw exception if invalid. //--------------------------------------------------------------- static public function fromJSON($json) { $map = Zend_Json::decode($json); if (!isset($map['author'])) throw new Exception('author property is not set'); if (!isset($map['message'])) throw new Exception('message property is not set'); $result = new GRESTbookEntry(); $result->author = $map['author']; $result->message = $map['message'];
$result->validate(); return $result; } //--------------------------------------------------------------- // Throw an exception if the business data is invalid. //--------------------------------------------------------------- public function validate() { if (!is_string($this->author)) throw new Exception('author is not a string'); if (!is_string($this->message)) throw new Exception('message is not a string');
if ($this->author == '') throw new Exception('author is an empty string'); if ($this->message == '') throw new Exception('message is an empty string'); return ''; }
//--------------------------------------------------------------- // Return a hash of the object (used for eTag) //--------------------------------------------------------------- public function hash() { return md5($this->author . '::' . $this->message); } //--------------------------------------------------------------- // Return JSON string, consisting of the author and message // fields (remaining fields available via HTTP request or response). //--------------------------------------------------------------- public function toJSON() { $map = array(); $map['author'] = $this->author; $map['message'] = $this->message; return Zend_Json::encode($map); } //--------------------------------------------------------------- // Return a human readable string representation //--------------------------------------------------------------- public function __toString() { $result = __CLASS__ . '{' . "\n"; $result .= ' id: ' . $this->id . "\n"; $result .= ' dateModified: ' . $this->dateModified . "\n"; $result .= ' eTag: ' . $this->eTag . "\n"; $result .= ' author: ' . $this->author . "\n"; $result .= ' message: ' . $this->message . "\n"; $result .= '}'; return $result; } }
//------------------------------------------------------------------- // This class handles the database access for the GRESTbook data. //------------------------------------------------------------------- class GRESTbookDB {
// our PDO database handle private $db; //--------------------------------------------------------------- // Connect to the database when the object is instantiated //--------------------------------------------------------------- public function __construct() { $this->db = new PDO('sqlite:gRESTbook.sq3', '', ''); } //--------------------------------------------------------------- // Disconnect from the database when object is GC'd //--------------------------------------------------------------- public function __destruct() { $this->db = null; }
//--------------------------------------------------------------- // CREATE a new GRESTbook entry. Expects the author and message // fields to be set; dateModified, eTag and id will be available // in the object returned, which will be the same object passed // in. // // GRESTbookEntry on input: // id: ignored // dateModified: ignored // eTag ignored // author: value to set in DB // message: value to set in DB // // GRESTbookEntry on output: // id: id of new entry // dateModified: current date // eTag hash of author::message // author: unchanged from input // message: unchanged from output // // Returns the input object, suitably updated, on success, // and null on failure. // // Can also throw an exception, including if the data is invalid. //--------------------------------------------------------------- public function create($gRESTbookEntry) {
// validate input $gRESTbookEntry->validate();
$db = $this->db; // set up the SQL statement $cmd = <<<CMD insert into ENTRIES (ID, DATE_MODIFIED, ETAG, AUTHOR, MESSAGE) values (?,?,?,?,?) CMD; $stmt = $db->prepare($cmd); if (false == $stmt) { $err = $db->errorInfo(); throw new Exception("Error creating insert statement: " . $err[2]); }
// set the dateModified and eTag fields $newDate = time(); $newETag = $gRESTbookEntry->hash();
// parameters for prepared statement $vars = array( NULL, $newDate, $newETag, $gRESTbookEntry->author, $gRESTbookEntry->message ); // execute, returning early if failure $result = $stmt->execute($vars); if (!$result) { return null; } // if succcess, update fields in our data $gRESTbookEntry->id = $db->lastInsertId(); $gRESTbookEntry->dateModified = $newDate; $gRESTbookEntry->eTag = $newETag; return $gRESTbookEntry; } //--------------------------------------------------------------- // READ a GRESTbook entry given an id. // // GRESTbookEntry on output: // id: same as input $id // dateModified: value from DB // eTag value from DB // author: value from DB // message: value from DB // // Returns a fully populated object if found, otherwise null. // // Can also throw an exception. //--------------------------------------------------------------- public function read($id) { $db = $this->db; // setup the SQL statement $cmd = <<<CMD select DATE_MODIFIED, ETAG, AUTHOR, MESSAGE from ENTRIES where ID = ? CMD; $stmt = $db->prepare($cmd); if (false == $stmt) { $err = $db->errorInfo(); throw new Exception("Error creating select statement: " . $err[2]); } // execute the SQL $stmt->execute(array($id)); $fetchResult = $stmt->fetch(PDO::FETCH_NUM); // early return if we didn't find it if (!$fetchResult) { return null; }
// found the entry! Set it up. $result = new GRESTbookEntry(); $result->id = $id; $result->dateModified = $fetchResult[0]; $result->eTag = $fetchResult[1]; $result->author = $fetchResult[2]; $result->message = $fetchResult[3];
return $result; } //--------------------------------------------------------------- // UPDATE a GRESTbook entry. Note that to prevent entries // from inadvertantly being updated, the eTag value passed in // must equal the eTag value of the entry currently in the // database. // // GRESTbookEntry on input: // id: id of entry to update // dateModified: ignored // eTag eTag of previous version of GRESTbookEntry // author: value to set in DB // message: value to set in DB // // GRESTbookEntry on input: // id: unchanged from input // dateModified: current date // eTag hash of new author::message // author: unchanged from input // message: unchanged from input // // Returns the input object, suitably updated, on success, // and null on failure. // // Can also throw an exception, including if the data is invalid. //--------------------------------------------------------------- public function update($gRESTbookEntry) { // validate the data $gRESTbookEntry->validate(); $db = $this->db; // new eTag and dateModified fields $newETag = $gRESTbookEntry->hash(); $newDate = time(); // setup the SQL $cmd = <<<CMD update ENTRIES SET DATE_MODIFIED = ?, ETAG = ?, AUTHOR = ?, MESSAGE = ? where (ID == ?) AND (ETAG == ?) CMD; $stmt = $db->prepare($cmd); if (false == $stmt) { $err = $db->errorInfo(); throw new Exception("Error creating update statement: " . $err[2]); } // execute the SQL $vars = array( $newDate, $newETag, $gRESTbookEntry->author, $gRESTbookEntry->message, $gRESTbookEntry->id, $gRESTbookEntry->eTag, ); $result = $stmt->execute($vars); // return early if not found. if (0 == $result) { return null; } if (0 == $stmt->rowCount()) { return null; }
// update the dateModified and eTag fiels in the object $gRESTbookEntry->dateModified = time(); $gRESTbookEntry->eTag = $newETag; return $gRESTbookEntry; }
//--------------------------------------------------------------- // DELETE a GRESTbook entry. Note that to prevent entries // from inadvertantly being updated, the eTag value passed in // must equal the eTag value of the entry currently in the // database. // // Returns true if successful, false on failure. //--------------------------------------------------------------- public function delete($id, $eTag) { $db = $this->db; // setup SQL $cmd = <<<CMD delete from ENTRIES where (ID = ?) AND (ETAG = ?) CMD; $stmt = $db->prepare($cmd); if (false == $stmt) { $err = $db->errorInfo(); throw new Exception("Error creating delete statement: " . $err[2]); } // execute SQL $result = $stmt->execute(array($id, $eTag)); // return early on error if (!$result) { return false; } if (0 == $stmt->rowCount()) { return false; }
return true; }
//--------------------------------------------------------------- // READ the GRESTbook entries. // // Returns an array of id's to the GRESTBook entries. //--------------------------------------------------------------- public function query() { $db = $this->db; // setup the SQL $cmd = <<<CMD select ID from ENTRIES CMD; $stmt = $db->prepare($cmd); if (false == $stmt) { $err = $db->errorInfo(); throw new Exception("Error creating select statement: " . $err[2]); } // execute the SQL, return the output $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
return $result; } }
|