<?php

//-------------------------------------------------------------------
// gRESTbook.php: an example RESTy web service for a Guestbook
//-------------------------------------------------------------------
// 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
//-------------------------------------------------------------------

require_once 'Zend/Json.php';

require_once 
'gRESTbookData.php';
require_once 
'gRESTbookURL.php';

//-------------------------------------------------------------------
// This class models the incoming request; basically it's just
// parsing up the 'CGI' variables and placing them in the class's
// properties.
//-------------------------------------------------------------------
class Request {

    
//-------------------------------------------------------------------
    // get a 'CGI' variable; return blank if not there
    //-------------------------------------------------------------------
    
private function getServerVar($key) {
        if (isset(
$_SERVER[$key])) return $_SERVER[$key];
        return 
'';
    }

    
//-------------------------------------------------------------------
    // get the 'CGI' variables we're interested in, and normalize
    //-------------------------------------------------------------------
    
public function __construct() {
        
$this->requestMethod  $this->getServerVar('REQUEST_METHOD');
        
$this->queryString    $this->getServerVar('QUERY_STRING');
        
$this->pathInfo       $this->getServerVar('PATH_INFO');
        
$this->accept         $this->getServerVar('HTTP_ACCEPT');
        
$this->acceptEncoding $this->getServerVar('HTTP_ACCEPT_ENCODING');
        
$this->acceptCharset  $this->getServerVar('HTTP_ACCEPT_CHARSET');
        
$this->contentType    $this->getServerVar('CONTENT_TYPE');
        
        
// if no path info provided, set to /
        
if ("" == $this->pathInfo$this->pathInfo "/";
        
        
// get the next path element in the path info;
        // for the container itself (no path element provided),
        // this will be the empty string
        
$pieces explode('/'$this->pathInfo);
        
$this->resourceName $pieces[1];
        
    }
    
    
//-------------------------------------------------------------------
    // diagnostic method to dump the variables to the HTTP response,
    // and leave.
    //-------------------------------------------------------------------
    
public function dump() {
        
header('Content-Type: text/plain');
        echo (string) 
$this;
        exit;
    }
    
    
//-------------------------------------------------------------------
    // nice human readable description of the class
    //-------------------------------------------------------------------
    
public function __toString() {
        
$result  __CLASS__ "{\n";
        
$result .= "  requestMethod:  $this->requestMethod\n";
        
$result .= "  queryString:    $this->queryString\n";
        
$result .= "  pathInfo:       $this->pathInfo\n";
        
$result .= "  resourceName:   $this->resourceName\n";
        
$result .= "  accept:         $this->accept\n";
        
$result .= "  acceptEncoding: $this->acceptEncoding\n";
        
$result .= "  acceptCharset:  $this->acceptCharset\n";
        
$result .= "  contentType:    $this->contentType\n";
        
$result .= "}";
        
        return 
$result;
    }
    
}


//-------------------------------------------------------------------
// function to set the HTTP status code, and leave; used for
// error returns
//-------------------------------------------------------------------
function httpStatus($code$message) {
    
header("HTTP/1.1 $code $message");
    exit;
}

//-------------------------------------------------------------------
// de-multiplex the service requests against the collection
//-------------------------------------------------------------------
function handleCollection($request) {
    switch (
$request->requestMethod) {
        case 
'GET':
            
handleCollectionGet($request);
            break;
        
        case 
'POST':
            
handleCollectionPost($request);
            break;
        
        default:
            
httpStatus(405"Method Not Allowed");
            break;
    }
    
}

//-------------------------------------------------------------------
// de-multiplex the service requests for items
//-------------------------------------------------------------------
function handleItem($request$resourceName) {
    
    switch (
$request->requestMethod) {
        case 
'GET':
            
handleItemGet($request$resourceName);
            break;
        
        case 
'PUT':
            
handleItemPut($request$resourceName);
            break;
        
        case 
'DELETE':
            
handleItemDelete($request$resourceName);
            break;
    
        default:
            
httpStatus(405"Method Not Allowed");
            break;
    }
}

//-------------------------------------------------------------------
// return a list of entries in the collection
//-------------------------------------------------------------------
function handleCollectionGet($request) {
    
$db      $request->db;
    
$entries $db->query();
    
    if (
strstr($request->accept,'text/json')) {
        
header('Content-Type: text/json');
        print 
Zend_Json::encode($entries);
        return;
    }
    
    
header('Content-Type: text/html');
    print 
"<ul>\n";
    
    foreach (
$entries as $entry) {
        
$line '<li><a href="' $entry '">' $entry "</a></li>\n";
    }
    
    print 
"</ul>\n";
}

//-------------------------------------------------------------------
// add a new entry to the collection
//-------------------------------------------------------------------
function handleCollectionPost($request) {
    
$db $request->db;
    
    if (
$request->ContentType != 'text/json') {
        
httpStatus(415'Unsupported Media Type');
    }
    
    
$data file_get_contents("php://input");
    
$entry GRESTbookEntry::fromJSON($data);
    
$db->create($entry);
    
    
header('Location: ' gRESTbookURL '/' $entry->id);
}

//-------------------------------------------------------------------
// get an entry from the collection
//-------------------------------------------------------------------
function handleItemGet($request$resourceName) {
    
$db $request->db;
    
    
$entry $db->read($resourceName);
    if (
null == $entry) {
        
httpStatus(404'Not found');
        return;
    }
    
    if (
strstr($request->accept,'text/json')) {
        
header('Content-Type: text/json');
        
header('ETag: ' $entry->eTag);
        
header('Last-Modified' date('r'$entry->dateModified));
        print 
$entry->toJSON();
        return;
    }
    
    
header('Content-Type: text/html');
    
header('ETag: ' $entry->eTag);
    
header('Last-Modified' date('r'$entry->dateModified));
    
    print 
'<h1>' $entry->id "</h1>\n";
    print 
'<span class="author">'  $entry->author  "</span> :\n";
    print 
'<span class="message">' $entry->message "</span> :\n";
        
}

//-------------------------------------------------------------------
// update an entry in the collection
//-------------------------------------------------------------------
function handleItemPut($request$resourceName) {
}

//-------------------------------------------------------------------
// delete an entry in the collection
//-------------------------------------------------------------------
function handleItemDelete($request$resourceName) {
}

//-------------------------------------------------------------------
// main processing starts here
//-------------------------------------------------------------------

//-------------------------------------------------------------------
// create the data accessor object
//-------------------------------------------------------------------
$db = new GRESTbookDB();

//-------------------------------------------------------------------
// create the request object
//-------------------------------------------------------------------
$request = new Request();
$request->db $db;

// $request->dump();

// de-multiplex the request into either a collection or entry operation
if ('' == $request->resourceName) {
    
handleCollection($request);
}
else {
    
handleItem($request$request->resourceName);
}

//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
// phpinfo();

?>