get_table_view(); if (!$table) { $table = $this->get_table_name(); } return "$table.$field"; } protected function select_query() { $table = $this->get_table_view(); if (!$table) { $table = $this->get_table_name(); } return "SELECT * FROM $table"; } public function get_table_view() { return false; } protected function build_where($filters=array()) { $execute = array(); $where_q = array(); foreach ($filters as $filter => $value) { $field = $this->filter_field_map($filter); //parser $operator = '='; $function = ''; $function_args = array(); if (is_array($value)) { $operators = array('!=', '<', '>', '<=', '>=', 'LIKE', 'BETWEEN', 'OR'); $functions = array('', 'date'); $operator = $value[0]; $function = isset($value[2]) ? $value[2] : ''; if (is_array($function)) { $function = $function[0]; $function_args = array_slice($value[2], 1); } $value = $value[1]; if (!in_array($operator, $operators)) { throw new \Exception('unknown operator: '.$operator); } if (!in_array($function, $functions)) { throw new \Exception('unknown function: '.$function); } } //builder if ($operator === 'BETWEEN') { if (count($value) < 2) { throw new \Exception('wrong BETWEEN argument. provide two values'); } if ($function !== '') { array_unshift($function_args, $field); $where_q[] = "$function(".implode(',', $function_args).") BETWEEN :${filter}_start AND :${filter}_end"; } else { $where_q[] = "$field BETWEEN :${filter}_start AND :${filter}_end"; } $execute[":${filter}_start"] = $value[0]; $execute[":${filter}_end"] = $value[1]; } elseif ($operator === 'OR') { if (!is_array($value)) { throw new \Exception('$data should be an array'); } $where_array = array(); foreach ($value as $k => $v) { $exec = ":${filter}_$k"; $where_array[] = "$field = $exec"; $execute[$exec] = $v; } $where_q[] = '('.implode(' OR ', $where_array).')'; } else { if ($function !== '') { array_unshift($function_args, $field); $where_q[] = "$function(".implode(',', $function_args).") $operator :$filter"; $execute[":$filter"] = $value; } elseif ($value === NULL || $value === '') { $where_q[] = "($field IS NULL OR $field = '')"; } elseif(is_int($value)) { $where_q[] = "$field $operator $value"; } else { $where_q[] = "$field $operator :$filter"; $execute[":$filter"] = $value; } } } $where = ''; if (count($where_q) > 0) { $where = ' WHERE '.implode(' AND ', $where_q); } return array($where, $execute); } public function __construct(Model $model) { $this->model = $model; } public function get_all($filters=array(), $orderby='', $defaults=array(), $limit=false) { list($where_q, $execute) = $this->build_where($filters); $q = $this->select_query() . $where_q; if ($orderby != '') { if (is_array($orderby)) $orderby = implode(', ', $orderby); $q .= " ORDER BY $orderby"; } if (is_int($limit)) { $q .= " LIMIT $limit"; } $sth = $this->model->db->prepare($q); $sth->setFetchMode(\PDO::FETCH_CLASS, $this->get_object_class_name(), array($this->model, $defaults)); $sth->execute($execute); return $sth; } public function count($filters=array()) { $table = $this->get_table_view(); if (!$table) { $table = $this->get_table_name(); } list($where_q, $execute) = $this->build_where($filters); $q = "SELECT COUNT(*) FROM $table " . $where_q; $sth = $this->model->db->prepare($q); $sth->execute($execute); $count = $sth->fetchColumn(); return $count; } public function exists($id) { $table = $this->get_table_name(); $q = "SELECT id FROM $table WHERE id = ?"; $sth = $this->model->db->prepare($q); $sth->execute(array($id)); if ($sth->fetch()) { return true; } return false; } public function get_one($id, $defaults=array()) { $table = $this->get_table_view(); if (!$table) { $table = $this->get_table_name(); } $q = $this->select_query()." WHERE $table.id = ?"; $sth = $this->model->db->prepare($q); $sth->execute(array($id)); $obj = $sth->fetchObject($this->get_object_class_name(), array($this->model, $defaults)); if ($obj === false) { throw new \Exception('there is no '.$this->get_table_name().' with id: '.$id); } return $obj; } public function get_table_name() { $class = (new \ReflectionClass($this))->getShortName(); return lcfirst(str_replace('Factory', '', $class)); } public function get_object_class_name() { $class = (new \ReflectionClass($this))->getName(); return str_replace('Factory', '', $class); } public function create_object($defaults=array()) { $object_name = $this->get_object_class_name(); $obj = new $object_name($this->model, $defaults); return $obj; } protected function beginTransaction() { $this->model->sqlite->query('BEGIN TRANSACTION'); } protected function commitTransaction() { $this->model->sqlite->query('COMMIT TRANSACTION'); } protected function rollbackTransaction() { $this->model->sqlite->query('ROLLBACK'); } protected function insert(Entity $obj) { if ($obj->id != NULL) { throw new \Exception('row already saved'); } $set = array(); $execute = array(); $columns = array(); foreach ($obj->get_columns() as $column) { if ($obj->$column === null) continue; $set[] = ":$column"; $columns[] = $column; $value = $obj->$column; if ($value === '') { $execute[':'.$column] = null; } else { $execute[':'.$column] = $value; } } $query = 'INSERT INTO '.$this->get_table_name().' ('.implode(',', $columns).') VALUES ('.implode(',', $set).')'; $sth = $this->model->db->prepare($query); $sth->execute($execute); $reflectionClass = new \ReflectionClass($obj); $reflectionProperty = $reflectionClass->getProperty('id'); $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($obj, $this->model->db->lastInsertId()); } protected function update(Entity $obj) { if ($obj->id == NULL) { throw new \Exception('row not inserted'); } $set = array(); $execute = array(':id' => $obj->id); foreach ($obj->get_columns() as $column) { if ($column == 'id') continue; $set[] = "$column=:$column"; $value = $obj->$column; if ($value === '') { $execute[':'.$column] = null; } else { $execute[':'.$column] = $value; } } $query = 'UPDATE ' . $this->get_table_name() . ' SET ' . implode(',', $set) . ' WHERE id=:id'; $sth = $this->model->db->prepare($query); $sth->execute($execute); } public function initial_save(Entity $obj, $data) { $obj->set_data($data); $this->insert($obj); } public function update_save(Entity $obj, $data) { $obj->set_data($data); $this->update($obj); } public function save(Entity $obj) { if ($obj->id == NULL) { $this->insert($obj); } else { $this->update($obj); } } protected function delete_from_db($id) { $q = 'DELETE FROM '.$this->get_table_name().' WHERE id = ?'; $sth = $this->model->db->prepare($q); $sth->execute(array($id)); } public function delete(Entity $obj) { if ($obj->acl_of('id') < BEZ_PERMISSION_DELETE) { throw new PermissionDeniedException('cannot delete'); } $this->delete_from_db($obj->id); } }