Skip to content

Instantly share code, notes, and snippets.

@bradley-holt
Created August 31, 2010 20:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bradley-holt/559700 to your computer and use it in GitHub Desktop.
Save bradley-holt/559700 to your computer and use it in GitHub Desktop.
<?php
/**
* Default
*
* @category Default
* @package Default_Model
* @copyright Copyright (c) 2005-2010 Found Line, Inc. (http://foundline.com/)
* @license http://foundline.com/legal/software-license New BSD License
*/
/**
* Entry Data Mapper
*
* @category Default
* @package Default_Model
* @copyright Copyright (c) 2005-2010 Found Line, Inc. (http://foundline.com/)
* @license http://foundline.com/legal/software-license New BSD License
*/
class Default_Model_EntryDataMapper
{
/**
* @var string
*/
private $_db;
/**
* @var string
*/
private $_host;
/**
* @var Zend_Http_Client
*/
private $_client;
/**
* @var Zend_Cache_Core
*/
private $_cache;
/**
* Entry to JSON
*
* @param Default_Model_Entry $entry
* @return string
*/
private function _entryToJson(Default_Model_Entry $entry)
{
return Zend_Json::encode($entry->toArray());
}
/**
* JSON to Entry
*
* @param string $json
* @return Default_Model_Entry
*/
private function _jsonToEntry($json)
{
return Default_Model_Entry::fromArray(Zend_Json::decode($json));
}
/**
* Prepare Index By Category
*
* @param Default_Model_Category $category
* @param string $order
*/
private function _prepareIndexByCategory(Default_Model_Category $category, $order)
{
switch($order) {
case 'published':
$this->_client->setUri($this->_host . $this->_db . '/_design/category/_view/published');
$this->_client->setParameterGet('descending', 'true');
$this->_client->setParameterGet(
'startkey',
Zend_Json::encode(
array (
'category' => $category->toArray(),
'published' => array (
'$t' => '9999-99-99T99:99:99-99:99',
),
)
)
);
$this->_client->setParameterGet(
'endkey',
Zend_Json::encode(
array (
'category' => $category->toArray(),
'published' => array (
'$t' => '0000-00-00T00:00:00-00:00',
),
)
)
);
break;
case 'index':
$this->_client->setUri($this->_host . $this->_db . '/_design/category/_view/index');
$this->_client->setParameterGet('descending', 'true');
$this->_client->setParameterGet(
'startkey',
Zend_Json::encode(
array (
'category' => $category->toArray(),
'i$index' => array (
'$t' => '999999',
),
)
)
);
$this->_client->setParameterGet(
'endkey',
Zend_Json::encode(
array (
'category' => $category->toArray(),
'i$index' => array (
'$t' => null,
),
)
)
);
break;
case 'rank':
$this->_client->setUri($this->_host . $this->_db . '/_design/category/_view/rank');
$this->_client->setParameterGet('descending', 'true');
$this->_client->setParameterGet(
'startkey',
Zend_Json::encode(
array (
'category' => $category->toArray(),
're$rank' => array (
'scheme' => $category->getScheme(),
'domain' => 'http://schemas.example.net/domain/2010#' . $category->getTerm(),
'$t' => '999999',
),
)
)
);
$this->_client->setParameterGet(
'endkey',
Zend_Json::encode(
array (
'category' => $category->toArray(),
're$rank' => array (
'scheme' => $category->getScheme(),
'domain' => 'http://schemas.example.net/domain/2010#' . $category->getTerm(),
'$t' => null,
),
)
)
);
break;
case 'single':
$this->_client->setUri($this->_host . $this->_db . '/_design/category/_view/single');
$this->_client->setParameterGet('descending', 'true');
$this->_client->setParameterGet(
'startkey',
Zend_Json::encode(
array (
'category' => $category->toArray(),
)
)
);
$this->_client->setParameterGet(
'endkey',
Zend_Json::encode(
array (
'category' => $category->toArray(),
)
)
);
break;
default;
throw new InvalidArgumentException('Invalid order name');
}
}
/**
* Construct
*
* @param string $db
* @param string $host
* @param Zend_Http_Client $client
* @return Default_Model_EntryDataMapper
*/
public function __construct(
$db,
$host = 'http://127.0.0.1:5984/',
Zend_Http_Client $client = null,
Zend_Cache_Core $cache = null
)
{
$this->_db = $db;
$this->_host = $host;
if (null === $client) {
$client = new Zend_Http_Client();
$client->setConfig(
array (
'keepalive' => true,
)
);
}
$this->_client = $client;
$this->_cache = $cache;
}
/**
* Index By Category Paginator
*
* @param Default_Model_Category $category
* @param string $order
* @return Zend_Paginator
*/
public function indexByCategoryPaginator(Default_Model_Category $category, $order)
{
$entryPaginatorAdapter = new Default_Model_EntryPaginatorAdapter($this, $category, $order);
return new Zend_Paginator($entryPaginatorAdapter);
}
/**
* Index By Category Count
*
* @param Default_Model_Category $category
* @param string $order
* @return integer
*/
public function indexByCategoryCount(Default_Model_Category $category, $order)
{
$this->_prepareIndexByCategory($category, $order);
$this->_client->setParameterGet('reduce', 'true');
$this->_client->setHeaders('Content-Type', 'application/json');
$response = $this->_client->request(Zend_Http_Client::GET);
$this->_client->resetParameters(true);
switch ($response->getStatus()) {
case 200:
// Do nothing
break;
default:
//TODO: throw a more specific exception
throw new Exception('Could not GET index of entries by category');
}
$responseArray = Zend_Json::decode($response->getBody());
if (0 == count($responseArray['rows'])) {
return 0;
}
return (integer)$responseArray['rows'][0]['value'];
}
/**
* Index By Category
*
* @param Default_Model_Category $category
* @param string $order
* @param integer $offset
* @param integer $itemCountPerPage
* @return array <Default_Model_Entry>
*/
public function indexByCategory(Default_Model_Category $category, $order, $offset = 0, $itemCountPerPage = -1)
{
$this->_prepareIndexByCategory($category, $order);
$this->_client->setParameterGet('reduce', 'false');
if ($offset > 0) {
$this->_client->setParameterGet('skip', $offset);
}
if ($itemCountPerPage >= 0) {
$this->_client->setParameterGet('limit', $itemCountPerPage);
}
$this->_client->setHeaders('Content-Type', 'application/json');
$response = $this->_client->request(Zend_Http_Client::GET);
$this->_client->resetParameters(true);
$responseArray = Zend_Json::decode($response->getBody());
switch ($response->getStatus()) {
case 200:
// Do nothing
break;
default:
//TODO: throw a more specific exception
throw new Exception('Could not GET index of entries by category');
}
$entries = array ();
foreach ($responseArray['rows'] as $row) {
$entries[] = $this->get($row['id']);
}
return $entries;
}
/**
* Get
*
* @param string $id
* @return Default_Model_Entry
*/
public function get($id)
{
$uri = $this->_host . $this->_db . '/' . urlencode($id);
$this->_client->setUri($uri);
$this->_client->setHeaders('Content-Type', 'application/json');
$cacheId = md5($uri);
/* @var $cachedEntry Default_Model_Entry */
$cachedEntry = false;
if (null !== $this->_cache) {
$cachedEntry = $this->_cache->load($cacheId);
if (false !== $cachedEntry && null !== $cachedEntry->getRev()) {
$this->_client->setHeaders('If-None-Match', '"' . $cachedEntry->getRev() . '"');
}
}
$response = $this->_client->request(Zend_Http_Client::GET);
$this->_client->resetParameters(true);
$entry = $cachedEntry;
switch ($response->getStatus()) {
case 200:
// OK
$entry = $this->_jsonToEntry($response->getBody());
if (null !== $this->_cache) {
$this->_cache->save($entry, $cacheId);
}
break;
case 304:
// Not Modified
if (false === $cachedEntry) {
throw new Exception('Not modified but no cached entry available');
}
$entry = $cachedEntry;
break;
case 404:
// Object Not Found
return null;
default:
//TODO: throw a more specific exception
throw new Exception('Could not GET entry');
}
return $entry;
}
/**
* Post
*
* @param Default_Model_Entry $entry
* @return Default_Model_Entry
*/
public function post(Default_Model_Entry $entry)
{
$this->_client->setUri($this->_host . $this->_db);
$this->_client->setHeaders('Content-Type', 'application/json');
$this->_client->setRawData($this->_entryToJson($entry));
$response = $this->_client->request(Zend_Http_Client::POST);
$this->_client->resetParameters(true);
$responseArray = Zend_Json::decode($response->getBody());
if (201 != $response->getStatus()) {
//TODO: throw a more specific exception
throw new Exception('Could not POST entry');
}
$entry->setId($responseArray['id']);
$entry->setRev($responseArray['rev']);
if (null !== $this->_cache) {
$uri = $this->_host . $this->_db . '/' . urlencode($entry->getId());
$cacheId = md5($uri);
$this->_cache->save($entry, $cacheId);
}
return $entry;
}
/**
* Put
*
* @param Default_Model_Entry $entry
* @return Default_Model_Entry
*/
public function put(Default_Model_Entry $entry)
{
$uri = $this->_host . $this->_db . '/' . urlencode($entry->getId());
$this->_client->setUri($uri);
$this->_client->setHeaders('Content-Type', 'application/json');
$this->_client->setRawData($this->_entryToJson($entry));
$response = $this->_client->request(Zend_Http_Client::PUT);
$this->_client->resetParameters(true);
$responseArray = Zend_Json::decode($response->getBody());
if (201 != $response->getStatus()) {
//TODO: throw a more specific exception
throw new Exception('Could not PUT entry');
}
$entry->setId($responseArray['id']);
$entry->setRev($responseArray['rev']);
if (null !== $this->_cache) {
$cacheId = md5($uri);
$this->_cache->save($entry, $cacheId);
}
return $entry;
}
/**
* Delete
*
* @param Default_Model_Entry $entry
* @return Default_Model_Entry
*/
public function delete(Default_Model_Entry $entry)
{
$uri = $this->_host . $this->_db . '/' . urlencode($entry->getId());
$this->_client->setUri($uri);
$this->_client->setHeaders('Content-Type', 'application/json');
$this->_client->setParameterGet('rev', $entry->getRev());
$response = $this->_client->request(Zend_Http_Client::DELETE);
$this->_client->resetParameters(true);
$responseArray = Zend_Json::decode($response->getBody());
if (200 != $response->getStatus()) {
//TODO: throw a more specific exception
throw new Exception('Could not DELETE entry');
}
$entry->setId($responseArray['id']);
$entry->setRev($responseArray['rev']);
if (null !== $this->_cache) {
$cacheId = md5($uri);
$this->_cache->remove($cacheId);
}
return $entry;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment