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