1de02284cSSzymon Olewniczak<?php 2de02284cSSzymon Olewniczak 3de02284cSSzymon Olewniczaknamespace dokuwiki\plugin\bez\mdl; 4de02284cSSzymon Olewniczak 5de02284cSSzymon Olewniczakabstract class Factory { 6de02284cSSzymon Olewniczak /** @var Model */ 7de02284cSSzymon Olewniczak protected $model; 8de02284cSSzymon Olewniczak 9de02284cSSzymon Olewniczak protected function filter_field_map($field) { 10de02284cSSzymon Olewniczak return $field; 11de02284cSSzymon Olewniczak } 12de02284cSSzymon Olewniczak 13de02284cSSzymon Olewniczak protected abstract function select_query(); 14de02284cSSzymon Olewniczak 15de02284cSSzymon Olewniczak protected function build_where($filters=array()) { 16de02284cSSzymon Olewniczak $execute = array(); 17de02284cSSzymon Olewniczak $where_q = array(); 18de02284cSSzymon Olewniczak foreach ($filters as $filter => $value) { 19de02284cSSzymon Olewniczak $field = $this->filter_field_map($filter); 20de02284cSSzymon Olewniczak 21de02284cSSzymon Olewniczak //parser 22de02284cSSzymon Olewniczak $operator = '='; 23de02284cSSzymon Olewniczak $function = ''; 24de02284cSSzymon Olewniczak $function_args = array(); 25de02284cSSzymon Olewniczak if (is_array($value)) { 26de02284cSSzymon Olewniczak $operators = array('!=', '<', '>', '<=', '>=', 'LIKE', 'BETWEEN', 'OR'); 27de02284cSSzymon Olewniczak $functions = array('', 'date'); 28de02284cSSzymon Olewniczak 29de02284cSSzymon Olewniczak $operator = $value[0]; 30de02284cSSzymon Olewniczak $function = isset($value[2]) ? $value[2] : ''; 31de02284cSSzymon Olewniczak 32de02284cSSzymon Olewniczak if (is_array($function)) { 33de02284cSSzymon Olewniczak $function = $function[0]; 34de02284cSSzymon Olewniczak $function_args = array_slice($value[2], 1); 35de02284cSSzymon Olewniczak } 36de02284cSSzymon Olewniczak 37de02284cSSzymon Olewniczak $value = $value[1]; 38de02284cSSzymon Olewniczak 39de02284cSSzymon Olewniczak if (!in_array($operator, $operators)) { 40de02284cSSzymon Olewniczak throw new \Exception('unknown operator: '.$operator); 41de02284cSSzymon Olewniczak } 42de02284cSSzymon Olewniczak 43de02284cSSzymon Olewniczak if (!in_array($function, $functions)) { 44de02284cSSzymon Olewniczak throw new \Exception('unknown function: '.$function); 45de02284cSSzymon Olewniczak } 46de02284cSSzymon Olewniczak } 47de02284cSSzymon Olewniczak 48de02284cSSzymon Olewniczak //builder 49de02284cSSzymon Olewniczak if ($operator === 'BETWEEN') { 50de02284cSSzymon Olewniczak if (count($value) < 2) { 51de02284cSSzymon Olewniczak throw new \Exception('wrong BETWEEN argument. provide two values'); 52de02284cSSzymon Olewniczak } 53de02284cSSzymon Olewniczak if ($function !== '') { 54de02284cSSzymon Olewniczak array_unshift($function_args, $field); 55de02284cSSzymon Olewniczak $where_q[] = "$function(".implode(',', $function_args).") BETWEEN :${filter}_start AND :${filter}_end"; 56de02284cSSzymon Olewniczak } else { 57de02284cSSzymon Olewniczak $where_q[] = "$field BETWEEN :${filter}_start AND :${filter}_end"; 58de02284cSSzymon Olewniczak } 59de02284cSSzymon Olewniczak $execute[":${filter}_start"] = $value[0]; 60de02284cSSzymon Olewniczak $execute[":${filter}_end"] = $value[1]; 61de02284cSSzymon Olewniczak } elseif ($operator === 'OR') { 62de02284cSSzymon Olewniczak if (!is_array($value)) { 63de02284cSSzymon Olewniczak throw new \Exception('$data should be an array'); 64de02284cSSzymon Olewniczak } 65de02284cSSzymon Olewniczak 66de02284cSSzymon Olewniczak $where_array = array(); 67de02284cSSzymon Olewniczak 68de02284cSSzymon Olewniczak foreach ($value as $k => $v) { 69de02284cSSzymon Olewniczak $exec = ":${filter}_$k"; 70de02284cSSzymon Olewniczak $where_array[] = "$field = $exec"; 71de02284cSSzymon Olewniczak $execute[$exec] = $v; 72de02284cSSzymon Olewniczak } 73de02284cSSzymon Olewniczak $where_q[] = '('.implode('OR', $where_array).')'; 74de02284cSSzymon Olewniczak 75de02284cSSzymon Olewniczak 76de02284cSSzymon Olewniczak } else { 77de02284cSSzymon Olewniczak if ($function !== '') { 78de02284cSSzymon Olewniczak array_unshift($function_args, $field); 79de02284cSSzymon Olewniczak $where_q[] = "$function(".implode(',', $function_args).") $operator :$filter"; 80de02284cSSzymon Olewniczak } else { 81de02284cSSzymon Olewniczak $where_q[] = "$field $operator :$filter"; 82de02284cSSzymon Olewniczak } 83de02284cSSzymon Olewniczak $execute[":$filter"] = $value; 84de02284cSSzymon Olewniczak } 85de02284cSSzymon Olewniczak } 86de02284cSSzymon Olewniczak 87de02284cSSzymon Olewniczak $where = ''; 88de02284cSSzymon Olewniczak if (count($where_q) > 0) { 89de02284cSSzymon Olewniczak $where = ' WHERE '.implode(' AND ', $where_q); 90de02284cSSzymon Olewniczak } 91de02284cSSzymon Olewniczak return array($where, $execute); 92de02284cSSzymon Olewniczak } 93de02284cSSzymon Olewniczak 94de02284cSSzymon Olewniczak public function __construct(Model $model) { 95de02284cSSzymon Olewniczak $this->model = $model; 96de02284cSSzymon Olewniczak } 97de02284cSSzymon Olewniczak 98de02284cSSzymon Olewniczak public function acl_static($field) { 99de02284cSSzymon Olewniczak return $this->model->acl->check_static_field($this->get_table_name(), $field); 100de02284cSSzymon Olewniczak } 101de02284cSSzymon Olewniczak 102de02284cSSzymon Olewniczak //chek acl 103*8a638198SSzymon Olewniczak public function get_all($filters=array(), $orderby='', $desc=true, $defaults=array()) { 104de02284cSSzymon Olewniczak// $dummy = $this->get_dummy_object(); 105de02284cSSzymon Olewniczak// if ($dummy->acl_of('id') < BEZ_PERMISSION_VIEW) { 106de02284cSSzymon Olewniczak// throw new PermissionDeniedException(); 107de02284cSSzymon Olewniczak// } 108de02284cSSzymon Olewniczak// 109de02284cSSzymon Olewniczak// if ($this->select_query === NULL) { 110de02284cSSzymon Olewniczak// throw new \Exception('no select query defined'); 111de02284cSSzymon Olewniczak// } 112de02284cSSzymon Olewniczak 113de02284cSSzymon Olewniczak list($where_q, $execute) = $this->build_where($filters); 114de02284cSSzymon Olewniczak 115de02284cSSzymon Olewniczak $q = $this->select_query() . $where_q; 116de02284cSSzymon Olewniczak 117fe5d6d1eSSzymon Olewniczak if ($orderby != '') { 118fe5d6d1eSSzymon Olewniczak $fields = call_user_func(array($this->get_object_class_name(), 'get_columns')); 119fe5d6d1eSSzymon Olewniczak if (!in_array($orderby, $fields)) { 120fe5d6d1eSSzymon Olewniczak throw new \Exception('unknown field '.$orderby); 121fe5d6d1eSSzymon Olewniczak } 122fe5d6d1eSSzymon Olewniczak $q .= " ORDER BY $orderby"; 123fe5d6d1eSSzymon Olewniczak if ($desc) { 124fe5d6d1eSSzymon Olewniczak $q .= " DESC"; 125fe5d6d1eSSzymon Olewniczak } 126fe5d6d1eSSzymon Olewniczak } 127fe5d6d1eSSzymon Olewniczak 128de02284cSSzymon Olewniczak $sth = $this->model->db->prepare($q); 129de02284cSSzymon Olewniczak 130de02284cSSzymon Olewniczak $sth->setFetchMode(\PDO::FETCH_CLASS, $this->get_object_class_name(), 131*8a638198SSzymon Olewniczak array($this->model, $defaults)); 132de02284cSSzymon Olewniczak 133de02284cSSzymon Olewniczak $sth->execute($execute); 134de02284cSSzymon Olewniczak 135de02284cSSzymon Olewniczak return $sth; 136de02284cSSzymon Olewniczak } 137de02284cSSzymon Olewniczak 138de02284cSSzymon Olewniczak public function count($filters=array()) { 139de02284cSSzymon Olewniczak// $dummy = $this->get_dummy_object(); 140de02284cSSzymon Olewniczak// if ($dummy->acl_of('id') < BEZ_PERMISSION_VIEW) { 141de02284cSSzymon Olewniczak// throw new PermissionDeniedException(); 142de02284cSSzymon Olewniczak// } 143de02284cSSzymon Olewniczak 144de02284cSSzymon Olewniczak if ($this->acl_static('id') < BEZ_PERMISSION_VIEW) { 145de02284cSSzymon Olewniczak throw new PermissionDeniedException(); 146de02284cSSzymon Olewniczak } 147de02284cSSzymon Olewniczak 148de02284cSSzymon Olewniczak list($where_q, $execute) = $this->build_where($filters); 149de02284cSSzymon Olewniczak 150de02284cSSzymon Olewniczak $q = 'SELECT COUNT(*) FROM ' . $this->get_table_name() . ' ' . $where_q; 151de02284cSSzymon Olewniczak $sth = $this->model->db->prepare($q); 152de02284cSSzymon Olewniczak $sth->execute($execute); 153de02284cSSzymon Olewniczak 154de02284cSSzymon Olewniczak $count = $sth->fetchColumn(); 155de02284cSSzymon Olewniczak return $count; 156de02284cSSzymon Olewniczak } 157de02284cSSzymon Olewniczak 158*8a638198SSzymon Olewniczak public function get_one($id, $defaults=array()) { 159de02284cSSzymon Olewniczak// if ($this->select_query === NULL) { 160de02284cSSzymon Olewniczak// throw new \Exception('no select query defined'); 161de02284cSSzymon Olewniczak// } 162de02284cSSzymon Olewniczak 163de02284cSSzymon Olewniczak $q = $this->select_query().' WHERE '.$this->get_table_name().'.id = ?'; 164de02284cSSzymon Olewniczak 165de02284cSSzymon Olewniczak $sth = $this->model->db->prepare($q); 166de02284cSSzymon Olewniczak $sth->execute(array($id)); 167de02284cSSzymon Olewniczak 168de02284cSSzymon Olewniczak $obj = $sth->fetchObject($this->get_object_class_name(), 169*8a638198SSzymon Olewniczak array($this->model, $defaults)); 170de02284cSSzymon Olewniczak 171de02284cSSzymon Olewniczak if ($obj === false) { 172de02284cSSzymon Olewniczak throw new \Exception('there is no '.$this->get_table_name().' with id: '.$id); 173de02284cSSzymon Olewniczak } 174de02284cSSzymon Olewniczak 175de02284cSSzymon Olewniczak return $obj; 176de02284cSSzymon Olewniczak } 177de02284cSSzymon Olewniczak 178de02284cSSzymon Olewniczak public function get_table_name() { 179de02284cSSzymon Olewniczak $class = (new \ReflectionClass($this))->getShortName(); 180de02284cSSzymon Olewniczak return lcfirst(str_replace('Factory', '', $class)); 181de02284cSSzymon Olewniczak } 182de02284cSSzymon Olewniczak 183de02284cSSzymon Olewniczak public function get_object_class_name() { 184de02284cSSzymon Olewniczak $class = (new \ReflectionClass($this))->getName(); 185de02284cSSzymon Olewniczak return str_replace('Factory', '', $class); 186de02284cSSzymon Olewniczak } 187de02284cSSzymon Olewniczak// 188de02284cSSzymon Olewniczak// public function get_table_singular() { 189de02284cSSzymon Olewniczak// $table = $this->get_table_name(); 190de02284cSSzymon Olewniczak// $singular = substr($table, 0, -1); 191de02284cSSzymon Olewniczak// return $singular; 192de02284cSSzymon Olewniczak// } 193de02284cSSzymon Olewniczak// 194de02284cSSzymon Olewniczak// private function get_singular_object_name() { 195de02284cSSzymon Olewniczak// return ucfirst($this->get_table_singular()); 196de02284cSSzymon Olewniczak// } 197de02284cSSzymon Olewniczak// 198de02284cSSzymon Olewniczak// private function get_object_class_name() { 199de02284cSSzymon Olewniczak// return 'BEZ_mdl_'.$this->get_singular_object_name(); 200de02284cSSzymon Olewniczak// } 201de02284cSSzymon Olewniczak 202de02284cSSzymon Olewniczak// private function get_dummy_object_class_name() { 203de02284cSSzymon Olewniczak// return 'BEZ_mdl_Dummy_'.$this->get_singular_object_name(); 204de02284cSSzymon Olewniczak// } 205de02284cSSzymon Olewniczak 206de02284cSSzymon Olewniczak public function create_object($defaults=array()) { 207de02284cSSzymon Olewniczak $object_name = $this->get_object_class_name(); 208de02284cSSzymon Olewniczak 209de02284cSSzymon Olewniczak $obj = new $object_name($this->model, $defaults); 210de02284cSSzymon Olewniczak return $obj; 211de02284cSSzymon Olewniczak } 212de02284cSSzymon Olewniczak 2137fbf4c39SSzymon Olewniczak protected function beginTransaction() { 214de02284cSSzymon Olewniczak $this->model->sqlite->query('BEGIN TRANSACTION'); 215de02284cSSzymon Olewniczak } 216de02284cSSzymon Olewniczak 2177fbf4c39SSzymon Olewniczak protected function commitTransaction() { 218de02284cSSzymon Olewniczak $this->model->sqlite->query('COMMIT TRANSACTION'); 219de02284cSSzymon Olewniczak } 220de02284cSSzymon Olewniczak 2217fbf4c39SSzymon Olewniczak protected function rollbackTransaction() { 222de02284cSSzymon Olewniczak $this->model->sqlite->query('ROLLBACK'); 223de02284cSSzymon Olewniczak } 224de02284cSSzymon Olewniczak 225de02284cSSzymon Olewniczak// public function get_dummy_object() { 226de02284cSSzymon Olewniczak// if ($this->dummy_object === NULL) { 227de02284cSSzymon Olewniczak// $dummy_object_name = $this->get_dummy_object_class_name(); 228de02284cSSzymon Olewniczak// $this->dummy_object = new $dummy_object_name($this->model); 229de02284cSSzymon Olewniczak// } 230de02284cSSzymon Olewniczak// return $this->dummy_object; 231de02284cSSzymon Olewniczak// } 232de02284cSSzymon Olewniczak 233de02284cSSzymon Olewniczak public function save(Entity $obj) { 234de02284cSSzymon Olewniczak //if user can change id, he can modify record 235de02284cSSzymon Olewniczak //$this->model->acl->can_change($obj, 'id'); 236de02284cSSzymon Olewniczak 237de02284cSSzymon Olewniczak $set = array(); 238de02284cSSzymon Olewniczak $execute = array(); 239de02284cSSzymon Olewniczak $columns = array(); 240de02284cSSzymon Olewniczak foreach ($obj->get_columns() as $column) { 241de02284cSSzymon Olewniczak if ($obj->$column === null) continue; 242de02284cSSzymon Olewniczak //id is special -> when null we insert new row 243de02284cSSzymon Olewniczak// if ($column == 'id' && $obj->id == NULL) continue; 244de02284cSSzymon Olewniczak 245de02284cSSzymon Olewniczak// if ($obj->$column === null) { 246de02284cSSzymon Olewniczak// throw new \Exception('cannot save object becouse it has uninitialized parameter: '.$column); 247de02284cSSzymon Olewniczak// } 248de02284cSSzymon Olewniczak $set[] = ":$column"; 249de02284cSSzymon Olewniczak $columns[] = $column; 250de02284cSSzymon Olewniczak $value = $obj->$column; 251de02284cSSzymon Olewniczak if ($value === '') { 252de02284cSSzymon Olewniczak $execute[':'.$column] = null; 253de02284cSSzymon Olewniczak } else { 254de02284cSSzymon Olewniczak $execute[':'.$column] = $value; 255de02284cSSzymon Olewniczak } 256de02284cSSzymon Olewniczak } 257de02284cSSzymon Olewniczak 258de02284cSSzymon Olewniczak $query = 'REPLACE INTO '.$this->get_table_name().' 259de02284cSSzymon Olewniczak ('.implode(',', $columns).') 260de02284cSSzymon Olewniczak VALUES ('.implode(',', $set).')'; 261de02284cSSzymon Olewniczak 262de02284cSSzymon Olewniczak $sth = $this->model->db->prepare($query); 263*8a638198SSzymon Olewniczak $res = $sth->execute($execute); 264de02284cSSzymon Olewniczak 265de02284cSSzymon Olewniczak //new object is created 266de02284cSSzymon Olewniczak if ($obj->id === NULL) { 267de02284cSSzymon Olewniczak $reflectionClass = new \ReflectionClass($obj); 268de02284cSSzymon Olewniczak $reflectionProperty = $reflectionClass->getProperty('id'); 269de02284cSSzymon Olewniczak $reflectionProperty->setAccessible(true); 270de02284cSSzymon Olewniczak $reflectionProperty->setValue($obj, $this->model->db->lastInsertId()); 271de02284cSSzymon Olewniczak } 272de02284cSSzymon Olewniczak// $id = $this->model->db->lastInsertId(); 273de02284cSSzymon Olewniczak// $obj->set_id($id); 274de02284cSSzymon Olewniczak 275de02284cSSzymon Olewniczak// } 276de02284cSSzymon Olewniczak 277de02284cSSzymon Olewniczak// return $id; 278de02284cSSzymon Olewniczak } 279de02284cSSzymon Olewniczak 280*8a638198SSzymon Olewniczak public function initial_save(Entity $obj, $data) { 281*8a638198SSzymon Olewniczak if ($obj->id != NULL) { 282*8a638198SSzymon Olewniczak throw new \Exception('row already saved. use update_save'); 283*8a638198SSzymon Olewniczak } 284*8a638198SSzymon Olewniczak } 285*8a638198SSzymon Olewniczak 286*8a638198SSzymon Olewniczak public function update_save(Entity $obj, $data) { 287*8a638198SSzymon Olewniczak if ($obj->id == NULL) { 288*8a638198SSzymon Olewniczak throw new \Exception('row not saved. use initial_save()'); 289*8a638198SSzymon Olewniczak } 290*8a638198SSzymon Olewniczak } 291*8a638198SSzymon Olewniczak 292de02284cSSzymon Olewniczak protected function delete_from_db($id) { 293de02284cSSzymon Olewniczak $q = 'DELETE FROM '.$this->get_table_name().' WHERE id = ?'; 294de02284cSSzymon Olewniczak $sth = $this->model->db->prepare($q); 295de02284cSSzymon Olewniczak $sth->execute(array($id)); 296de02284cSSzymon Olewniczak } 297de02284cSSzymon Olewniczak 298de02284cSSzymon Olewniczak public function delete(Entity $obj) { 299*8a638198SSzymon Olewniczak $this->model->acl->can($obj, 'id', BEZ_PERMISSION_DELETE); 300de02284cSSzymon Olewniczak $this->delete_from_db($obj->id); 301de02284cSSzymon Olewniczak } 302de02284cSSzymon Olewniczak} 303