PageRenderTime 69ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/libs/dibi/dibi.min.php

https://github.com/vrana/mvc-exception-demo
PHP | 1788 lines | 1765 code | 4 blank | 19 comment | 3 complexity | fdbfd30d5494967a62e2557b54c3fd73 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php //netteloader=DibiVariable,IDataSource,IDibiProfiler,IDibiDriver,IDibiResultDriver,IDibiReflector,DibiObject,DibiLazyStorageBase,DibiLazyStorage,DibiException,DibiDriverException,DibiConnection,DibiResult,DibiResultIterator,DibiRow,DibiTranslator,DibiDataSource,DibiFluent,DibiDatabaseInfo,DibiTableInfo,DibiResultInfo,DibiColumnInfo,DibiForeignKeyInfo,DibiIndexInfo,DibiProfiler,dibi,DibiMySqlReflector,DibiMySqlDriver,DibiMySqliDriver,DibiOdbcDriver,DibiPdoDriver,DibiPostgreDriver,DibiSqliteReflector,DibiSqliteDriver,DibiSqlite3Driver
  2. /**
  3. * dibi - tiny'n'smart database abstraction layer
  4. * ----------------------------------------------
  5. *
  6. * Copyright (c) 2005, 2010 David Grudl (http://davidgrudl.com)
  7. *
  8. * This source file is subject to the "dibi license" that is bundled
  9. * with this package in the file license.txt, and/or GPL license.
  10. *
  11. * For more information please see http://dibiphp.com
  12. *
  13. * @copyright Copyright (c) 2005, 2010 David Grudl
  14. * @license http://dibiphp.com/license dibi license
  15. * @link http://dibiphp.com
  16. * @package dibi
  17. */
  18. if(version_compare(PHP_VERSION,'5.2.0','<')){throw
  19. new
  20. Exception('dibi needs PHP 5.2.0 or newer.');}@set_magic_quotes_runtime(FALSE);if(!class_exists('NotImplementedException',FALSE)){class
  21. NotImplementedException
  22. extends
  23. LogicException{}}if(!class_exists('NotSupportedException',FALSE)){class
  24. NotSupportedException
  25. extends
  26. LogicException{}}if(!class_exists('MemberAccessException',FALSE)){class
  27. MemberAccessException
  28. extends
  29. LogicException{}}if(!class_exists('InvalidStateException',FALSE)){class
  30. InvalidStateException
  31. extends
  32. RuntimeException{}}if(!class_exists('IOException',FALSE)){class
  33. IOException
  34. extends
  35. RuntimeException{}}if(!class_exists('FileNotFoundException',FALSE)){class
  36. FileNotFoundException
  37. extends
  38. IOException{}}if(!class_exists('PcreException',FALSE)){class
  39. PcreException
  40. extends
  41. Exception{public
  42. function
  43. __construct(){static$messages=array(PREG_INTERNAL_ERROR=>'Internal error.',PREG_BACKTRACK_LIMIT_ERROR=>'Backtrack limit was exhausted.',PREG_RECURSION_LIMIT_ERROR=>'Recursion limit was exhausted.',PREG_BAD_UTF8_ERROR=>'Malformed UTF-8 data.',5=>'Offset didn\'t correspond to the begin of a valid UTF-8 code point.');$code=preg_last_error();parent::__construct(isset($messages[$code])?$messages[$code]:'Unknown error.',$code);}}}if(!interface_exists('IDebugPanel',FALSE)){interface
  44. IDebugPanel{function
  45. getTab();function
  46. getPanel();function
  47. getId();}}if(!class_exists('DateTime53',FALSE)){class
  48. DateTime53
  49. extends
  50. DateTime{public
  51. function
  52. __sleep(){$this->fix=array($this->format('Y-m-d H:i:s'),$this->getTimezone()->getName());return
  53. array('fix');}public
  54. function
  55. __wakeup(){$this->__construct($this->fix[0],new
  56. DateTimeZone($this->fix[1]));unset($this->fix);}public
  57. function
  58. getTimestamp(){return(int)$this->format('U');}public
  59. function
  60. setTimestamp($timestamp){return$this->__construct(date('Y-m-d H:i:s',$timestamp),new
  61. DateTimeZone($this->getTimezone()->getName()));}}}class
  62. DibiVariable
  63. extends
  64. DateTime53{function
  65. __construct($val){parent::__construct($val);}}interface
  66. IDataSource
  67. extends
  68. Countable,IteratorAggregate{}interface
  69. IDibiProfiler{const
  70. CONNECT=1;const
  71. SELECT=4;const
  72. INSERT=8;const
  73. DELETE=16;const
  74. UPDATE=32;const
  75. QUERY=60;const
  76. BEGIN=64;const
  77. COMMIT=128;const
  78. ROLLBACK=256;const
  79. TRANSACTION=448;const
  80. EXCEPTION=512;const
  81. ALL=1023;function
  82. before(DibiConnection$connection,$event,$sql=NULL);function
  83. after($ticket,$result=NULL);function
  84. exception(DibiDriverException$exception);}interface
  85. IDibiDriver{function
  86. connect(array&$config);function
  87. disconnect();function
  88. query($sql);function
  89. getAffectedRows();function
  90. getInsertId($sequence);function
  91. begin($savepoint=NULL);function
  92. commit($savepoint=NULL);function
  93. rollback($savepoint=NULL);function
  94. getResource();function
  95. getReflector();function
  96. escape($value,$type);function
  97. applyLimit(&$sql,$limit,$offset);}interface
  98. IDibiResultDriver{function
  99. getRowCount();function
  100. seek($row);function
  101. fetch($type);function
  102. free();function
  103. getResultColumns();function
  104. getResultResource();function
  105. unescape($value,$type);}interface
  106. IDibiReflector{function
  107. getTables();function
  108. getColumns($table);function
  109. getIndexes($table);function
  110. getForeignKeys($table);}abstract
  111. class
  112. DibiObject{private
  113. static$extMethods;final
  114. public
  115. function
  116. getClass(){return
  117. get_class($this);}final
  118. public
  119. function
  120. getReflection(){return
  121. new
  122. ReflectionObject($this);}public
  123. function
  124. __call($name,$args){$class=get_class($this);if($name===''){throw
  125. new
  126. MemberAccessException("Call to class '$class' method without name.");}if(preg_match('#^on[A-Z]#',$name)){$rp=new
  127. ReflectionProperty($class,$name);if($rp->isPublic()&&!$rp->isStatic()){$list=$this->$name;if(is_array($list)||$list
  128. instanceof
  129. Traversable){foreach($list
  130. as$handler){if(is_object($handler)){call_user_func_array(array($handler,'__invoke'),$args);}else{call_user_func_array($handler,$args);}}}return
  131. NULL;}}if($cb=self::extensionMethod("$class::$name")){array_unshift($args,$this);return
  132. call_user_func_array($cb,$args);}throw
  133. new
  134. MemberAccessException("Call to undefined method $class::$name().");}public
  135. static
  136. function
  137. __callStatic($name,$args){$class=get_called_class();throw
  138. new
  139. MemberAccessException("Call to undefined static method $class::$name().");}public
  140. static
  141. function
  142. extensionMethod($name,$callback=NULL){if(self::$extMethods===NULL||$name===NULL){$list=get_defined_functions();foreach($list['user']as$fce){$pair=explode('_prototype_',$fce);if(count($pair)===2){self::$extMethods[$pair[1]][$pair[0]]=$fce;self::$extMethods[$pair[1]]['']=NULL;}}if($name===NULL)return
  143. NULL;}$name=strtolower($name);$a=strrpos($name,':');if($a===FALSE){$class=strtolower(get_called_class());$l=&self::$extMethods[$name];}else{$class=substr($name,0,$a-1);$l=&self::$extMethods[substr($name,$a+1)];}if($callback!==NULL){$l[$class]=$callback;$l['']=NULL;return
  144. NULL;}if(empty($l)){return
  145. FALSE;}elseif(isset($l[''][$class])){return$l[''][$class];}$cl=$class;do{$cl=strtolower($cl);if(isset($l[$cl])){return$l[''][$class]=$l[$cl];}}while(($cl=get_parent_class($cl))!==FALSE);foreach(class_implements($class)as$cl){$cl=strtolower($cl);if(isset($l[$cl])){return$l[''][$class]=$l[$cl];}}return$l[''][$class]=FALSE;}public
  146. function&__get($name){$class=get_class($this);if($name===''){throw
  147. new
  148. MemberAccessException("Cannot read a class '$class' property without name.");}$name[0]=$name[0]&"\xDF";$m='get'.$name;if(self::hasAccessor($class,$m)){$val=$this->$m();return$val;}$m='is'.$name;if(self::hasAccessor($class,$m)){$val=$this->$m();return$val;}$name=func_get_arg(0);throw
  149. new
  150. MemberAccessException("Cannot read an undeclared property $class::\$$name.");}public
  151. function
  152. __set($name,$value){$class=get_class($this);if($name===''){throw
  153. new
  154. MemberAccessException("Cannot assign to a class '$class' property without name.");}$name[0]=$name[0]&"\xDF";if(self::hasAccessor($class,'get'.$name)||self::hasAccessor($class,'is'.$name)){$m='set'.$name;if(self::hasAccessor($class,$m)){$this->$m($value);return;}else{$name=func_get_arg(0);throw
  155. new
  156. MemberAccessException("Cannot assign to a read-only property $class::\$$name.");}}$name=func_get_arg(0);throw
  157. new
  158. MemberAccessException("Cannot assign to an undeclared property $class::\$$name.");}public
  159. function
  160. __isset($name){$name[0]=$name[0]&"\xDF";return$name!==''&&self::hasAccessor(get_class($this),'get'.$name);}public
  161. function
  162. __unset($name){$class=get_class($this);throw
  163. new
  164. MemberAccessException("Cannot unset the property $class::\$$name.");}private
  165. static
  166. function
  167. hasAccessor($c,$m){static$cache;if(!isset($cache[$c])){$cache[$c]=array_flip(get_class_methods($c));}return
  168. isset($cache[$c][$m]);}}abstract
  169. class
  170. DibiLazyStorageBase{private$callback;public
  171. function
  172. __construct($callback){$this->setCallback($callback);}public
  173. function
  174. setCallback($callback){if(!is_callable($callback)){$able=is_callable($callback,TRUE,$textual);throw
  175. new
  176. InvalidArgumentException("Handler '$textual' is not ".($able?'callable.':'valid PHP callback.'));}$this->callback=$callback;}public
  177. function
  178. getCallback(){return$this->callback;}}final
  179. class
  180. DibiLazyStorage
  181. extends
  182. DibiLazyStorageBase{public
  183. function
  184. __get($nm){if(is_array($nm)){$nm=$nm[1];}if($nm==''){throw
  185. new
  186. InvalidStateException('Missing identifier name.');}return$this->$nm=call_user_func($this->getCallback(),$nm);}}class
  187. DibiException
  188. extends
  189. Exception
  190. implements
  191. IDebugPanel{private$sql;public
  192. function
  193. __construct($message=NULL,$code=0,$sql=NULL){parent::__construct($message,(int)$code);$this->sql=$sql;}final
  194. public
  195. function
  196. getSql(){return$this->sql;}public
  197. function
  198. __toString(){return
  199. parent::__toString().($this->sql?"\nSQL: ".$this->sql:'');}public
  200. function
  201. getTab(){return'SQL';}public
  202. function
  203. getPanel(){return$this->sql?dibi::dump($this->sql,TRUE):NULL;}public
  204. function
  205. getId(){return
  206. __CLASS__;}}class
  207. DibiDriverException
  208. extends
  209. DibiException{private
  210. static$errorMsg;public
  211. static
  212. function
  213. tryError(){set_error_handler(array(__CLASS__,'_errorHandler'),E_ALL);self::$errorMsg=NULL;}public
  214. static
  215. function
  216. catchError(&$message){restore_error_handler();$message=self::$errorMsg;self::$errorMsg=NULL;return$message!==NULL;}public
  217. static
  218. function
  219. _errorHandler($code,$message){restore_error_handler();if(ini_get('html_errors')){$message=strip_tags($message);$message=html_entity_decode($message);}self::$errorMsg=$message;}}class
  220. DibiConnection
  221. extends
  222. DibiObject{private$config;private$driver;private$translator;private$profiler;private$connected=FALSE;public
  223. function
  224. __construct($config,$name=NULL){if(is_string($config)){parse_str($config,$config);}elseif($config
  225. instanceof
  226. Traversable){$tmp=array();foreach($config
  227. as$key=>$val){$tmp[$key]=$val
  228. instanceof
  229. Traversable?iterator_to_array($val):$val;}$config=$tmp;}elseif(!is_array($config)){throw
  230. new
  231. InvalidArgumentException('Configuration must be array, string or object.');}self::alias($config,'username','user');self::alias($config,'password','pass');self::alias($config,'host','hostname');self::alias($config,'result|detectTypes','resultDetectTypes');self::alias($config,'result|formatDateTime','resultDateTime');if(!isset($config['driver'])){$config['driver']=dibi::$defaultDriver;}$driver=preg_replace('#[^a-z0-9_]#','_',strtolower($config['driver']));$class="Dibi".$driver."Driver";if(!class_exists($class,FALSE)){ include_once dirname(__FILE__)."/../drivers/$driver.php";if(!class_exists($class,FALSE)){throw
  232. new
  233. DibiException("Unable to create instance of dibi driver '$class'.");}}$config['name']=$name;$this->config=$config;$this->driver=new$class;$this->translator=new
  234. DibiTranslator($this->driver);$profilerCfg=&$config['profiler'];if(is_scalar($profilerCfg)){$profilerCfg=array('run'=>(bool)$profilerCfg,'class'=>strlen($profilerCfg)>1?$profilerCfg:NULL);}if(!empty($profilerCfg['run'])){$class=isset($profilerCfg['class'])?$profilerCfg['class']:'DibiProfiler';if(!class_exists($class)){throw
  235. new
  236. DibiException("Unable to create instance of dibi profiler '$class'.");}$this->setProfiler(new$class($profilerCfg));}if(!empty($config['substitutes'])){foreach($config['substitutes']as$key=>$value){dibi::addSubst($key,$value);}}if(empty($config['lazy'])){$this->connect();}}public
  237. function
  238. __destruct(){$this->connected&&$this->disconnect();}final
  239. public
  240. function
  241. connect(){if($this->profiler!==NULL){$ticket=$this->profiler->before($this,IDibiProfiler::CONNECT);}$this->driver->connect($this->config);$this->connected=TRUE;if(isset($ticket)){$this->profiler->after($ticket);}}final
  242. public
  243. function
  244. disconnect(){$this->driver->disconnect();$this->connected=FALSE;}final
  245. public
  246. function
  247. isConnected(){return$this->connected;}final
  248. public
  249. function
  250. getConfig($key=NULL,$default=NULL){if($key===NULL){return$this->config;}elseif(isset($this->config[$key])){return$this->config[$key];}else{return$default;}}public
  251. static
  252. function
  253. alias(&$config,$key,$alias){$foo=&$config;foreach(explode('|',$key)as$key)$foo=&$foo[$key];if(!isset($foo)&&isset($config[$alias])){$foo=$config[$alias];unset($config[$alias]);}}final
  254. public
  255. function
  256. getDriver(){$this->connected||$this->connect();return$this->driver;}final
  257. public
  258. function
  259. query($args){$this->connected||$this->connect();$args=func_get_args();return$this->nativeQuery($this->translator->translate($args));}final
  260. public
  261. function
  262. translate($args){$this->connected||$this->connect();$args=func_get_args();return$this->translator->translate($args);}function
  263. sql($args){trigger_error(__METHOD__.'() is deprecated; use translate() instead.',E_USER_NOTICE);$this->connected||$this->connect();$args=func_get_args();return$this->translator->translate($args);}final
  264. public
  265. function
  266. test($args){$this->connected||$this->connect();$args=func_get_args();try{dibi::dump($this->translator->translate($args));return
  267. TRUE;}catch(DibiException$e){dibi::dump($e->getSql());return
  268. FALSE;}}final
  269. public
  270. function
  271. dataSource($args){$this->connected||$this->connect();$args=func_get_args();return
  272. new
  273. DibiDataSource($this->translator->translate($args),$this);}final
  274. public
  275. function
  276. nativeQuery($sql){$this->connected||$this->connect();if($this->profiler!==NULL){$event=IDibiProfiler::QUERY;if(preg_match('#\s*(SELECT|UPDATE|INSERT|DELETE)#i',$sql,$matches)){static$events=array('SELECT'=>IDibiProfiler::SELECT,'UPDATE'=>IDibiProfiler::UPDATE,'INSERT'=>IDibiProfiler::INSERT,'DELETE'=>IDibiProfiler::DELETE);$event=$events[strtoupper($matches[1])];}$ticket=$this->profiler->before($this,$event,$sql);}dibi::$sql=$sql;if($res=$this->driver->query($sql)){$res=new
  277. DibiResult($res,$this->config['result']);}else{$res=$this->driver->getAffectedRows();}if(isset($ticket)){$this->profiler->after($ticket,$res);}return$res;}public
  278. function
  279. getAffectedRows(){$this->connected||$this->connect();$rows=$this->driver->getAffectedRows();if(!is_int($rows)||$rows<0)throw
  280. new
  281. DibiException('Cannot retrieve number of affected rows.');return$rows;}public
  282. function
  283. affectedRows(){return$this->getAffectedRows();}public
  284. function
  285. getInsertId($sequence=NULL){$this->connected||$this->connect();$id=$this->driver->getInsertId($sequence);if($id<1)throw
  286. new
  287. DibiException('Cannot retrieve last generated ID.');return(int)$id;}public
  288. function
  289. insertId($sequence=NULL){return$this->getInsertId($sequence);}public
  290. function
  291. begin($savepoint=NULL){$this->connected||$this->connect();if($this->profiler!==NULL){$ticket=$this->profiler->before($this,IDibiProfiler::BEGIN,$savepoint);}$this->driver->begin($savepoint);if(isset($ticket)){$this->profiler->after($ticket);}}public
  292. function
  293. commit($savepoint=NULL){$this->connected||$this->connect();if($this->profiler!==NULL){$ticket=$this->profiler->before($this,IDibiProfiler::COMMIT,$savepoint);}$this->driver->commit($savepoint);if(isset($ticket)){$this->profiler->after($ticket);}}public
  294. function
  295. rollback($savepoint=NULL){$this->connected||$this->connect();if($this->profiler!==NULL){$ticket=$this->profiler->before($this,IDibiProfiler::ROLLBACK,$savepoint);}$this->driver->rollback($savepoint);if(isset($ticket)){$this->profiler->after($ticket);}}public
  296. function
  297. command(){return
  298. new
  299. DibiFluent($this);}public
  300. function
  301. select($args){$args=func_get_args();return$this->command()->__call('select',$args);}public
  302. function
  303. update($table,$args){if(!(is_array($args)||$args
  304. instanceof
  305. Traversable)){throw
  306. new
  307. InvalidArgumentException('Arguments must be array or Traversable.');}return$this->command()->update('%n',$table)->set($args);}public
  308. function
  309. insert($table,$args){if($args
  310. instanceof
  311. Traversable){$args=iterator_to_array($args);}elseif(!is_array($args)){throw
  312. new
  313. InvalidArgumentException('Arguments must be array or Traversable.');}return$this->command()->insert()->into('%n',$table,'(%n)',array_keys($args))->values('%l',$args);}public
  314. function
  315. delete($table){return$this->command()->delete()->from('%n',$table);}public
  316. function
  317. setProfiler(IDibiProfiler$profiler=NULL){$this->profiler=$profiler;return$this;}public
  318. function
  319. getProfiler(){return$this->profiler;}public
  320. function
  321. fetch($args){$args=func_get_args();return$this->query($args)->fetch();}public
  322. function
  323. fetchAll($args){$args=func_get_args();return$this->query($args)->fetchAll();}public
  324. function
  325. fetchSingle($args){$args=func_get_args();return$this->query($args)->fetchSingle();}public
  326. function
  327. fetchPairs($args){$args=func_get_args();return$this->query($args)->fetchPairs();}public
  328. function
  329. loadFile($file){$this->connected||$this->connect();@set_time_limit(0);$handle=@fopen($file,'r');if(!$handle){throw
  330. new
  331. FileNotFoundException("Cannot open file '$file'.");}$count=0;$sql='';while(!feof($handle)){$s=fgets($handle);$sql.=$s;if(substr(rtrim($s),-1)===';'){$this->driver->query($sql);$sql='';$count++;}}fclose($handle);return$count;}public
  332. function
  333. getDatabaseInfo(){$this->connected||$this->connect();return
  334. new
  335. DibiDatabaseInfo($this->driver->getReflector(),isset($this->config['database'])?$this->config['database']:NULL);}public
  336. function
  337. __wakeup(){throw
  338. new
  339. NotSupportedException('You cannot serialize or unserialize '.$this->getClass().' instances.');}public
  340. function
  341. __sleep(){throw
  342. new
  343. NotSupportedException('You cannot serialize or unserialize '.$this->getClass().' instances.');}}class
  344. DibiResult
  345. extends
  346. DibiObject
  347. implements
  348. IDataSource{private$driver;private$types;private$meta;private$fetched=FALSE;private$rowClass='DibiRow';private$dateFormat='';public
  349. function
  350. __construct($driver,$config){$this->driver=$driver;if(!empty($config['detectTypes'])){$this->detectTypes();}if(!empty($config['formatDateTime'])){$this->dateFormat=is_string($config['formatDateTime'])?$config['formatDateTime']:'';}}final
  351. public
  352. function
  353. getResource(){return$this->getDriver()->getResultResource();}final
  354. public
  355. function
  356. free(){if($this->driver!==NULL){$this->driver->free();$this->driver=$this->meta=NULL;}}private
  357. function
  358. getDriver(){if($this->driver===NULL){throw
  359. new
  360. InvalidStateException('Result-set was released from memory.');}return$this->driver;}final
  361. public
  362. function
  363. seek($row){return($row!==0||$this->fetched)?(bool)$this->getDriver()->seek($row):TRUE;}final
  364. public
  365. function
  366. count(){return$this->getDriver()->getRowCount();}final
  367. public
  368. function
  369. getRowCount(){return$this->getDriver()->getRowCount();}final
  370. public
  371. function
  372. rowCount(){return$this->getDriver()->getRowCount();}final
  373. public
  374. function
  375. getIterator(){if(func_num_args()){trigger_error(__METHOD__.' arguments $offset & $limit have been dropped; use SQL clauses instead.',E_USER_WARNING);}return
  376. new
  377. DibiResultIterator($this);}public
  378. function
  379. setRowClass($class){$this->rowClass=$class;return$this;}public
  380. function
  381. getRowClass(){return$this->rowClass;}final
  382. public
  383. function
  384. fetch(){$row=$this->getDriver()->fetch(TRUE);if(!is_array($row))return
  385. FALSE;$this->fetched=TRUE;if($this->types!==NULL){foreach($this->types
  386. as$col=>$type){if(isset($row[$col])){$row[$col]=$this->convert($row[$col],$type);}}}return
  387. new$this->rowClass($row);}final
  388. public
  389. function
  390. fetchSingle(){$row=$this->getDriver()->fetch(TRUE);if(!is_array($row))return
  391. FALSE;$this->fetched=TRUE;$value=reset($row);$key=key($row);if(isset($this->types[$key])){return$this->convert($value,$this->types[$key]);}return$value;}final
  392. public
  393. function
  394. fetchAll($offset=NULL,$limit=NULL){$limit=$limit===NULL?-1:(int)$limit;$this->seek((int)$offset);$row=$this->fetch();if(!$row)return
  395. array();$data=array();do{if($limit===0)break;$limit--;$data[]=$row;}while($row=$this->fetch());return$data;}final
  396. public
  397. function
  398. fetchAssoc($assoc){if(strpos($assoc,',')!==FALSE){return$this->oldFetchAssoc($assoc);}$this->seek(0);$row=$this->fetch();if(!$row)return
  399. array();$data=NULL;$assoc=preg_split('#(\[\]|->|=|\|)#',$assoc,NULL,PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);foreach($assoc
  400. as$as){if($as!=='[]'&&$as!=='='&&$as!=='->'&&$as!=='|'&&!property_exists($row,$as)){throw
  401. new
  402. InvalidArgumentException("Unknown column '$as' in associative descriptor.");}}if($as==='->'){array_pop($assoc);}if(empty($assoc)){$assoc[]='[]';}do{$x=&$data;foreach($assoc
  403. as$i=>$as){if($as==='[]'){$x=&$x[];}elseif($as==='='){$x=$row->{$assoc[$i+1]};continue
  404. 2;}elseif($as==='->'){if($x===NULL){$x=clone$row;$x=&$x->{$assoc[$i+1]};$x=NULL;}else{$x=&$x->{$assoc[$i+1]};}}elseif($as!=='|'){$x=&$x[$row->$as];}}if($x===NULL){$x=$row;}}while($row=$this->fetch());unset($x);return$data;}private
  405. function
  406. oldFetchAssoc($assoc){$this->seek(0);$row=$this->fetch();if(!$row)return
  407. array();$data=NULL;$assoc=explode(',',$assoc);$leaf='@';$last=count($assoc)-1;while($assoc[$last]==='='||$assoc[$last]==='@'){$leaf=$assoc[$last];unset($assoc[$last]);$last--;if($last<0){$assoc[]='#';break;}}do{$x=&$data;foreach($assoc
  408. as$i=>$as){if($as==='#'){$x=&$x[];}elseif($as==='='){if($x===NULL){$x=$row->toArray();$x=&$x[$assoc[$i+1]];$x=NULL;}else{$x=&$x[$assoc[$i+1]];}}elseif($as==='@'){if($x===NULL){$x=clone$row;$x=&$x->{$assoc[$i+1]};$x=NULL;}else{$x=&$x->{$assoc[$i+1]};}}else{$x=&$x[$row->$as];}}if($x===NULL){if($leaf==='='){$x=$row->toArray();}else{$x=$row;}}}while($row=$this->fetch());unset($x);return$data;}final
  409. public
  410. function
  411. fetchPairs($key=NULL,$value=NULL){$this->seek(0);$row=$this->fetch();if(!$row)return
  412. array();$data=array();if($value===NULL){if($key!==NULL){throw
  413. new
  414. InvalidArgumentException("Either none or both columns must be specified.");}$tmp=array_keys($row->toArray());$key=$tmp[0];if(count($row)<2){do{$data[]=$row[$key];}while($row=$this->fetch());return$data;}$value=$tmp[1];}else{if(!property_exists($row,$value)){throw
  415. new
  416. InvalidArgumentException("Unknown value column '$value'.");}if($key===NULL){do{$data[]=$row[$value];}while($row=$this->fetch());return$data;}if(!property_exists($row,$key)){throw
  417. new
  418. InvalidArgumentException("Unknown key column '$key'.");}}do{$data[$row[$key]]=$row[$value];}while($row=$this->fetch());return$data;}final
  419. public
  420. function
  421. setType($col,$type){$this->types[$col]=$type;return$this;}final
  422. public
  423. function
  424. detectTypes(){foreach($this->getInfo()->getColumns()as$col){$this->types[$col->getName()]=$col->getType();}}final
  425. public
  426. function
  427. setTypes(array$types){$this->types=$types;return$this;}final
  428. public
  429. function
  430. getType($col){return
  431. isset($this->types[$col])?$this->types[$col]:NULL;}protected
  432. function
  433. convert($value,$type){if($value===NULL||$value===FALSE){return
  434. NULL;}switch($type){case
  435. dibi::TEXT:return(string)$value;case
  436. dibi::BINARY:return$this->getDriver()->unescape($value,$type);case
  437. dibi::INTEGER:return(int)$value;case
  438. dibi::FLOAT:return(float)$value;case
  439. dibi::DATE:case
  440. dibi::DATETIME:if((int)$value===0){return
  441. NULL;}elseif($this->dateFormat===''){return
  442. new
  443. DateTime53(is_numeric($value)?date('Y-m-d H:i:s',$value):$value);}elseif($this->dateFormat==='U'){return
  444. is_numeric($value)?(int)$value:strtotime($value);}elseif(is_numeric($value)){return
  445. date($this->dateFormat,$value);}else{$value=new
  446. DateTime53($value);return$value->format($this->dateFormat);}case
  447. dibi::BOOL:return((bool)$value)&&$value!=='f'&&$value!=='F';default:return$value;}}public
  448. function
  449. getInfo(){if($this->meta===NULL){$this->meta=new
  450. DibiResultInfo($this->getDriver());}return$this->meta;}final
  451. public
  452. function
  453. getColumns(){return$this->getInfo()->getColumns();}public
  454. function
  455. getColumnNames($fullNames=FALSE){return$this->getInfo()->getColumnNames($fullNames);}final
  456. public
  457. function
  458. dump(){$i=0;$this->seek(0);while($row=$this->fetch()){if($i===0){echo"\n<table class=\"dump\">\n<thead>\n\t<tr>\n\t\t<th>#row</th>\n";foreach($row
  459. as$col=>$foo){echo"\t\t<th>".htmlSpecialChars($col)."</th>\n";}echo"\t</tr>\n</thead>\n<tbody>\n";}echo"\t<tr>\n\t\t<th>",$i,"</th>\n";foreach($row
  460. as$col){echo"\t\t<td>",htmlSpecialChars($col),"</td>\n";}echo"\t</tr>\n";$i++;}if($i===0){echo'<p><em>empty result set</em></p>';}else{echo"</tbody>\n</table>\n";}}}class
  461. DibiResultIterator
  462. implements
  463. Iterator,Countable{private$result;private$row;private$pointer;public
  464. function
  465. __construct(DibiResult$result){$this->result=$result;}public
  466. function
  467. rewind(){$this->pointer=0;$this->result->seek(0);$this->row=$this->result->fetch();}public
  468. function
  469. key(){return$this->pointer;}public
  470. function
  471. current(){return$this->row;}public
  472. function
  473. next(){$this->row=$this->result->fetch();$this->pointer++;}public
  474. function
  475. valid(){return!empty($this->row);}public
  476. function
  477. count(){return$this->result->getRowCount();}}class
  478. DibiRow
  479. implements
  480. ArrayAccess,IteratorAggregate,Countable{public
  481. function
  482. __construct($arr){foreach($arr
  483. as$k=>$v)$this->$k=$v;}public
  484. function
  485. toArray(){return(array)$this;}public
  486. function
  487. asDateTime($key,$format=NULL){$time=$this[$key];if((int)$time===0){return
  488. NULL;}$dt=new
  489. DateTime53(is_numeric($time)?date('Y-m-d H:i:s',$time):$time);return$format===NULL?$dt:$dt->format($format);}public
  490. function
  491. asTimestamp($key){$time=$this[$key];return(int)$time===0?NULL:(is_numeric($time)?(int)$time:strtotime($time));}public
  492. function
  493. asBool($key){$value=$this[$key];if($value===NULL||$value===FALSE){return$value;}else{return((bool)$value)&&$value!=='f'&&$value!=='F';}}public
  494. function
  495. asDate($key,$format=NULL){if($format===NULL){return$this->asTimestamp($key);}else{return$this->asDateTime($key,$format===TRUE?NULL:$format);}}final
  496. public
  497. function
  498. count(){return
  499. count((array)$this);}final
  500. public
  501. function
  502. getIterator(){return
  503. new
  504. ArrayIterator($this);}final
  505. public
  506. function
  507. offsetSet($nm,$val){$this->$nm=$val;}final
  508. public
  509. function
  510. offsetGet($nm){return$this->$nm;}final
  511. public
  512. function
  513. offsetExists($nm){return
  514. isset($this->$nm);}final
  515. public
  516. function
  517. offsetUnset($nm){unset($this->$nm);}}final
  518. class
  519. DibiTranslator
  520. extends
  521. DibiObject{private$driver;private$cursor;private$args;private$hasError;private$comment;private$ifLevel;private$ifLevelStart;private$limit;private$offset;private$identifiers;public
  522. function
  523. __construct(IDibiDriver$driver){$this->driver=$driver;$this->identifiers=new
  524. DibiLazyStorage(array($this,'delimite'));}public
  525. function
  526. translate(array$args){$args=array_values($args);while(count($args)===1&&is_array($args[0])){$args=array_values($args[0]);}$this->args=$args;$this->limit=-1;$this->offset=0;$this->hasError=FALSE;$commandIns=NULL;$lastArr=NULL;$cursor=&$this->cursor;$cursor=0;$this->ifLevel=$this->ifLevelStart=0;$comment=&$this->comment;$comment=FALSE;$sql=array();while($cursor<count($this->args)){$arg=$this->args[$cursor];$cursor++;if(is_string($arg)){$toSkip=strcspn($arg,'`[\'":%');if(strlen($arg)===$toSkip){$sql[]=$arg;}else{$sql[]=substr($arg,0,$toSkip).preg_replace_callback('/(?=[`[\'":%?])(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\S*?:)([a-zA-Z0-9._]?)|%([a-zA-Z]{1,4})(?![a-zA-Z])|(\?))/s',array($this,'cb'),substr($arg,$toSkip));if(preg_last_error())throw
  527. new
  528. PcreException;}continue;}if($comment){$sql[]='...';continue;}if($arg
  529. instanceof
  530. Traversable){$arg=iterator_to_array($arg);}if(is_array($arg)){if(is_string(key($arg))){if($commandIns===NULL){$commandIns=strtoupper(substr(ltrim($this->args[0]),0,6));$commandIns=$commandIns==='INSERT'||$commandIns==='REPLAC';$sql[]=$this->formatValue($arg,$commandIns?'v':'a');}else{if($lastArr===$cursor-1)$sql[]=',';$sql[]=$this->formatValue($arg,$commandIns?'l':'a');}$lastArr=$cursor;continue;}}$sql[]=$this->formatValue($arg,FALSE);}if($comment)$sql[]="*/";$sql=implode(' ',$sql);if($this->hasError){throw
  531. new
  532. DibiException('SQL translate error',0,$sql);}if($this->limit>-1||$this->offset>0){$this->driver->applyLimit($sql,$this->limit,$this->offset);}return$sql;}public
  533. function
  534. formatValue($value,$modifier){if($value
  535. instanceof
  536. Traversable){$value=iterator_to_array($value);}if(is_array($value)){$vx=$kx=array();switch($modifier){case'and':case'or':if(empty($value)){return'1=1';}foreach($value
  537. as$k=>$v){if(is_string($k)){$pair=explode('%',$k,2);$k=$this->identifiers->{$pair[0]}.' ';if(!isset($pair[1])){$v=$this->formatValue($v,FALSE);$vx[]=$k.($v==='NULL'?'IS ':'= ').$v;}elseif($pair[1]==='ex'){$vx[]=$k.$this->formatValue($v,'ex');}else{$v=$this->formatValue($v,$pair[1]);$vx[]=$k.($pair[1]==='l'||$pair[1]==='in'?'IN ':($v==='NULL'?'IS ':'= ')).$v;}}else{$vx[]=$this->formatValue($v,'ex');}}return'('.implode(') '.strtoupper($modifier).' (',$vx).')';case'n':foreach($value
  538. as$k=>$v){if(is_string($k)){$vx[]=$this->identifiers->$k.(empty($v)?'':' AS '.$v);}else{$pair=explode('%',$v,2);$vx[]=$this->identifiers->{$pair[0]};}}return
  539. implode(', ',$vx);case'a':foreach($value
  540. as$k=>$v){$pair=explode('%',$k,2);$vx[]=$this->identifiers->{$pair[0]}.'='.$this->formatValue($v,isset($pair[1])?$pair[1]:(is_array($v)?'ex':FALSE));}return
  541. implode(', ',$vx);case'in':case'l':foreach($value
  542. as$k=>$v){$pair=explode('%',$k,2);$vx[]=$this->formatValue($v,isset($pair[1])?$pair[1]:(is_array($v)?'ex':FALSE));}return'('.(($vx||$modifier==='l')?implode(', ',$vx):'NULL').')';case'v':foreach($value
  543. as$k=>$v){$pair=explode('%',$k,2);$kx[]=$this->identifiers->{$pair[0]};$vx[]=$this->formatValue($v,isset($pair[1])?$pair[1]:(is_array($v)?'ex':FALSE));}return'('.implode(', ',$kx).') VALUES ('.implode(', ',$vx).')';case'm':foreach($value
  544. as$k=>$v){if(is_array($v)){if(isset($proto)){if($proto!==array_keys($v)){$this->hasError=TRUE;return'**Multi-insert array "'.$k.'" is different.**';}}else{$proto=array_keys($v);}}else{$this->hasError=TRUE;return'**Unexpected type '.gettype($v).'**';}$pair=explode('%',$k,2);$kx[]=$this->identifiers->{$pair[0]};foreach($v
  545. as$k2=>$v2){$vx[$k2][]=$this->formatValue($v2,isset($pair[1])?$pair[1]:(is_array($v2)?'ex':FALSE));}}foreach($vx
  546. as$k=>$v){$vx[$k]='('.implode(', ',$v).')';}return'('.implode(', ',$kx).') VALUES '.implode(', ',$vx);case'by':foreach($value
  547. as$k=>$v){if(is_array($v)){$vx[]=$this->formatValue($v,'ex');}elseif(is_string($k)){$v=(is_string($v)&&strncasecmp($v,'d',1))||$v>0?'ASC':'DESC';$vx[]=$this->identifiers->$k.' '.$v;}else{$vx[]=$this->identifiers->$v;}}return
  548. implode(', ',$vx);case'ex':case'sql':$translator=new
  549. self($this->driver);return$translator->translate($value);default:foreach($value
  550. as$v){$vx[]=$this->formatValue($v,$modifier);}return
  551. implode(', ',$vx);}}if($modifier){if($value!==NULL&&!is_scalar($value)&&!($value
  552. instanceof
  553. DateTime)){$this->hasError=TRUE;return'**Unexpected type '.gettype($value).'**';}switch($modifier){case's':case'bin':case'b':return$value===NULL?'NULL':$this->driver->escape($value,$modifier);case'sN':case'sn':return$value==''?'NULL':$this->driver->escape($value,dibi::TEXT);case'iN':case'in':if($value=='')$value=NULL;case'i':case'u':if(is_string($value)&&preg_match('#[+-]?\d++(e\d+)?$#A',$value)){return$value;}else{return$value===NULL?'NULL':(string)(int)($value+0);}case'f':if(is_string($value)&&is_numeric($value)&&strpos($value,'x')===FALSE){return$value;}else{return$value===NULL?'NULL':rtrim(rtrim(number_format($value+0,5,'.',''),'0'),'.');}case'd':case't':if($value===NULL){return'NULL';}else{if(is_numeric($value)){$value=(int)$value;}elseif(is_string($value)){$value=new
  554. DateTime($value);}return$this->driver->escape($value,$modifier);}case'by':case'n':return$this->identifiers->$value;case'ex':case'sql':$value=(string)$value;$toSkip=strcspn($value,'`[\'":');if(strlen($value)!==$toSkip){$value=substr($value,0,$toSkip).preg_replace_callback('/(?=[`[\'":])(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|:(\S*?:)([a-zA-Z0-9._]?))/s',array($this,'cb'),substr($value,$toSkip));if(preg_last_error())throw
  555. new
  556. PcreException;}return$value;case'SQL':return(string)$value;case'and':case'or':case'a':case'l':case'v':$this->hasError=TRUE;return'**Unexpected type '.gettype($value).'**';default:$this->hasError=TRUE;return"**Unknown or invalid modifier %$modifier**";}}if(is_string($value)){return$this->driver->escape($value,dibi::TEXT);}elseif(is_int($value)){return(string)$value;}elseif(is_float($value)){return
  557. rtrim(rtrim(number_format($value,5,'.',''),'0'),'.');}elseif(is_bool($value)){return$this->driver->escape($value,dibi::BOOL);}elseif($value===NULL){return'NULL';}elseif($value
  558. instanceof
  559. DateTime){return$this->driver->escape($value,dibi::DATETIME);}else{$this->hasError=TRUE;return'**Unexpected '.gettype($value).'**';}}private
  560. function
  561. cb($matches){if(!empty($matches[11])){$cursor=&$this->cursor;if($cursor>=count($this->args)){$this->hasError=TRUE;return"**Extra placeholder**";}$cursor++;return$this->formatValue($this->args[$cursor-1],FALSE);}if(!empty($matches[10])){$mod=$matches[10];$cursor=&$this->cursor;if($cursor>=count($this->args)&&$mod!=='else'&&$mod!=='end'){$this->hasError=TRUE;return"**Extra modifier %$mod**";}if($mod==='if'){$this->ifLevel++;$cursor++;if(!$this->comment&&!$this->args[$cursor-1]){$this->ifLevelStart=$this->ifLevel;$this->comment=TRUE;return"/*";}return'';}elseif($mod==='else'){if($this->ifLevelStart===$this->ifLevel){$this->ifLevelStart=0;$this->comment=FALSE;return"*/";}elseif(!$this->comment){$this->ifLevelStart=$this->ifLevel;$this->comment=TRUE;return"/*";}}elseif($mod==='end'){$this->ifLevel--;if($this->ifLevelStart===$this->ifLevel+1){$this->ifLevelStart=0;$this->comment=FALSE;return"*/";}return'';}elseif($mod==='ex'){array_splice($this->args,$cursor,1,$this->args[$cursor]);return'';}elseif($mod==='lmt'){if($this->args[$cursor]!==NULL)$this->limit=(int)$this->args[$cursor];$cursor++;return'';}elseif($mod==='ofs'){if($this->args[$cursor]!==NULL)$this->offset=(int)$this->args[$cursor];$cursor++;return'';}else{$cursor++;return$this->formatValue($this->args[$cursor-1],$mod);}}if($this->comment)return'...';if($matches[1])return$this->identifiers->{$matches[1]};if($matches[2])return$this->identifiers->{$matches[2]};if($matches[3])return$this->driver->escape(str_replace("''","'",$matches[4]),dibi::TEXT);if($matches[5])return$this->driver->escape(str_replace('""','"',$matches[6]),dibi::TEXT);if($matches[7]){$this->hasError=TRUE;return'**Alone quote**';}if($matches[8]){$m=substr($matches[8],0,-1);$m=isset(dibi::$substs[$m])?dibi::$substs[$m]:call_user_func(dibi::$substFallBack,$m);return$matches[9]==''?$this->formatValue($m,FALSE):$m.$matches[9];}die('this should be never executed');}public
  562. function
  563. delimite($value){$value=self::substitute($value);$parts=explode('.',$value);foreach($parts
  564. as&$v){if($v!=='*')$v=$this->driver->escape($v,dibi::IDENTIFIER);}return
  565. implode('.',$parts);}public
  566. static
  567. function
  568. substitute($value){if(strpos($value,':')!==FALSE){return
  569. preg_replace_callback('#:([^:\s]*):#',array(__CLASS__,'subCb'),$value);}return$value;}private
  570. static
  571. function
  572. subCb($m){$m=$m[1];return
  573. isset(dibi::$substs[$m])?dibi::$substs[$m]:call_user_func(dibi::$substFallBack,$m);}}class
  574. DibiDataSource
  575. extends
  576. DibiObject
  577. implements
  578. IDataSource{private$connection;private$sql;private$result;private$count;private$totalCount;private$cols=array();private$sorting=array();private$conds=array();private$offset;private$limit;public
  579. function
  580. __construct($sql,DibiConnection$connection){if(strpbrk($sql," \t\r\n")===FALSE){$this->sql=$connection->getDriver()->escape($sql,dibi::IDENTIFIER);}else{$this->sql='('.$sql.') t';}$this->connection=$connection;}public
  581. function
  582. select($col,$as=NULL){if(is_array($col)){$this->cols=$col;}else{$this->cols[$col]=$as;}$this->result=NULL;return$this;}public
  583. function
  584. where($cond){if(is_array($cond)){$this->conds[]=$cond;}else{$this->conds[]=func_get_args();}$this->result=$this->count=NULL;return$this;}public
  585. function
  586. orderBy($row,$sorting='ASC'){if(is_array($row)){$this->sorting=$row;}else{$this->sorting[$row]=$sorting;}$this->result=NULL;return$this;}public
  587. function
  588. applyLimit($limit,$offset=NULL){$this->limit=$limit;$this->offset=$offset;$this->result=$this->count=NULL;return$this;}final
  589. public
  590. function
  591. getConnection(){return$this->connection;}public
  592. function
  593. getResult(){if($this->result===NULL){$this->result=$this->connection->nativeQuery($this->__toString());}return$this->result;}public
  594. function
  595. getIterator(){return$this->getResult()->getIterator();}public
  596. function
  597. fetch(){return$this->getResult()->fetch();}public
  598. function
  599. fetchSingle(){return$this->getResult()->fetchSingle();}public
  600. function
  601. fetchAll(){return$this->getResult()->fetchAll();}public
  602. function
  603. fetchAssoc($assoc){return$this->getResult()->fetchAssoc($assoc);}public
  604. function
  605. fetchPairs($key=NULL,$value=NULL){return$this->getResult()->fetchPairs($key,$value);}public
  606. function
  607. release(){$this->result=$this->count=$this->totalCount=NULL;}public
  608. function
  609. toFluent(){return$this->connection->select('*')->from('(%SQL) AS t',$this->__toString());}public
  610. function
  611. toDataSource(){return
  612. new
  613. self($this->__toString(),$this->connection);}public
  614. function
  615. __toString(){return$this->connection->translate('
  616. SELECT %n',(empty($this->cols)?'*':$this->cols),'
  617. FROM %SQL',$this->sql,'
  618. %ex',$this->conds?array('WHERE %and',$this->conds):NULL,'
  619. %ex',$this->sorting?array('ORDER BY %by',$this->sorting):NULL,'
  620. %ofs %lmt',$this->offset,$this->limit);}public
  621. function
  622. count(){if($this->count===NULL){$this->count=$this->conds||$this->offset||$this->limit?(int)$this->connection->nativeQuery('SELECT COUNT(*) FROM ('.$this->__toString().') AS t')->fetchSingle():$this->getTotalCount();}return$this->count;}public
  623. function
  624. getTotalCount(){if($this->totalCount===NULL){$this->totalCount=(int)$this->connection->nativeQuery('SELECT COUNT(*) FROM '.$this->sql)->fetchSingle();}return$this->totalCount;}}class
  625. DibiFluent
  626. extends
  627. DibiObject
  628. implements
  629. IDataSource{const
  630. REMOVE=FALSE;public
  631. static$masks=array('SELECT'=>array('SELECT','DISTINCT','FROM','WHERE','GROUP BY','HAVING','ORDER BY','LIMIT','OFFSET'),'UPDATE'=>array('UPDATE','SET','WHERE','ORDER BY','LIMIT'),'INSERT'=>array('INSERT','INTO','VALUES','SELECT'),'DELETE'=>array('DELETE','FROM','USING','WHERE','ORDER BY','LIMIT'));public
  632. static$modifiers=array('SELECT'=>'%n','FROM'=>'%n','IN'=>'%in','VALUES'=>'%l','SET'=>'%a','WHERE'=>'%and','HAVING'=>'%and','ORDER BY'=>'%by','GROUP BY'=>'%by');public
  633. static$separators=array('SELECT'=>',','FROM'=>',','WHERE'=>'AND','GROUP BY'=>',','HAVING'=>'AND','ORDER BY'=>',','LIMIT'=>FALSE,'OFFSET'=>FALSE,'SET'=>',','VALUES'=>',','INTO'=>FALSE);public
  634. static$clauseSwitches=array('JOIN'=>'FROM','INNER JOIN'=>'FROM','LEFT JOIN'=>'FROM','RIGHT JOIN'=>'FROM');private$connection;private$command;private$clauses=array();private$flags=array();private$cursor;private
  635. static$normalizer;public
  636. function
  637. __construct(DibiConnection$connection){$this->connection=$connection;if(self::$normalizer===NULL){self::$normalizer=new
  638. DibiLazyStorage(array(__CLASS__,'_formatClause'));}}public
  639. function
  640. __call($clause,$args){$clause=self::$normalizer->$clause;if($this->command===NULL){if(isset(self::$masks[$clause])){$this->clauses=array_fill_keys(self::$masks[$clause],NULL);}$this->cursor=&$this->clauses[$clause];$this->cursor=array();$this->command=$clause;}if(isset(self::$clauseSwitches[$clause])){$this->cursor=&$this->clauses[self::$clauseSwitches[$clause]];}if(array_key_exists($clause,$this->clauses)){$this->cursor=&$this->clauses[$clause];if($args===array(self::REMOVE)){$this->cursor=NULL;return$this;}if(isset(self::$separators[$clause])){$sep=self::$separators[$clause];if($sep===FALSE){$this->cursor=array();}elseif(!empty($this->cursor)){$this->cursor[]=$sep;}}}else{if($args===array(self::REMOVE)){return$this;}$this->cursor[]=$clause;}if($this->cursor===NULL){$this->cursor=array();}if(count($args)===1){$arg=$args[0];if($arg===TRUE){return$this;}elseif(is_string($arg)&&preg_match('#^[a-z:_][a-z0-9_.:]*$#i',$arg)){$args=array('%n',$arg);}elseif($arg
  641. instanceof
  642. self){$args=array_merge(array('('),$arg->_export(),array(')'));}elseif(is_array($arg)||$arg
  643. instanceof
  644. Traversable){if(isset(self::$modifiers[$clause])){$args=array(self::$modifiers[$clause],$arg);}elseif(is_string(key($arg))){$args=array('%a',$arg);}}}foreach($args
  645. as$arg)$this->cursor[]=$arg;return$this;}public
  646. function
  647. clause($clause,$remove=FALSE){$this->cursor=&$this->clauses[self::$normalizer->$clause];if($remove){trigger_error(__METHOD__.'(..., TRUE) is deprecated; use removeClause() instead.',E_USER_NOTICE);$this->cursor=NULL;}elseif($this->cursor===NULL){$this->cursor=array();}return$this;}public
  648. function
  649. removeClause($clause){$this->clauses[self::$normalizer->$clause]=NULL;return$this;}public
  650. function
  651. setFlag($flag,$value=TRUE){$flag=strtoupper($flag);if($value){$this->flags[$flag]=TRUE;}else{unset($this->flags[$flag]);}return$this;}final
  652. public
  653. function
  654. getFlag($flag){return
  655. isset($this->flags[strtoupper($flag)]);}final
  656. public
  657. function
  658. getCommand(){return$this->command;}final
  659. public
  660. function
  661. getConnection(){return$this->connection;}public
  662. function
  663. execute($return=NULL){$res=$this->connection->query($this->_export());return$return===dibi::IDENTIFIER?$this->connection->getInsertId():$res;}public
  664. function
  665. fetch(){if($this->command==='SELECT'){return$this->connection->query($this->_export(NULL,array('%lmt',1)))->fetch();}else{return$this->connection->query($this->_export())->fetch();}}public
  666. function
  667. fetchSingle(){if($this->command==='SELECT'){return$this->connection->query($this->_export(NULL,array('%lmt',1)))->fetchSingle();}else{return$this->connection->query($this->_export())->fetchSingle();}}public
  668. function
  669. fetchAll($offset=NULL,$limit=NULL){return$this->connection->query($this->_export(NULL,array('%ofs %lmt',$offset,$limit)))->fetchAll();}public
  670. function
  671. fetchAssoc($assoc){return$this->connection->query($this->_export())->fetchAssoc($assoc);}public
  672. function
  673. fetchPairs($key=NULL,$value=NULL){return$this->connection->query($this->_export())->fetchPairs($key,$value);}public
  674. function
  675. getIterator($offset=NULL,$limit=NULL){return$this->connection->query($this->_export(NULL,array('%ofs %lmt',$offset,$limit)))->getIterator();}public
  676. function
  677. test($clause=NULL){return$this->connection->test($this->_export($clause));}public
  678. function
  679. count(){return(int)$this->connection->query('SELECT COUNT(*) FROM (%ex',$this->_export(),') AS [data]')->fetchSingle();}public
  680. function
  681. toDataSource(){return
  682. new
  683. DibiDataSource($this->connection->translate($this->_export()),$this->connection);}final
  684. public
  685. function
  686. __toString(){return$this->connection->translate($this->_export());}protected
  687. function
  688. _export($clause=NULL,$args=array()){if($clause===NULL){$data=$this->clauses;}else{$clause=self::$normalizer->$clause;if(array_key_exists($clause,$this->clauses)){$data=array($clause=>$this->clauses[$clause]);}else{return
  689. array();}}foreach($data
  690. as$clause=>$statement){if($statement!==NULL){$args[]=$clause;if($clause===$this->command&&$this->flags){$args[]=implode(' ',array_keys($this->flags));}foreach($statement
  691. as$arg)$args[]=$arg;}}return$args;}public
  692. static
  693. function
  694. _formatClause($s){if($s==='order'||$s==='group'){$s.='By';trigger_error("Did you mean '$s'?",E_USER_NOTICE);}return
  695. strtoupper(preg_replace('#[a-z](?=[A-Z])#','$0 ',$s));}public
  696. function
  697. __clone(){foreach($this->clauses
  698. as$clause=>$val){$this->clauses[$clause]=&$val;unset($val);}$this->cursor=&$foo;}}class
  699. DibiDatabaseInfo
  700. extends
  701. DibiObject{private$reflector;private$name;private$tables;public
  702. function
  703. __construct(IDibiReflector$reflector,$name){$this->reflector=$reflector;$this->name=$name;}public
  704. function
  705. getName(){return$this->name;}public
  706. function
  707. getTables(){$this->init();return
  708. array_values($this->tables);}public
  709. function
  710. getTableNames(){$this->init();$res=array();foreach($this->tables
  711. as$table){$res[]=$table->getName();}return$res;}public
  712. function
  713. getTable($name){$name=DibiTranslator::substitute($name);$this->init();$l=strtolower($name);if(isset($this->tables[$l])){return$this->tables[$l];}else{throw
  714. new
  715. DibiException("Database '$this->name' has no table '$name'.");}}public
  716. function
  717. hasTable($name){$name=DibiTranslator::substitute($name);$this->init();return
  718. isset($this->tables[strtolower($name)]);}protected
  719. function
  720. init(){if($this->tables===NULL){$this->tables=array();foreach($this->reflector->getTables()as$info){$this->tables[strtolower($info['name'])]=new
  721. DibiTableInfo($this->reflector,$info);}}}}class
  722. DibiTableInfo
  723. extends
  724. DibiObject{private$reflector;private$name;private$view;private$columns;private$foreignKeys;private$indexes;private$primaryKey;public
  725. function
  726. __construct(IDibiReflector$reflector,array$info){$this->reflector=$reflector;$this->name=$info['name'];$this->view=!empty($info['view']);}public
  727. function
  728. getName(){return$this->name;}public
  729. function
  730. isView(){return$this->view;}public
  731. function
  732. getColumns(){$this->initColumns();return
  733. array_values($this->columns);}public
  734. function
  735. getColumnNames(){$this->initColumns();$res=array();foreach($this->columns
  736. as$column){$res[]=$column->getName();}return$res;}public
  737. function
  738. getColumn($name){$name=DibiTranslator::substitute($name);$this->initColumns();$l=strtolower($name);if(isset($this->columns[$l])){return$this->columns[$l];}else{throw
  739. new
  740. DibiException("Table '$this->name' has no column '$name'.");}}public
  741. function
  742. hasColumn($name){$name=DibiTranslator::substitute($name);$this->initColumns();return
  743. isset($this->columns[strtolower($name)]);}public
  744. function
  745. getForeignKeys(){$this->initForeignKeys();return$this->foreignKeys;}public
  746. function
  747. getIndexes(){$this->initIndexes();return$this->indexes;}public
  748. function
  749. getPrimaryKey(){$this->initIndexes();return$this->primaryKey;}protected
  750. function
  751. initColumns(){if($this->columns===NULL){$this->columns=array();foreach($this->reflector->getColumns($this->name)as$info){$this->columns[strtolower($info['name'])]=new
  752. DibiColumnInfo($this->reflector,$info);}}}protected
  753. function
  754. initIndexes(){if($this->indexes===NULL){$this->initColumns();$this->indexes=array();foreach($this->reflector->getIndexes($this->name)as$info){foreach($info['columns']as$key=>$name){$info['columns'][$key]=$this->columns[strtolower($name)];}$this->indexes[strtolower($info['name'])]=new
  755. DibiIndexInfo($info);if(!empty($info['primary'])){$this->primaryKey=$this->indexes[strtolower($info['name'])];}}}}protected
  756. function
  757. initForeignKeys(){throw
  758. new
  759. NotImplementedException;}}class
  760. DibiResultInfo
  761. extends
  762. DibiObject{private$driver;private$columns;private$names;public
  763. function
  764. __construct(IDibiResultDriver$driver){$this->driver=$driver;}public
  765. function
  766. getColumns(){$this->initColumns();return
  767. array_values($this->columns);}public
  768. function
  769. getColumnNames($fullNames=FALSE){$this->initColumns();$res=array();foreach($this->columns
  770. as$column){$res[]=$fullNames?$column->getFullName():$column->getName();}return$res;}public
  771. function
  772. getColumn($name){$name=DibiTranslator::substitute($name);$this->initColumns();$l=strtolower($name);if(isset($this->names[$l])){return$this->names[$l];}else{throw
  773. new
  774. DibiException("Result set has no column '$name'.");}}public
  775. function
  776. hasColumn($name){$name=DibiTranslator::substitute($name);$this->initColumns();return
  777. isset($this->names[strtolower($name)]);}protected
  778. function
  779. initColumns(){if($this->columns===NULL){$this->columns=array();$reflector=$this->driver
  780. instanceof
  781. IDibiReflector?$this->driver:NULL;foreach($this->driver->getResultColumns()as$info){$this->columns[]=$this->names[$info['name']]=new
  782. DibiColumnInfo($reflector,$info);}}}}class
  783. DibiColumnInfo
  784. extends
  785. DibiObject{private
  786. static$types;private$reflector;private$info;public
  787. function
  788. __construct(IDibiReflector$reflector=NULL,array$info){$this->reflector=$reflector;$this->info=$info;}public
  789. function
  790. getName(){return$this->info['name'];}public
  791. function
  792. getFullName(){return
  793. isset($this->info['fullname'])?$this->info['fullname']:NULL;}public
  794. function
  795. hasTable(){return!empty($this->info['table']);}public
  796. function
  797. getTable(){if(empty($this->info['table'])||!$this->reflector){throw
  798. new
  799. DibiException("Table is unknown or not available.");}return
  800. new
  801. DibiTableInfo($this->reflector,array('name'=>$this->info['table']));}public
  802. function
  803. getTableName(){return
  804. isset($this->info['table'])?$this->info['table']:NULL;}public
  805. function
  806. getType(){if(self::$types===NULL){self::$types=new
  807. DibiLazyStorage(array(__CLASS__,'detectType'));}return$this->info['nativetype']?self::$types->{$this->info['nativetype']}:dibi::TEXT;}public
  808. function
  809. getNativeType(){return$this->info['nativetype'];}public
  810. function
  811. getSize(){return
  812. isset($this->info['size'])?(int)$this->info['size']:NULL;}public
  813. function
  814. isUnsigned(){return
  815. isset($this->info['unsigned'])?(bool)$this->info['unsigned']:NULL;}public
  816. function
  817. isNullable(){return
  818. isset($this->info['nullable'])?(bool)$this->info['nullable']:NULL;}public
  819. function
  820. isAutoIncrement(){return
  821. isset($this->info['autoincrement'])?(bool)$this->info['autoincrement']:NULL;}public
  822. function
  823. getDefault(){return
  824. isset($this->info['default'])?$this->info['default']:NULL;}public
  825. function
  826. getVendorInfo($key){return
  827. isset($this->info['vendor'][$key])?$this->info['vendor'][$key]:NULL;}public
  828. static
  829. function
  830. detectType($type){static$patterns=array('BYTEA|BLOB|BIN'=>dibi::BINARY,'TEXT|CHAR|BIGINT|LONGLONG'=>dibi::TEXT,'BYTE|COUNTER|SERIAL|INT|LONG'=>dibi::INTEGER,'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC|NUMBER'=>dibi::FLOAT,'^TIME$'=>dibi::TIME,'TIME'=>dibi::DATETIME,'YEAR|DATE'=>dibi::DATE,'BOOL|BIT'=>dibi::BOOL);foreach($patterns
  831. as$s=>$val){if(preg_match("#$s#i",$type)){return$val;}}return
  832. dibi::TEXT;}}class
  833. DibiForeignKeyInfo
  834. extends
  835. DibiObject{private$name;private$references;public
  836. function
  837. __construct($name,array$references){$this->name=$name;$this->references=$references;}public
  838. function
  839. getName(){return$this->name;}public
  840. function
  841. getReferences(){return$this->references;}}class
  842. DibiIndexInfo
  843. extends
  844. DibiObject{private$info;public
  845. function
  846. __construct(array$info){$this->info=$info;}public
  847. function
  848. getName(){return$this->info['name'];}public
  849. function
  850. getColumns(){return$this->info['columns'];}public
  851. function
  852. isUnique(){return!empty($this->info['unique']);}public
  853. function
  854. isPrimary(){return!empty($this->info['primary']);}}class
  855. DibiProfiler
  856. extends
  857. DibiObject
  858. implements
  859. IDibiProfiler,IDebugPanel{static
  860. public$maxQueries=30;static
  861. public$maxLength=1000;private$file;public$useFirebug;public$explainQuery=TRUE;private$filter=self::ALL;public
  862. static$tickets=array();public
  863. static$fireTable=array(array('Time','SQL Statement','Rows','Connection'));public
  864. function
  865. __construct(array$config){if(class_exists('Debug',FALSE)&&is_callable('Debug::addPanel')){Debug::addPanel($this);}$this->useFirebug=isset($_SERVER['HTTP_USER_AGENT'])&&strpos($_SERVER['HTTP_USER_AGENT'],'FirePHP/');if(isset($config['filter'])){$this->setFilter($config['filter']);}if(isset($config['explain'])){$this->explainQuery=(bool)$config['explain'];}}pub

Large files files are truncated, but you can click here to view the full file