PageRenderTime 36ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/Yab/Db/Table.php

https://github.com/vib94/Framework
PHP | 482 lines | 257 code | 210 blank | 15 comment | 50 complexity | eaf64c35226928b88848aff9bc5e8e00 MD5 | raw file
  1. <?php
  2. /**
  3. * Yab Framework
  4. *
  5. * @category Yab_Db
  6. * @package Yab_Db_Table
  7. * @author Yann BELLUZZI
  8. * @copyright (c) 2010 YBellu
  9. * @license http://www.ybellu.com/yab-framework/license.html
  10. * @link http://www.ybellu.com/yab-framework
  11. */
  12. class Yab_Db_Table extends Yab_Object {
  13. private $_adapter = null;
  14. private $_safe_primary = null;
  15. protected $_schema = null;
  16. protected $_name = null;
  17. protected $_columns = array();
  18. private $_saving = 0;
  19. final public function __construct($adapter = null, $name = null, $schema = null) {
  20. # trying to give the adapter
  21. if(!($adapter instanceof Yab_Db_Adapter_Abstract)) {
  22. $schema = $name;
  23. $name = $adapter;
  24. $adapter = Yab_Db_Adapter_Abstract::getDefaultAdapter();
  25. }
  26. $this->_adapter = $adapter;
  27. # trying to give the schema name
  28. if($this->_schema === null || $schema !== null) {
  29. if(!$schema) {
  30. $parts = explode('.', $this->_name ? $this->_name : $this->_adapter->unQuoteIdentifier($name));
  31. if(1 < count($parts)) {
  32. $schema = array_shift($parts);
  33. $schema = implode('.', $parts);
  34. } else {
  35. $schema = $this->_adapter->getSelectedSchema();
  36. }
  37. }
  38. $schema = $this->_adapter->unQuoteIdentifier($schema);
  39. if(!$schema)
  40. throw new Yab_Exception($schema.' is not a valid schema name');
  41. $this->_schema = $schema;
  42. }
  43. # trying to directly find by primary_key
  44. if($this->_name !== null && $name !== null)
  45. $this->feed($this->find($name)->toArray());
  46. # trying to give the table name
  47. if($this->_name === null && $name !== null)
  48. $this->_name = $this->_adapter->unQuoteIdentifier($name);
  49. $this->_init();
  50. }
  51. protected function _init() {}
  52. final public function getAdapter() {
  53. return $this->_adapter;
  54. }
  55. final public function getSchema() {
  56. return $this->_schema;
  57. }
  58. final public function getName() {
  59. return $this->_name;
  60. }
  61. final public function getTable($table = null) {
  62. if($table === null)
  63. return $this;
  64. return $this->getAdapter()->getTable($table);
  65. }
  66. final public function find($attributes) {
  67. return $this->search($attributes)->toRow();
  68. }
  69. final public function search($attributes) {
  70. return $this->fetchAll()->where($this->getSqlCondition($attributes));
  71. }
  72. final public function fetchAll() {
  73. return $this->_adapter->prepare('
  74. SELECT '.implode(', ', array_map(array($this->_adapter, 'quoteIdentifier'), $this->getColumns())).'
  75. FROM '.$this
  76. )->setValue(clone $this);
  77. }
  78. final public function getColumns() {
  79. if(count($this->_columns))
  80. return $this->_columns;
  81. $this->_columns = $this->_adapter->getColumns($this);
  82. return $this->_columns;
  83. }
  84. final public function getColumn($name) {
  85. foreach($this->getColumns() as $column)
  86. if($column->getName() == $name)
  87. return $column;
  88. throw new Yab_Exception($name.' is not a column of '.$this.' ('.implode(', ', $this->getColumns()).')');
  89. }
  90. final public function hasColumn($name) {
  91. foreach($this->getColumns() as $column)
  92. if($column->getName() == $name)
  93. return true;
  94. return false;
  95. }
  96. final protected function addColumn(Yab_Db_Table_Column $column, $override = false) {
  97. if(!$override && $this->hasColumn($column->getName()))
  98. throw new Yab_Exception('Table "'.get_class($this).'" has already a column named "'.$column->getName().'"');
  99. $this->_columns[$column->getName()] = $column;
  100. return $this;
  101. }
  102. final public function insert(array $values) {
  103. return $this->_adapter->insert($this, $values);
  104. }
  105. final public function update(array $values, $where) {
  106. return $this->_adapter->update($this, $values, $where);
  107. }
  108. final public function truncate() {
  109. return $this->_adapter->truncate($this);
  110. }
  111. final public function exists() {
  112. try {
  113. if(!$this->getSafePrimary())
  114. return false;
  115. $this->find($this->getSafePrimary());
  116. return true;
  117. } catch(Yab_Exception $e) {
  118. return false;
  119. }
  120. }
  121. final public function save($attributes = array()) {
  122. $this->_saving++;
  123. if(method_exists($this, 'preSave') && $this->_saving < 2)
  124. $this->preSave($attributes);
  125. if($this->exists()) {
  126. $this->_update($attributes);
  127. } else {
  128. $this->_insert($attributes);
  129. }
  130. if(method_exists($this, 'postSave') && $this->_saving < 2)
  131. $this->postSave($attributes);
  132. $this->_saving--;
  133. return $this;
  134. }
  135. final private function _insert($attributes = array()) {
  136. if($this->exists())
  137. throw new Yab_Exception('can not insert row, this row already exists');
  138. $this->insert($this->getAttributes($attributes));
  139. foreach($this->getColumns() as $column)
  140. if($column->getSequence())
  141. $this->set($column->getName(), $this->_adapter->getLastInsertId($this));
  142. return $this;
  143. }
  144. final private function _update($attributes = array()) {
  145. if(!$this->exists())
  146. throw new Yab_Exception('can not update row, this row does not exists');
  147. $where = $this->getSqlCondition();
  148. $attributes = $this->getAttributes($attributes);
  149. foreach($this->getSafePrimary() as $key => $value)
  150. if($value == $this->get($key))
  151. unset($attributes[$key]);
  152. $this->update($attributes, $where);
  153. return $this;
  154. }
  155. final public function delete($where = null) {
  156. if($where !== null)
  157. return $this->_adapter->delete($this, $where);
  158. if(!$this->exists())
  159. throw new Yab_Exception('can not delete row, this row does not exists');
  160. $where = $this->getSqlCondition();
  161. if(method_exists($this, 'preDelete'))
  162. $this->preDelete();
  163. $this->delete($where);
  164. if(method_exists($this, 'postDelete'))
  165. $this->postDelete();
  166. return $this;
  167. }
  168. final public function getSqlCondition($values = array(), $comparator = '=', $combinator = 'AND') {
  169. $where = array();
  170. if(!is_array($values))
  171. $values = array($values);
  172. $primary_columns = $this->getPrimaryColumns();
  173. foreach($values as $key => $value) {
  174. if(!is_numeric($key))
  175. continue;
  176. unset($values[$key]);
  177. $key = (string) array_shift($primary_columns);
  178. $values[$key] = $value;
  179. }
  180. if(!count($values))
  181. $values = $this->getSafePrimary();
  182. $comparator = trim((string) $comparator);
  183. $combinator = trim((string) $combinator);
  184. foreach($values as $key => $value) {
  185. $condition = $this->_adapter->quoteIdentifier($key);
  186. if(is_array($value)) {
  187. if($this->getColumn($key)->getQuotable())
  188. $value = implode(', ', array_map(array($this->_adapter, 'quote'), $value));
  189. if(in_array($comparator, array('!=', '<>'))) {
  190. $condition .= ' NOT IN ('.$value.')';
  191. } else {
  192. $condition .= ' IN ('.$value.')';
  193. }
  194. } else {
  195. $condition .= ' '.$comparator.' ';
  196. $condition .= $this->getColumn($key)->getQuotable() ? $this->_adapter->quote($value) : $value;
  197. }
  198. array_push($where, $condition);
  199. }
  200. $where = implode(' '.$combinator.' ', $where);
  201. return $where;
  202. }
  203. final public function getSafePrimary() {
  204. return $this->_safe_primary;
  205. }
  206. final public function getPrimary() {
  207. $primary = array();
  208. foreach($this->getPrimaryColumns() as $column)
  209. $primary[$column->getName()] = $this->get($column->getName());
  210. return $primary;
  211. }
  212. final public function getPrimaryColumns() {
  213. $primary_columns = array();
  214. foreach($this->getColumns() as $column) {
  215. if(!$column->getPrimary())
  216. continue;
  217. array_push($primary_columns, $column);
  218. }
  219. return $primary_columns;
  220. }
  221. final public function safePopulate(array $attributes = array()) {
  222. foreach($attributes as $key => $value) {
  223. try {
  224. $this->set($key, $value);
  225. } catch(Yab_Exception $e) {
  226. continue;
  227. }
  228. }
  229. return $this;
  230. }
  231. public function getForm(array $attributes = array('method' => 'post', 'action' => '')) {
  232. $form = new Yab_Form($attributes);
  233. foreach($this->getColumns() as $column) {
  234. if($column->getPrimary() || $column->getSequence())
  235. continue;
  236. $form->setElement($column->getName(), array(
  237. 'type' => 'text',
  238. 'label' => $column->getName(),
  239. 'id' => $column->getName(),
  240. 'value' => $this->has($column->getName()) ? $this->get($column->getName()) : $column->getDefaultValue(),
  241. ));
  242. }
  243. return $form;
  244. }
  245. final public function get($key, $filters = null) {
  246. if(!$this->hasColumn($key))
  247. throw new Yab_Exception($key.' is not a valid column name in table '.$this->getName());
  248. return parent::get($key, $filters);
  249. }
  250. final public function set($key, $value) {
  251. if(!$this->hasColumn($key))
  252. throw new Yab_Exception($key.' is not a valid column name in table '.$this->getName());
  253. parent::set($key, $value);
  254. try {
  255. if($this->_safe_primary === null && $this->getPrimary())
  256. $this->_safe_primary = $this->getPrimary();
  257. } catch(Yab_Exception $e) {}
  258. return $this;
  259. }
  260. final public function resetPrimary() {
  261. $this->_safe_primary = null;
  262. return $this;
  263. }
  264. final public function clear() {
  265. parent::clear();
  266. return $this->resetPrimary();
  267. }
  268. final public function __toString() {
  269. return $this->_adapter->formatTable($this);
  270. }
  271. }
  272. // Do not clause PHP tags unless it is really necessary