xref: /plugin/bez/mdl/Factory.php (revision de02284c1e90f3c0d8df29c1c019b3ef912eafd9)
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