/lib/Controller/Data/Array.php
http://github.com/atk4/atk4 · PHP · 212 lines · 180 code · 24 blank · 8 comment · 25 complexity · 2fdbf41ad4d181f370528584c7685290 MD5 · raw file
- <?php
- /**
- * Undocumented
- */
- class Controller_Data_Array extends Controller_Data
- {
- public $supportConditions = true;
- public $supportLimit = true;
- public $supportOrder = false;
- public $supportOperators = array(
- '=' => true,
- '>' => true,
- '>=' => true,
- '<=' => true,
- '<' => true,
- '!=' => true,
- 'like' => true
- );
- public function setSource($model, $table)
- {
- if (!is_array($table)) {
- throw $this->exception('Wrong type: expected array')
- ->addMoreInfo('source', $table);
- }
- if (!$model->hasMethod('push')) {
- $model->addMethod('push', $this);
- }
- // convert single dimension arrays
- reset($table);
- list(, $firstrow) = @each($table);
- if (!is_array($firstrow)) {
- // assuming that this array needs to be converted
- foreach ($table as $key => &$name) {
- $name = array($model->id_field => $key, $model->title_field => $name);
- }
- return parent::setSource($model, $table);
- }
- $data = array();
- foreach ($table as $key => $row) {
- $id = isset($row[$model->id_field]) ? $row[$model->id_field] : $key;
- $data[$id] = $row;
- }
- return parent::setSource($model, $data);
- }
- public function save($model, $id, $data)
- {
- $oldId = $id;
- if (is_null($id)) { // insert
- $newId = $data[$model->id_field] ?: $this->generateNewId($model);
- if (isset($model->_table[$this->short_name][$newId])) {
- throw $this->exception('This id is already used. Load the model before')
- ->addMoreInfo('id', $data[$model->id_field]);
- }
- } else { // update
- //unset($model->_table[$this->short_name][$oldId]);
- $newId = $id; //$data[$model->id_field];
- $data = array_merge($model->_table[$this->short_name][$newId], $data);
- }
- $data[$model->id_field] = $newId;
- $model->_table[$this->short_name][$newId] = $data;
- $model->data = $data;
- return $newId;
- }
- public function delete($model, $id)
- {
- unset($model->_table[$this->short_name][$id]);
- }
- public function loadById($model, $id)
- {
- if (isset($model->_table[$this->short_name][$id])) {
- $model->id = $id;
- $model->data = $model->_table[$this->short_name][$id];
- return true;
- }
- return false;
- }
- public function loadByConditions($model)
- {
- $ids = $this->getIdsFromConditions($model->_table[$this->short_name], $model->conditions);
- if (!empty($ids)) {
- $id = array_pop($ids);
- $model->id = $id;
- $model->data = $model->_table[$this->short_name][$id];
- }
- }
- public function deleteAll($model)
- {
- $ids = $this->getIdsFromConditions($model->_table[$this->short_name], $model->conditions);
- foreach ($ids as $id) {
- $this->delete($model, $id);
- }
- }
- public function prefetchAll($model)
- {
- // TODO: miss ordering...
- return $this->getIdsFromConditions($model->_table[$this->short_name], $model->conditions, $model->limit);
- }
- public function loadCurrent($model, &$cursor)
- {
- if (!$this->loadByID($model, array_shift($cursor))) {
- $model->id = null;
- $model->data = array();
- }
- }
- // resolve all conditions
- public function getIdsFromConditions($rows, $conditions, $limit = null)
- {
- $withLimit = !is_null($limit) && (is_array($limit) && !is_null($limit[0]));
- if ($withLimit) {
- $max = is_null($limit[1]) ? $limit[0] : ($limit[0] + $limit[1]);
- }
- $ids = array();
- foreach ($rows as $id => $row) {
- if ($id === '__ids__') {
- continue;
- }
- $valid = true;
- foreach ($conditions as $c) {
- if (!$this->isValid($row, $c)) {
- $valid = false;
- break;
- }
- }
- if ($valid === true) {
- $ids[] = $id;
- if ($withLimit && isset($max) && count($ids) > $max) {
- break;
- }
- }
- }
- if ($withLimit) {
- if ($limit[1] === null) {
- $ids = array_slice($ids, 0, $limit[0]);
- } else {
- $ids = array_slice($ids, $limit[0], $limit[1]);
- }
- }
- return $ids;
- }
- public function isValid($row, $conditions)
- {
- $value = $row[$conditions[0]];
- $op = $conditions[1];
- $expected = $conditions[2];
- switch ($op) {
- case '=':
- return $value === $expected;
- case '>':
- return $value > $expected;
- case '>=':
- return $value >= $expected;
- case '<=':
- return $value <= $expected;
- case '<':
- return $value < $expected;
- case '!=':
- return $value != $expected;
- case 'like':
- $pattern = '/^' . str_replace('%', '.*', preg_quote($expected, '/')) . '$/i';
- return (bool) preg_match($pattern, $value);
- default:
- throw $this->exception('Unknown operator')
- ->addMoreInfo('operator', $op);
- }
- }
- public function generateNewId($model)
- {
- $ids = array_keys($model->_table[$this->short_name]);
- $type = $model->getElement($model->id_field)->type();
- if (in_array($type, array('int', 'integer'))) {
- return count($ids) === 0 ? 1 : (max($ids) + 1);
- } elseif (in_array($type, array('str', 'string'))) {
- return uniqid();
- } else {
- throw $this->exception('Unknown id type')
- ->addMoreInfo('type', $type)
- ->addMoreInfo('support', array('int', 'str'));
- }
- }
- public function count($model)
- {
- return count($model->_table[$this->short_name]);
- }
- public function push($model, $row)
- {
- $model->_table[$this->short_name][] = $row;
- }
- }