1 <?php
2 3 4 5 6 7 8 9 10
11
12
13 14 15 16 17 18 19 20 21 22 23 24 25 26
27 class NeevoConnection implements INeevoObservable, ArrayAccess {
28
29
30
31 private $config;
32
33
34 private $connected = false;
35
36
37 private $driver;
38
39
40 private $parser = 'NeevoParser';
41
42
43 private $observers;
44
45
46 private $cache;
47
48
49 50 51 52 53 54 55
56 public function __construct($config, INeevoCache $cache = null){
57 $this->observers = new NeevoObserverMap;
58
59 $this->cache = $cache !== null ? $cache : new NeevoCacheMemory;
60
61
62 if(is_string($config)){
63 parse_str($config, $config);
64
65 } elseif($config instanceof Traversable){
66 $tmp = array();
67 foreach($config as $key => $val){
68 $tmp[$key] = $val instanceof Traversable ? iterator_to_array($val) : $val;
69 }
70 $config = $tmp;
71
72 } elseif(!is_array($config)){
73 throw new InvalidArgumentException('Configuration must be an array, string or Traversable.');
74 }
75
76
77 $defaults = array(
78 'driver' => Neevo::$defaultDriver,
79 'lazy' => false,
80 'rowClass' => 'NeevoRow',
81 'tablePrefix' => '',
82 'result' => array(
83 'detectTypes' => false,
84 'formatDate' => '',
85 ),
86 );
87
88
89 self::alias($config, 'driver', 'extension');
90 self::alias($config, 'username', 'user');
91 self::alias($config, 'password', 'pass');
92 self::alias($config, 'password', 'pswd');
93 self::alias($config, 'host', 'hostname');
94 self::alias($config, 'host', 'server');
95 self::alias($config, 'database', 'db');
96 self::alias($config, 'database', 'dbname');
97 self::alias($config, 'tablePrefix', 'table_prefix');
98 self::alias($config, 'tablePrefix', 'prefix');
99 self::alias($config, 'charset', 'encoding');
100 self::alias($config, 'result.detectTypes', 'detectTypes');
101 self::alias($config, 'result.formatDate', 'formatDateTime');
102
103 $config = array_replace_recursive($defaults, $config);
104
105 $this->setDriver($config['driver']);
106
107 $config['lazy'] = (bool) $config['lazy'] && strtolower($config['lazy']) !== 'false';
108 $this->config = $config;
109
110 if($config['lazy'] === false)
111 $this->connect();
112 }
113
114
115 116 117 118
119 public function __destruct(){
120 try{
121 $this->driver->closeConnection();
122 } catch(NeevoImplementationException $e){
123
124 }
125
126 $this->notifyObservers(INeevoObserver::DISCONNECT);
127 }
128
129
130 131 132 133
134 public function connect(){
135 if($this->connected !== false)
136 return;
137
138 $this->driver->connect($this->config);
139 $this->connected = true;
140 $this->notifyObservers(INeevoObserver::CONNECT);
141 }
142
143
144 145 146 147 148
149 public function getConfig($key = null){
150 if($key === null)
151 return $this->config;
152 return isset($this->config[$key]) ? $this->config[$key] : null;
153 }
154
155
156 157 158 159
160 public function getPrefix(){
161 return isset($this->config['tablePrefix']) ? $this->config['tablePrefix'] : '';
162 }
163
164
165 166 167 168
169 public function getDriver(){
170 return $this->driver;
171 }
172
173
174 175 176 177
178 public function getParser(){
179 return $this->parser;
180 }
181
182
183 184 185 186
187 public function getCache(){
188 return $this->cache;
189 }
190
191
192 193 194 195
196 public function setCache(INeevoCache $cache){
197 $this->cache = $cache;
198 }
199
200
201
202
203
204 205 206 207 208 209
210 public function attachObserver(INeevoObserver $observer, $event){
211 $this->observers->attach($observer, $event);
212 }
213
214
215 216 217 218 219
220 public function detachObserver(INeevoObserver $observer){
221 $this->observers->detach($observer);
222 }
223
224
225 226 227 228 229
230 public function notifyObservers($event){
231 foreach($this->observers as $observer){
232 if($event & $this->observers->getEvent())
233 $observer->updateStatus($this, $event);
234 }
235 }
236
237
238
239
240
241 242 243 244 245
246 public function offsetGet($key){
247 return $this->getConfig($key);
248 }
249
250
251 252 253 254 255
256 public function offsetExists($key){
257 return isset($this->config[$key]);
258 }
259
260
261
262 public function offsetSet($offset, $value){}
263
264
265 public function offsetUnset($offset){}
266
267
268
269
270
271 272 273 274 275 276 277
278 public static function alias(&$config, $key, $alias){
279 if(!isset($config[$alias]))
280 return;
281 $tmp = & $config;
282 foreach(explode('.', $key) as $key){
283 $tmp = & $tmp[$key];
284 }
285 if(!isset($tmp))
286 $tmp = $config[$alias];
287 }
288
289
290 291 292 293 294 295
296 protected function setDriver($driver){
297 if(strcasecmp($driver, 'sqlite') === 0)
298 $driver = 'SQLite2';
299
300 $class = "NeevoDriver$driver";
301
302 if(!class_exists($class)){
303 $file = dirname(__FILE__) . '/drivers/' . strtolower($driver) . '.php';
304
305 if(!file_exists($file))
306 throw new NeevoDriverException("$driver driver file ($file) does not exist.");
307 if(is_readable($file))
308 include_once $file;
309 else
310 throw new NeevoDriverException("$driver driver file ($file) is not readable.");
311
312 }
313 if(!$this->isDriver($class))
314 throw new NeevoDriverException("Class '$class' is not a valid Neevo driver class.");
315
316 $this->driver = new $class;
317
318
319 if($this->isParser($class))
320 $this->parser = $class;
321 }
322
323
324 325 326 327 328
329 protected function isDriver($class){
330 try{
331 $reflection = new ReflectionClass($class);
332 return $reflection->implementsInterface('INeevoDriver');
333 } catch(ReflectionException $e){
334 return false;
335 }
336 }
337
338
339 340 341 342 343
344 protected function isParser($class){
345 try{
346 $reflection = new ReflectionClass($class);
347 return $reflection->isSubclassOf('NeevoParser');
348 } catch(ReflectionException $e){
349 return false;
350 }
351 }
352
353
354 }
355