5 const NOSET
= '*!NOSET!*';
19 static private $_cache;
21 static private $_global_cache_enabled = false;
23 static public function setDefaultConnection(smp_Db
$db)
33 static public function getDefaultConnection()
45 private $_primary = 'id';
48 private $_data = array();
49 private $_types = array();
51 private $_cache_enabled = false;
53 protected $_id = false;
55 static private $_ops = array(
63 static public function create($table,smp_Db
$db=null)
70 final public function reset()
72 $this->_data
= array();
74 $this->_order
= array();
77 final public function getId()
82 final public function isCacheEnabled()
84 if ($this instanceof self
) {
85 return isset($this->_cache_enabled
) ?
$this->_cache_enabled
: self
::$_global_cache_enabled;
87 return self
::$_global_cache_enabled;
91 final public function enableCaching()
93 if ($this instanceof self
) {
94 $this->_cache_enabled
= true;
96 self
::$_global_cache_enabled = true;
100 final public function disableCaching()
102 if ($this instanceof self
) {
103 $this->_cache_enabled
= false;
105 self
::$_global_cache_enabled = false;
109 final public function __construct(smp_Db
$db = null)
111 if ($this->isCacheEnabled() && !(self
::$_cache instanceof smp_Cache
))
113 self
::$_cache = Simplicity
::getInstance()->getCache();
116 $this->_conn
= isset($db) ?
$db : self
::$_db;
121 final protected function setTable($table)
123 $this->_table
= $table;
126 final protected function setType($column,smp_DataTableType
$type)
128 $this->_types
[$column] = $type;
131 final protected function setPrimary($primary)
133 $this->_primary
= $primary;
136 public function init() {}
138 private function setCacheData($prefix,array $data,$timeout=null)
140 if (!$this->isCacheEnabled()) return false;
141 foreach ($data as $k => $v)
143 $key = md5($this->_table
.$prefix.$k);
144 self
::$_cache->set($key,$v,$timeout);
148 private function getCacheData($prefix,$key)
150 if (!$this->isCacheEnabled()) return false;
151 $key = md5($this->_table
.$prefix.$key);
152 return self
::$_cache->get($key);
155 private function delCacheData($prefix,array $keys)
157 if (!$this->isCacheEnabled()) return false;
158 foreach ($data as $key)
160 $key = md5($this->_table
.$prefix.$key);
161 self
::$_cache->del($key);
165 final public function find($search,$cache=null)
169 if (is_array($search)) {
170 $key = implode(array_keys($search)).implode($search);
176 if (!$id = $this->getCacheData('find',$key))
178 if (is_array($search))
180 list($qry,$params) = $this->_search($search);
181 $row = $this->_conn
->query($qry,$params);
182 if (isset($row[0])) $row = $row[0];
183 $id = isset($row[$this->_primary
]) ?
$row[$this->_primary
] : false;
187 $qry = "select `{$this->_primary}` from `{$this->_table}` where `{$this->_primary}` = ?";
188 $row = $this->_conn
->query($qry,array($search));
189 $id = isset($row[$this->_primary
]) ?
$row[$this->_primary
] : false;
192 $this->setCacheData('find',array($key => $id),(is_array($search) ?
$cache : null));
199 final public function get($name,$no_overload=false)
201 if (!$no_overload && $val = $this->preGet($name)) $this->_data
[$name] = $val;
203 if (!isset($this->_data
[$name]) && !$this->_data
[$name] = $this->getCacheData('get'.$this->_id
,$name)) {
204 if (!$this->_id
) return false;
206 $qry = "select `{$name}` from `{$this->_table}` where `{$this->_primary}` = ?";
208 $row = $this->_conn
->query($qry,array($this->_id
));
210 if (!isset($row[$name])) return false;
212 $this->_data
[$name] = $row[$name];
214 $this->setCacheData('get'.$this->_id
,array($name => $this->_data
[$name]));
217 if ($this->_data
[$name]) {
218 if (isset($this->_types
[$name])) {
219 return $this->_types
[$name]->formatOut($this->_data
[$name]);
221 return $this->_data
[$name];
227 final public function __get($name) {
228 return $this->get($name);
231 final public function __set($name,$value) {
232 return $this->set($name,$value);
235 final public function __unset($name)
240 final public function del($name)
242 unset($this->_data
[$name]);
245 final public function set($name,$value)
247 $value = $this->preSet($name,$value);
249 if ($value == self
::NOSET
) return false;
251 if (isset($this->_types
[$name]))
253 $value = $this->_types
[$name]->formatIn($value);
256 if ($name == $this->_primary
)
261 $this->_data
[$name] = $value;
264 final private function filterSearchValue($val,$col)
267 $op = isset(self
::$_ops[$op]) ? self
::$_ops[$op] : '=';
268 return "`{$col}` {$op} ?";
271 final private function filterSearch($filter,$col) {
274 if (is_array($filter)) {
275 if (!is_numeric(key($filter))) {
276 $filter = array($filter);
278 while ($fil = array_shift($filter))
280 $vals[] = current($fil);
281 $filters[] = $this->filterSearchValue($fil,$col);
284 $filters = implode(' and ',$filters);
287 $filters = "`{$col}` = ?";
291 return array($filters,$vals);
294 final private function formatSearchFilter($v)
299 final private function mergeSearchFilters($filter)
303 while ($fil = array_shift($filter))
305 $mfilters[] = $fil[0];
306 $mvals = array_merge($mvals,$fil[1]);
308 $mfilters = array_map(array($this,'formatSearchFilter'),$mfilters);
309 $mfilters = implode(' and ',$mfilters);
310 return array($mfilters,$mvals);
313 final private function _search($search)
318 if ($search != 'all') {
319 list($filters,$params) = $this->mergeSearchFilters(array_map(array($this,'filterSearch'),$search,array_keys($search)));
322 $qry = "select `{$this->_primary}` from `{$this->_table}`";
324 if ($search != 'all')
326 $qry .= " where {$filters}";
329 if (!is_array($params)) $params = array();
331 return array($qry,$params);
334 final private function fixSearchIds($val)
336 return $val[$this->_primary
];
340 * Get a smp_DataTableIterator
342 * @param array|string $search Search query
343 * @param int $cache Cache timeout in seconds (0 for until cleared)
344 * @return smp_DataTableIterator
346 final public function search($search,$cache=null)
348 if (is_array($search)) {
349 $key = md5(var_export($search,true));
354 if (!$ids = $this->getCacheData('search',$key))
356 list($qry,$params) = $this->_search($search);
358 $ids = $this->_conn
->query($qry,$params);
359 $ids = array_map(array($this,'fixSearchIds'),$ids);
360 if (isset($cache)) $this->setCacheData('search',array($key=>$ids),$cache);
363 $it = new smp_DataTableIterator($ids,$this);
366 $it->orderBy($this->_order
);
367 $this->_order
= false;
373 final public function getData() {
374 if (!$this->_id
) return false;
376 $cols = $this->_conn
->getMeta()->getTable($this->_table
);
378 foreach($cols as $col => $meta) {
379 $row[$col] = $this->get($col);
385 final public function getColumnMeta($column)
387 $cols = $this->_conn
->getMeta()->getTable($this->_table
);
388 return isset($cols[$column]) ?
$cols[$column] : false;
391 final public function setData($data=array()) {
392 foreach ($data as $name => $value)
394 $this->set($name,$value);
398 final public function save($no_hooks=false)
400 if ($this->_id
) return $this->update($no_hooks);
402 return $this->insert($no_hooks);
405 final public function delete($no_hooks=false)
407 if (!$this->_id
) {return false;}
409 if (!$no_hooks) $this->preDelete();
411 $qry = "delete from {$this->_table} where `{$this->_primary}` = ?";
413 $this->_conn
->query($qry,array($this->_id
));
415 $this->delCacheData($this->_id
,array_keys($this->_data
));
417 if (!$no_hooks) $this->postDelete($this->_id
);
422 protected function preSet($name,$value) { return $value; }
423 protected function preGet($name) { return false; }
425 protected function preAdd() {}
426 protected function postAdd() {}
427 protected function preUpdate() {}
428 protected function postUpdate() {}
429 protected function preDelete() {}
430 protected function postDelete($id) {}
432 final private function fixInsertVal($val)
437 final private function insert($no_hooks)
439 if (!count($this->_data
)) return false;
441 if (!$no_hooks) $this->preAdd();
443 if (isset($this->_data
[$this->_primary
])) unset($this->_data
[$this->_primary
]);
445 $cols = array_keys($this->_data
);
447 $vals = implode(',',array_fill(0,count($cols),'?'));
449 $cols = array_map(array($this,'fixInsertVal'),$cols);
450 $cols = implode(',',$cols);
452 $qry = "insert into {$this->_table} ({$cols}) values ({$vals})";
453 $this->_conn
->query($qry,array_values($this->_data
));
455 $id = $this->_conn
->lastInsertId();
459 $this->setCacheData($this->_id
,$this->_data
);
461 if (!$no_hooks) $this->postAdd($this->_id
);
466 final private function fixUpdateVal($val)
468 return "`{$val}` = ?";
471 final private function update($no_hooks)
473 if (!$this->_id
) return false;
474 if (!count($this->_data
)) return true;
476 if (!$no_hooks) $this->preUpdate();
478 if (isset($this->_data
[$this->_primary
])) unset($this->_data
[$this->_primary
]);
480 $cols = array_keys($this->_data
);
481 $cols = array_map(array($this,'fixUpdateVal'),$cols);
482 $cols = implode(',',$cols);
484 $qry = "update {$this->_table} set {$cols} where `{$this->_primary}` = ?";
486 $params = array_merge(array_values($this->_data
),array($this->_id
));
488 $this->_conn
->query($qry,$params);
490 $this->setCacheData($this->_id
,$this->_data
);
492 if (!$no_hooks) $this->postUpdate($this->_id
);