00001 <?php
00044 require_once 'Object/Freezer/Storage.php';
00045
00057 class Object_Freezer_Storage_CouchDB extends Object_Freezer_Storage
00058 {
00062 protected $database;
00063
00067 protected $host;
00068
00072 protected $port;
00073
00085 public function __construct($database, Object_Freezer $freezer = NULL, Object_Freezer_Cache $cache = NULL, $useLazyLoad = FALSE, $host = 'localhost', $port = 5984)
00086 {
00087 parent::__construct($freezer, $cache, $useLazyLoad);
00088
00089
00090 if (!is_string($database)) {
00091 throw Object_Freezer_Util::getInvalidArgumentException(1, 'string');
00092 }
00093
00094
00095 if (!is_string($host)) {
00096 throw Object_Freezer_Util::getInvalidArgumentException(4, 'string');
00097 }
00098
00099
00100 if (!is_int($port)) {
00101 throw Object_Freezer_Util::getInvalidArgumentException(5, 'integer');
00102 }
00103
00104 $this->database = $database;
00105 $this->host = $host;
00106 $this->port = $port;
00107 }
00108
00114 protected function doStore(array $frozenObject)
00115 {
00116 $payload = array('docs' => array());
00117
00118 foreach ($frozenObject['objects'] as $_id => $_object) {
00119 if ($_object['isDirty'] !== FALSE) {
00120 $payload['docs'][] = array(
00121 '_id' => $_id,
00122 'class' => $_object['className'],
00123 'state' => $_object['state']
00124 );
00125 }
00126 }
00127
00128 if (!empty($payload['docs'])) {
00129 $this->send(
00130 'POST',
00131 '/' . $this->database . '/_bulk_docs',
00132 json_encode($payload)
00133 );
00134 }
00135 }
00136
00146 protected function doFetch($id, array &$objects = array())
00147 {
00148 $isRoot = empty($objects);
00149
00150 if (!isset($objects[$id])) {
00151 $response = $this->send('GET', '/' . $this->database . '/' . $id);
00152
00153 if (strpos($response['headers'], 'HTTP/1.0 200 OK') === 0) {
00154 $object = json_decode($response['body'], TRUE);
00155 } else {
00156 throw new RuntimeException(
00157 sprintf('Object with id "%s" could not be fetched.', $id)
00158 );
00159 }
00160
00161 $objects[$id] = array(
00162 'className' => $object['class'],
00163 'isDirty' => FALSE,
00164 'state' => $object['state']
00165 );
00166
00167 if (!$this->lazyLoad) {
00168 $this->fetchArray($object['state'], $objects);
00169 }
00170 }
00171
00172 if ($isRoot) {
00173 return array('root' => $id, 'objects' => $objects);
00174 }
00175 }
00176
00186 public function send($method, $url, $payload = NULL)
00187 {
00188 $socket = @fsockopen($this->host, $this->port, $errno, $errstr);
00189
00190 if (!$socket) {
00191 throw new RuntimeException($errno . ': ' . $errstr);
00192 }
00193
00194 $request = $method . ' ' . $url . " HTTP/1.0\r\nHost: localhost\r\n";
00195
00196 if ($payload !== NULL) {
00197 $request .= 'Content-Length: ' . strlen($payload) . "\r\n\r\n";
00198 $request .= $payload;
00199 }
00200
00201 $request .= "\r\n";
00202 fwrite($socket, $request);
00203
00204 $buffer = '';
00205
00206 while (!feof($socket)) {
00207 $buffer .= fgets($socket);
00208 }
00209
00210 list($headers, $body) = explode("\r\n\r\n", $buffer);
00211
00212 return array('headers' => $headers, 'body' => $body);
00213 }
00214 }