-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updated CouchDB datasource for CakePHP 2.0 #28
base: 2.0
Are you sure you want to change the base?
Changes from all commits
e3e0040
be17699
82faa72
4b564dd
8b190b2
6cf3f9b
ee24bb2
a9283c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,21 +17,36 @@ | |
* @since CakePHP Datasources v 0.3 | ||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php) | ||
*/ | ||
App::import('Core', 'HttpSocket'); | ||
App::uses('HttpSocket', 'Network/Http'); | ||
App::uses('DataSource', 'Model/Datasource'); | ||
|
||
/** | ||
* CouchDB Datasource | ||
* | ||
* @package datasources | ||
* @subpackage datasources.models.datasources | ||
*/ | ||
class CouchdbSource extends DataSource { | ||
class CouchDBSource extends DataSource { | ||
|
||
/** | ||
* Constructor | ||
* Start quote | ||
* | ||
* @var string | ||
*/ | ||
public $startQuote = null; | ||
|
||
/** | ||
* End quote | ||
* | ||
* @var string | ||
*/ | ||
public $endQuote = null; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param array $config Connection setup for CouchDB. | ||
* @param integer $autoConnect Autoconnect | ||
* @param integer $autoConnect Autoconnect. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. most of these punctuation changes are not required. If it's not a sentence ( |
||
* @return boolean | ||
*/ | ||
public function __construct($config = null, $autoConnect = true) { | ||
|
@@ -51,10 +66,10 @@ public function __construct($config = null, $autoConnect = true) { | |
} | ||
|
||
/** | ||
* Reconnects to the database with optional new settings | ||
* Reconnects to the database with optional new settings. | ||
* | ||
* @param array $config New settings | ||
* @return boolean Success | ||
* @param array $config New settings. | ||
* @return boolean Success. | ||
*/ | ||
public function reconnect($config = null) { | ||
$this->disconnect(); | ||
|
@@ -64,9 +79,9 @@ public function reconnect($config = null) { | |
} | ||
|
||
/** | ||
* Connects to the database. Options are specified in the $config instance variable | ||
* Connects to the database. Options are specified in the $config instance variable. | ||
* | ||
* @return boolean Connected | ||
* @return boolean Connected. | ||
*/ | ||
public function connect() { | ||
if ($this->connected !== true) { | ||
|
@@ -76,12 +91,12 @@ public function connect() { | |
if (isset($this->config['password'])) | ||
$this->config['request']['uri']['pass'] = $this->config['password']; | ||
|
||
$this->Socket = new HttpSocket($this->config); | ||
if (strpos($this->Socket->get(), 'couchdb') !== false) { | ||
try { | ||
$this->Socket = new HttpSocket($this->config); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is put in a protected method, |
||
$this->Socket->get(); | ||
$this->connected = true; | ||
} else { | ||
trigger_error(__('CouchDB Error: connection failed ', true), E_USER_WARNING); | ||
return $this->cakeError('missingConnection', array(array('code' => 500, 'className' => 'CouchdbSource'))); | ||
} catch (SocketException $e) { | ||
throw new MissingConnectionException(array('class' => $e->getMessage())); | ||
} | ||
} | ||
return $this->connected; | ||
|
@@ -92,7 +107,7 @@ public function connect() { | |
* connection is closed, and if DEBUG is turned on (equal to 2) displays the | ||
* log of stored data. | ||
* | ||
* @return boolean Disconnected | ||
* @return boolean Disconnected. | ||
*/ | ||
public function close() { | ||
if (Configure::read('debug') > 1) { | ||
|
@@ -102,9 +117,9 @@ public function close() { | |
} | ||
|
||
/** | ||
* Disconnect from the database | ||
* Disconnect from the database. | ||
* | ||
* @return boolean Disconnected | ||
* @return boolean Disconnected. | ||
*/ | ||
public function disconnect() { | ||
if (isset($this->results) && is_resource($this->results)) { | ||
|
@@ -115,19 +130,20 @@ public function disconnect() { | |
} | ||
|
||
/** | ||
* List of databases | ||
* List of databases. | ||
* | ||
* @return array Databases | ||
* @return array Databases. | ||
*/ | ||
public function listSources() { | ||
return $this->__decode($this->Socket->get($this->__uri('_all_dbs')), true); | ||
$databases = $this->__decode($this->Socket->get($this->__uri('_all_dbs')), true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like a noop change |
||
return $databases; | ||
} | ||
|
||
/** | ||
* Convenience method for DboSource::listSources(). | ||
* Returns the names of databases in lowercase. | ||
* | ||
* @return array Lowercase databases | ||
* @return array Lowercase databases. | ||
*/ | ||
public function sources($reset = false) { | ||
if ($reset === true) { | ||
|
@@ -137,10 +153,10 @@ public function sources($reset = false) { | |
} | ||
|
||
/** | ||
* Returns a description of the model (metadata) | ||
* Returns a description of the model (metadata). | ||
* | ||
* @param Model $model | ||
* @return array | ||
* @return array Schema. | ||
*/ | ||
public function describe($model) { | ||
return $model->schema; | ||
|
@@ -149,12 +165,12 @@ public function describe($model) { | |
/** | ||
* Creates a new document in the database. | ||
* If the primaryKey is declared, creates the document with the specified ID. | ||
* To create a new database: $this->__decode($this->Socket->put($this->__uri('databaseName'))); | ||
* To create a new database: $this->Model->curlPut('databaseName'); | ||
* | ||
* @param Model $model | ||
* @param array $fields An array of field names to insert. If null, $model->data will be used to generate the field names. | ||
* @param array $values An array with key values of the fields. If null, $model->data will be used to generate the field names. | ||
* @return boolean Success | ||
* @return boolean Success. | ||
*/ | ||
public function create($model, $fields = null, $values = null) { | ||
$data = $model->data; | ||
|
@@ -183,7 +199,7 @@ public function create($model, $fields = null, $values = null) { | |
* Reads data from a document. | ||
* | ||
* @param Model $model | ||
* @param array $queryData An array of information containing $queryData keys, similar to Model::find() | ||
* @param array $queryData An array of information containing $queryData keys, similar to Model::find(). | ||
* @param integer $recursive Level number of associations. | ||
* @return mixed False if an error occurred, otherwise an array of results. | ||
*/ | ||
|
@@ -224,7 +240,7 @@ public function read($model, $queryData = array(), $recursive = null) { | |
* Applies the rules to the document read. | ||
* | ||
* @param Model $model | ||
* @param array $queryData An array of information containing $queryData keys, similar to Model::find() | ||
* @param array $queryData An array of information containing $queryData keys, similar to Model::find(). | ||
* @param array $result Data read from the document. | ||
* @return mixed False if an error occurred, otherwise an array of results. | ||
*/ | ||
|
@@ -269,7 +285,7 @@ private function __readResult($model, $queryData, $result) { | |
* @param array $fields | ||
* @param array $values | ||
* @param mixed $conditions | ||
* @return boolean Success | ||
* @return boolean Success. | ||
*/ | ||
public function update($model, $fields = null, $values = null, $conditions = null) { | ||
$data = $model->data[$model->alias]; | ||
|
@@ -307,21 +323,36 @@ private function __idRevData(&$model, &$data) { | |
unset($data['rev']); | ||
} else if ($model->rev) { | ||
$data['_rev'] = $model->rev; | ||
} else { | ||
$data['_rev'] = $this->__lastRevision($model, $model->id); | ||
} | ||
} | ||
|
||
/** | ||
* Generates and executes a DELETE statement | ||
* The method searches for the latest revision of a document | ||
* | ||
* @param object $model | ||
* @param int $id | ||
* @return string Last revision of the document | ||
*/ | ||
private function __lastRevision(&$model, $id) { | ||
$result = $this->__decode($this->Socket->get($this->__uri($model, $id))); | ||
return $result->_rev; | ||
} | ||
|
||
/** | ||
* Generates and executes a DELETE statement. | ||
* | ||
* @param Model $model | ||
* @param mixed $conditions | ||
* @return boolean Success | ||
* @return boolean Success. | ||
*/ | ||
public function delete($model, $conditions = null) { | ||
$id = $model->id; | ||
$rev = $model->rev; | ||
|
||
if (!empty($id) && !empty($rev)) { | ||
if (!empty($id)) { | ||
if (empty($rev)) $rev = $this->__lastRevision($model, $id); | ||
$id_rev = $id . '/?rev=' . $rev; | ||
$result = $this->__decode($this->Socket->delete($this->__uri($model, $id_rev))); | ||
return $this->__checkOk($result); | ||
|
@@ -330,23 +361,37 @@ public function delete($model, $conditions = null) { | |
} | ||
|
||
/** | ||
* Returns an instruction to count data. (SQL, i.e. COUNT() or MAX()) | ||
* Returns an instruction to count data. (SQL, i.e. COUNT() or MAX()). | ||
* | ||
* @param model $model | ||
* @param string $func Lowercase name of SQL function, i.e. 'count' or 'max' | ||
* @param array $params Function parameters (any values must be quoted manually) | ||
* @return string An SQL calculation function | ||
* @param string $func Lowercase name of SQL function, i.e. 'count' or 'max'. | ||
* @param array $params Function parameters (any values must be quoted manually). | ||
* @return string An SQL calculation function. | ||
*/ | ||
public function calculate($model, $func, $params = array()) { | ||
return true; | ||
} | ||
|
||
/** | ||
* Gets full table name including prefix | ||
* Returns an object to represent a database expression in a query. Expression objects | ||
* are not sanitized or escaped. | ||
* | ||
* @param string $expression An arbitrary expression to be inserted into a query. | ||
* @return stdClass An object representing a database expression to be used in a query | ||
*/ | ||
public function expression($expression) { | ||
$obj = new stdClass(); | ||
$obj->type = 'expression'; | ||
$obj->value = $expression; | ||
return $obj; | ||
} | ||
|
||
/** | ||
* Gets full table name including prefix. | ||
* | ||
* @param mixed $model | ||
* @param boolean $quote | ||
* @return string Full name of table | ||
* @return string Full name of table. | ||
*/ | ||
public function fullTableName($model = null, $quote = true) { | ||
$table = null; | ||
|
@@ -361,22 +406,75 @@ public function fullTableName($model = null, $quote = true) { | |
} | ||
|
||
/** | ||
* Perform any function in CouchDB | ||
* Perform any function in CouchDB. | ||
* The first position of the $params array is used to mount the uri. | ||
* The second place in the $params array is used to assemble data from a POST or PUT. | ||
* The third parameter is used to decode the return json. | ||
* The fourth parameter is used to build an associative array. | ||
* | ||
* The method can be performed by a Model of the following ways: | ||
* | ||
* $this->Model->curlGet('_all_dbs'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does the model need to know that the command it is issuing is curl-based? |
||
* $this->Model->curlPut('document_name'); | ||
* $this->Model->curlPost('document_name', array('field' => 'value')); | ||
* $this->Model->curlDelete('document_name'); | ||
* $this->Model->curlPost('document_name', array('field' => 'value'), false); | ||
* $this->Model->curlPost('document_name', array('field' => 'value'), true , false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These examples all look like standard CRUD operations - with the wrong method name (I mean they look logically equivalent to calling save/delete) |
||
* | ||
* @param string $uri | ||
* @param array $post | ||
* @param string $method | ||
* @param array $params Parâmetros aceitos na ordem: uri, data, decode, assoc | ||
* @return object | ||
*/ | ||
public function query($uri, $post) { | ||
return $this->__decode($this->Socket->post($uri, $this->__encode($post))); | ||
public function query($method, $params) { | ||
list($uri, $data, $decode, $assoc) = $this->__queryParams($params); | ||
|
||
$request = array( | ||
'method' => strtoupper(str_replace('curl', '', $method)) | ||
); | ||
|
||
if (!empty($uri)) | ||
$request['uri'] = '/' . $uri; | ||
|
||
if (!empty($data)) | ||
$request['body'] = $this->__encode($data); | ||
|
||
$result = $this->Socket->request($request); | ||
|
||
if ($decode === true) { | ||
$result = $this->__decode($result, $assoc); | ||
} | ||
|
||
return $result; | ||
} | ||
|
||
/** | ||
* Get a URI | ||
* Construct the parameter of the query method. | ||
* | ||
* @param array $params | ||
* @return array | ||
*/ | ||
private function __queryParams($params) { | ||
if (isset($params[0])) $uri = $params[0]; | ||
else $uri = ''; | ||
|
||
if (isset($params[1])) $data = $params[1]; | ||
else $data = array(); | ||
|
||
if (isset($params[2])) $decode = $params[2]; | ||
else $decode = true; | ||
|
||
if (isset($params[3])) $assoc = $params[3]; | ||
else $assoc = true; | ||
|
||
return array($uri, $data, $decode, $assoc); | ||
} | ||
|
||
/** | ||
* Get a URI. | ||
* | ||
* @param mixed $model | ||
* @param string $params | ||
* @return string URI | ||
* @return string URI. | ||
*/ | ||
private function __uri($model = null, $params = null) { | ||
if (!is_null($params)) { | ||
|
@@ -386,17 +484,18 @@ private function __uri($model = null, $params = null) { | |
} | ||
|
||
/** | ||
* JSON encode | ||
* JSON encode. | ||
* | ||
* @param string json $data | ||
* @return string JSON | ||
* @return string JSON. | ||
*/ | ||
private function __encode($data) { | ||
return json_encode($data); | ||
} | ||
|
||
/** | ||
* JSON decode | ||
* JSON decode. | ||
* | ||
* @param string json $data | ||
* @param boolean $assoc If true, returns array. If false, returns object. | ||
* @return mixed Object or Array. | ||
|
@@ -406,7 +505,7 @@ private function __decode($data, $assoc = false) { | |
} | ||
|
||
/** | ||
* Checks if the result returned ok = true | ||
* Checks if the result returned ok = true. | ||
* | ||
* @param object $object | ||
* @return boolean | ||
|
@@ -415,3 +514,4 @@ private function __checkOk($object = null) { | |
return isset($object->ok) && $object->ok === true; | ||
} | ||
} | ||
?> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no new line at the end of this file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that necessary - Perhaps add a todo to rename the class which we can do at the next major release (rather than force this update to be further delayed until after the next major release)