| 1 |
1
|
kore |
<?php |
|
| 2 |
↓
|
kore |
/** |
|
| 3 |
2
|
kore |
* phpillow CouchDB backend |
|
| 4 |
1
|
kore |
* |
|
| 5 |
2
|
kore |
* This file is part of phpillow. |
|
| 6 |
1
|
kore |
* |
|
| 7 |
3
|
kore |
* phpillow is free software; you can redistribute it and/or modify it under |
|
| 8 |
↓
|
kore |
* the terms of the GNU Lesser General Public License as published by the Free |
|
| 9 |
↓
|
kore |
* Software Foundation; version 3 of the License. |
|
| 10 |
1
|
kore |
* |
|
| 11 |
3
|
kore |
* phpillow is distributed in the hope that it will be useful, but WITHOUT ANY |
|
| 12 |
↓
|
kore |
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
| 13 |
↓
|
kore |
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
|
| 14 |
↓
|
kore |
* more details. |
|
| 15 |
1
|
kore |
* |
|
| 16 |
3
|
kore |
* You should have received a copy of the GNU Lesser General Public License |
|
| 17 |
↓
|
kore |
* along with phpillow; if not, write to the Free Software Foundation, Inc., 51 |
|
| 18 |
↓
|
kore |
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 19 |
1
|
kore |
* |
|
| 20 |
↓
|
kore |
* @package Core |
|
| 21 |
4
|
kore |
* @version $Revision: 159 $ |
|
| 22 |
3
|
kore |
* @license http://www.gnu.org/licenses/lgpl-3.0.txt LGPL |
|
| 23 |
1
|
kore |
*/ |
|
| 24 |
↓
|
kore |
|
|
| 25 |
↓
|
kore |
/** |
|
| 26 |
↓
|
kore |
* Basic couch DB connection handling class |
|
| 27 |
↓
|
kore |
* |
|
| 28 |
159
|
kore |
* Default connection handler using PHPs stream wrappers. |
|
| 29 |
59
|
kore |
* |
|
| 30 |
1
|
kore |
* @package Core |
|
| 31 |
4
|
kore |
* @version $Revision: 159 $ |
|
| 32 |
3
|
kore |
* @license http://www.gnu.org/licenses/lgpl-3.0.txt LGPL |
|
| 33 |
1
|
kore |
*/ |
|
| 34 |
63
|
kore |
abstract class phpillowConnection |
|
| 35 |
1
|
kore |
{ |
|
| 36 |
↓
|
kore |
/** |
|
| 37 |
9
|
kore |
* CouchDB connection options |
|
| 38 |
159
|
kore |
* |
|
| 39 |
9
|
kore |
* @var array |
|
| 40 |
1
|
kore |
*/ |
|
| 41 |
9
|
kore |
protected $options = array( |
|
| 42 |
↓
|
kore |
'host' => 'localhost', |
|
| 43 |
↓
|
kore |
'port' => 5984, |
|
| 44 |
↓
|
kore |
'ip' => '127.0.0.1', |
|
| 45 |
56
|
kore |
'timeout' => .01, |
|
| 46 |
21
|
kore |
'keep-alive' => true, |
|
| 47 |
24
|
kore |
'http-log' => false, |
|
| 48 |
106
|
kore |
'username' => null, |
|
| 49 |
↓
|
kore |
'password' => null, |
|
| 50 |
9
|
kore |
); |
|
| 51 |
1
|
kore |
|
|
| 52 |
97
|
kore |
/** |
|
| 53 |
1
|
kore |
* Currently used database |
|
| 54 |
↓
|
kore |
* |
|
| 55 |
↓
|
kore |
* @var string |
|
| 56 |
↓
|
kore |
*/ |
|
| 57 |
↓
|
kore |
protected static $database = null; |
|
| 58 |
↓
|
kore |
|
|
| 59 |
↓
|
kore |
/** |
|
| 60 |
3
|
kore |
* Instance of phpillowConnection for singleton implementation. |
|
| 61 |
1
|
kore |
* |
|
| 62 |
3
|
kore |
* @var phpillowConnection |
|
| 63 |
1
|
kore |
*/ |
|
| 64 |
↓
|
kore |
protected static $instance = null; |
|
| 65 |
↓
|
kore |
|
|
| 66 |
↓
|
kore |
/** |
|
| 67 |
↓
|
kore |
* Array containing the list of allowed HTTP methods to interact with couch |
|
| 68 |
↓
|
kore |
* server. |
|
| 69 |
↓
|
kore |
* |
|
| 70 |
↓
|
kore |
* @var array |
|
| 71 |
↓
|
kore |
*/ |
|
| 72 |
↓
|
kore |
protected static $allowedMethods = array( |
|
| 73 |
↓
|
kore |
'DELETE' => true, |
|
| 74 |
↓
|
kore |
'GET' => true, |
|
| 75 |
↓
|
kore |
'POST' => true, |
|
| 76 |
↓
|
kore |
'PUT' => true, |
|
| 77 |
↓
|
kore |
); |
|
| 78 |
↓
|
kore |
|
|
| 79 |
↓
|
kore |
/** |
|
| 80 |
↓
|
kore |
* Construct a couch DB connection |
|
| 81 |
↓
|
kore |
* |
|
| 82 |
↓
|
kore |
* Construct a couch DB connection from basic connection parameters for one |
|
| 83 |
124
|
kore |
* given database. |
|
| 84 |
1
|
kore |
* |
|
| 85 |
124
|
kore |
* In most cases you want to use the createInstance() method to register |
|
| 86 |
↓
|
kore |
* the connection instance, so it can be used by the document and view |
|
| 87 |
↓
|
kore |
* classes. If you want to operate directly on a raw connection you may |
|
| 88 |
↓
|
kore |
* also instantiate it directly, though. |
|
| 89 |
↓
|
kore |
* |
|
| 90 |
1
|
kore |
* @param string $host |
|
| 91 |
↓
|
kore |
* @param int $port |
|
| 92 |
3
|
kore |
* @return phpillowConnection |
|
| 93 |
1
|
kore |
*/ |
|
| 94 |
124
|
kore |
public function __construct( $host, $port, $username = null, $password = null, $ip = null ) |
|
| 95 |
1
|
kore |
{ |
|
| 96 |
106
|
kore |
$this->options['host'] = (string) $host; |
|
| 97 |
↓
|
kore |
$this->options['port'] = (int) $port; |
|
| 98 |
↓
|
kore |
$this->options['username'] = $username; |
|
| 99 |
↓
|
kore |
$this->options['password'] = $password; |
|
| 100 |
1
|
kore |
|
|
| 101 |
106
|
kore |
if ($ip === null) |
|
| 102 |
↓
|
kore |
{ |
|
| 103 |
↓
|
kore |
$this->options['ip'] = gethostbyname($this->options['host']); |
|
| 104 |
↓
|
kore |
} |
|
| 105 |
↓
|
kore |
else |
|
| 106 |
↓
|
kore |
{ |
|
| 107 |
↓
|
kore |
$this->options['ip'] = $ip; |
|
| 108 |
↓
|
kore |
} |
|
| 109 |
1
|
kore |
} |
|
| 110 |
↓
|
kore |
|
|
| 111 |
↓
|
kore |
/** |
|
| 112 |
9
|
kore |
* Set option value |
|
| 113 |
↓
|
kore |
* |
|
| 114 |
↓
|
kore |
* Set the value for an connection option. Throws an |
|
| 115 |
↓
|
kore |
* phpillowOptionException for unknown options. |
|
| 116 |
159
|
kore |
* |
|
| 117 |
↓
|
kore |
* @param string $option |
|
| 118 |
↓
|
kore |
* @param mixed $value |
|
| 119 |
9
|
kore |
* @return void |
|
| 120 |
↓
|
kore |
*/ |
|
| 121 |
↓
|
kore |
public function setOption( $option, $value ) |
|
| 122 |
↓
|
kore |
{ |
|
| 123 |
↓
|
kore |
switch ( $option ) |
|
| 124 |
↓
|
kore |
{ |
|
| 125 |
↓
|
kore |
case 'keep-alive': |
|
| 126 |
↓
|
kore |
$this->options[$option] = (bool) $value; |
|
| 127 |
↓
|
kore |
break; |
|
| 128 |
↓
|
kore |
|
|
| 129 |
24
|
kore |
case 'http-log': |
|
| 130 |
106
|
kore |
case 'password': |
|
| 131 |
↓
|
kore |
case 'username': |
|
| 132 |
24
|
kore |
$this->options[$option] = $value; |
|
| 133 |
↓
|
kore |
break; |
|
| 134 |
↓
|
kore |
|
|
| 135 |
9
|
kore |
default: |
|
| 136 |
↓
|
kore |
throw new phpillowOptionException( $option ); |
|
| 137 |
↓
|
kore |
} |
|
| 138 |
↓
|
kore |
} |
|
| 139 |
↓
|
kore |
|
|
| 140 |
↓
|
kore |
/** |
|
| 141 |
1
|
kore |
* Create a new couch DB connection instance. |
|
| 142 |
↓
|
kore |
* |
|
| 143 |
↓
|
kore |
* Static method to create a new couch DB connection instance. This method |
|
| 144 |
↓
|
kore |
* should be used to configure the connection for later use. |
|
| 145 |
↓
|
kore |
* |
|
| 146 |
↓
|
kore |
* The host and its port default to localhost:5984. |
|
| 147 |
↓
|
kore |
* |
|
| 148 |
97
|
kore |
* Optionally the class name of the called class can be provided. By |
|
| 149 |
↓
|
kore |
* default the better working "custom connection" connection handler is |
|
| 150 |
↓
|
kore |
* instantiated and used. The stream based connection handler is slower and |
|
| 151 |
↓
|
kore |
* might not work at all. |
|
| 152 |
↓
|
kore |
* |
|
| 153 |
1
|
kore |
* @param string $host |
|
| 154 |
↓
|
kore |
* @param int $port |
|
| 155 |
106
|
kore |
* @param string $username |
|
| 156 |
↓
|
kore |
* @param string $password |
|
| 157 |
97
|
kore |
* @param string $called |
|
| 158 |
1
|
kore |
* @return void |
|
| 159 |
↓
|
kore |
*/ |
|
| 160 |
106
|
kore |
public static function createInstance( $host = '127.0.0.1', $port = 5984, $username = null, $password = null, $called = "phpillowCustomConnection" ) |
|
| 161 |
1
|
kore |
{ |
|
| 162 |
↓
|
kore |
// Prevent from reestablishing connection during one run, without |
|
| 163 |
↓
|
kore |
// explicit cleanup before. |
|
| 164 |
↓
|
kore |
if ( self::$instance !== null ) |
|
| 165 |
↓
|
kore |
{ |
|
| 166 |
3
|
kore |
throw new phpillowConnectionException( |
|
| 167 |
1
|
kore |
'Connection already established.', |
|
| 168 |
↓
|
kore |
array() |
|
| 169 |
↓
|
kore |
); |
|
| 170 |
↓
|
kore |
} |
|
| 171 |
↓
|
kore |
|
|
| 172 |
159
|
kore |
// // Default to custom connection, if root class has been called. This |
|
| 173 |
94
|
kore |
// // currently is the safer default. |
|
| 174 |
↓
|
kore |
// if ( !$called ) |
|
| 175 |
↓
|
kore |
// { |
|
| 176 |
↓
|
kore |
// $called = 'phpillowCustomConnection'; |
|
| 177 |
↓
|
kore |
// } |
|
| 178 |
63
|
kore |
|
|
| 179 |
94
|
kore |
|
|
| 180 |
1
|
kore |
// Create connection and store it in static property to be accessible |
|
| 181 |
↓
|
kore |
// by static getInstance() method. |
|
| 182 |
106
|
kore |
self::$instance = new $called( $host, $port, $username, $password ); |
|
| 183 |
1
|
kore |
} |
|
| 184 |
↓
|
kore |
|
|
| 185 |
↓
|
kore |
/** |
|
| 186 |
↓
|
kore |
* Set database to use |
|
| 187 |
↓
|
kore |
* |
|
| 188 |
↓
|
kore |
* Set the name of database to use. You do not need to provide this as a |
|
| 189 |
↓
|
kore |
* path, but only its name. |
|
| 190 |
159
|
kore |
* |
|
| 191 |
↓
|
kore |
* @param string $database |
|
| 192 |
1
|
kore |
* @return void |
|
| 193 |
↓
|
kore |
*/ |
|
| 194 |
↓
|
kore |
public static function setDatabase( $database ) |
|
| 195 |
↓
|
kore |
{ |
|
| 196 |
↓
|
kore |
self::$database = '/' . $database . '/'; |
|
| 197 |
↓
|
kore |
} |
|
| 198 |
↓
|
kore |
|
|
| 199 |
↓
|
kore |
/** |
|
| 200 |
↓
|
kore |
* Return name of the currently used database |
|
| 201 |
159
|
kore |
* |
|
| 202 |
1
|
kore |
* Return name of the currently used database |
|
| 203 |
159
|
kore |
* |
|
| 204 |
1
|
kore |
* @return string |
|
| 205 |
↓
|
kore |
*/ |
|
| 206 |
↓
|
kore |
public static function getDatabase() |
|
| 207 |
↓
|
kore |
{ |
|
| 208 |
↓
|
kore |
if ( self::$database === null ) |
|
| 209 |
↓
|
kore |
{ |
|
| 210 |
4
|
kore |
throw new phpillowNoDatabaseException(); |
|
| 211 |
1
|
kore |
} |
|
| 212 |
↓
|
kore |
|
|
| 213 |
↓
|
kore |
return self::$database; |
|
| 214 |
↓
|
kore |
} |
|
| 215 |
↓
|
kore |
|
|
| 216 |
↓
|
kore |
/** |
|
| 217 |
↓
|
kore |
* Get configured couch DB connection instance |
|
| 218 |
↓
|
kore |
* |
|
| 219 |
↓
|
kore |
* Get configured couch DB connection instance |
|
| 220 |
↓
|
kore |
* |
|
| 221 |
3
|
kore |
* @return phpillowConnection |
|
| 222 |
1
|
kore |
*/ |
|
| 223 |
↓
|
kore |
public static function getInstance() |
|
| 224 |
↓
|
kore |
{ |
|
| 225 |
159
|
kore |
// Check if connection has been properly configured, and bail out |
|
| 226 |
1
|
kore |
// otherwise. |
|
| 227 |
↓
|
kore |
if ( self::$instance === null ) |
|
| 228 |
↓
|
kore |
{ |
|
| 229 |
3
|
kore |
throw new phpillowConnectionException( |
|
| 230 |
1
|
kore |
'No connection to database configured.', |
|
| 231 |
↓
|
kore |
array() |
|
| 232 |
↓
|
kore |
); |
|
| 233 |
↓
|
kore |
} |
|
| 234 |
↓
|
kore |
|
|
| 235 |
159
|
kore |
// If a connection has been configured properly, just return it |
|
| 236 |
1
|
kore |
return self::$instance; |
|
| 237 |
↓
|
kore |
} |
|
| 238 |
↓
|
kore |
|
|
| 239 |
↓
|
kore |
/** |
|
| 240 |
↓
|
kore |
* HTTP method request wrapper |
|
| 241 |
↓
|
kore |
* |
|
| 242 |
108
|
kore |
* Wraps the HTTP method requests to interact with the couch server. The |
|
| 243 |
1
|
kore |
* supported methods are: |
|
| 244 |
↓
|
kore |
* - GET |
|
| 245 |
↓
|
kore |
* - DELETE |
|
| 246 |
↓
|
kore |
* - POST |
|
| 247 |
↓
|
kore |
* - PUT |
|
| 248 |
↓
|
kore |
* |
|
| 249 |
108
|
kore |
* Each request takes the full request path as the first parameter and |
|
| 250 |
↓
|
kore |
* optionally data as the second parameter. The path must include the |
|
| 251 |
↓
|
kore |
* database name, if the request should operate on a specific database. |
|
| 252 |
1
|
kore |
* |
|
| 253 |
108
|
kore |
* The requests will return a object wrapping the server response. |
|
| 254 |
↓
|
kore |
* |
|
| 255 |
1
|
kore |
* @param string $method |
|
| 256 |
↓
|
kore |
* @param array $params |
|
| 257 |
2
|
kore |
* @return phpillow... |
|
| 258 |
1
|
kore |
*/ |
|
| 259 |
↓
|
kore |
public function __call( $method, $params ) |
|
| 260 |
↓
|
kore |
{ |
|
| 261 |
↓
|
kore |
// Check if request method is an allowed HTTP request method. |
|
| 262 |
↓
|
kore |
$method = strtoupper( $method ); |
|
| 263 |
↓
|
kore |
if ( !isset( self::$allowedMethods[$method] ) ) |
|
| 264 |
↓
|
kore |
{ |
|
| 265 |
3
|
kore |
throw new phpillowInvalidRequestException( |
|
| 266 |
1
|
kore |
'Unsupported request method: %method', |
|
| 267 |
↓
|
kore |
array( |
|
| 268 |
↓
|
kore |
'method' => $method, |
|
| 269 |
↓
|
kore |
) |
|
| 270 |
↓
|
kore |
); |
|
| 271 |
↓
|
kore |
} |
|
| 272 |
↓
|
kore |
|
|
| 273 |
↓
|
kore |
// Check if required parameter containing the path is set and valid. |
|
| 274 |
↓
|
kore |
if ( !isset( $params[0] ) || |
|
| 275 |
↓
|
kore |
!is_string( $params[0] ) || |
|
| 276 |
↓
|
kore |
( $params[0][0] !== '/' ) ) |
|
| 277 |
↓
|
kore |
{ |
|
| 278 |
3
|
kore |
throw new phpillowInvalidRequestException( |
|
| 279 |
1
|
kore |
'Absolute path required as first parameter for the request.', |
|
| 280 |
↓
|
kore |
array() |
|
| 281 |
↓
|
kore |
); |
|
| 282 |
↓
|
kore |
} |
|
| 283 |
↓
|
kore |
$path = $params[0]; |
|
| 284 |
↓
|
kore |
|
|
| 285 |
↓
|
kore |
// Check if data has been provided |
|
| 286 |
↓
|
kore |
$data = ( ( isset( $params[1] ) ) ? (string) $params[1] : null ); |
|
| 287 |
25
|
kore |
$raw = ( ( isset( $params[2] ) ) ? (bool) $params[2] : false ); |
|
| 288 |
1
|
kore |
|
|
| 289 |
↓
|
kore |
// Finally perform request and return the result from the server |
|
| 290 |
25
|
kore |
return $this->request( $method, $path, $data, $raw ); |
|
| 291 |
1
|
kore |
} |
|
| 292 |
↓
|
kore |
|
|
| 293 |
↓
|
kore |
/** |
|
| 294 |
10
|
kore |
* Perform a request to the server and return the result |
|
| 295 |
↓
|
kore |
* |
|
| 296 |
25
|
kore |
* Perform a request to the server and return the result converted into a |
|
| 297 |
↓
|
kore |
* phpillowResponse object. If you do not expect a JSON structure, which |
|
| 298 |
97
|
kore |
* could be converted in such a response object, set the fourth parameter to |
|
| 299 |
159
|
kore |
* true, and you get a response object returned, containing the raw body. |
|
| 300 |
10
|
kore |
* |
|
| 301 |
↓
|
kore |
* @param string $method |
|
| 302 |
↓
|
kore |
* @param string $path |
|
| 303 |
↓
|
kore |
* @param string $data |
|
| 304 |
97
|
kore |
* @param bool $raw |
|
| 305 |
25
|
kore |
* @return phpillowResponse |
|
| 306 |
10
|
kore |
*/ |
|
| 307 |
63
|
kore |
abstract protected function request( $method, $path, $data, $raw = false ); |
|
| 308 |
1
|
kore |
} |
|
| 309 |
↓
|
kore |
|
|