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