xref: /plugin/bez/mdl/Factory.php (revision 53df74e7ac5ae4234aac1fa716a33878a039026f)
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
9e8827d73SSzymon Olewniczak	/** @var array of Entity */
10e8827d73SSzymon Olewniczak	protected $objects = array();
11e8827d73SSzymon Olewniczak
12de02284cSSzymon Olewniczak	protected function filter_field_map($field) {
13ff14b107SSzymon Olewniczak        $table = $this->get_table_view();
14ff14b107SSzymon Olewniczak        if (!$table) {
15ff14b107SSzymon Olewniczak            $table = $this->get_table_name();
16de02284cSSzymon Olewniczak        }
17de02284cSSzymon Olewniczak
18ff14b107SSzymon Olewniczak	    return "$table.$field";
19ff14b107SSzymon Olewniczak    }
20ff14b107SSzymon Olewniczak
21ff14b107SSzymon Olewniczak    protected function select_query() {
22ff14b107SSzymon Olewniczak	    $table = $this->get_table_view();
23ff14b107SSzymon Olewniczak	    if (!$table) {
24ff14b107SSzymon Olewniczak	        $table = $this->get_table_name();
25ff14b107SSzymon Olewniczak        }
26ff14b107SSzymon Olewniczak        return "SELECT * FROM $table";
27ff14b107SSzymon Olewniczak    }
28ff14b107SSzymon Olewniczak
29ff14b107SSzymon Olewniczak    public function get_table_view() {
30ff14b107SSzymon Olewniczak	    return false;
31ff14b107SSzymon Olewniczak    }
32de02284cSSzymon Olewniczak
33de02284cSSzymon Olewniczak    protected function build_where($filters=array()) {
34de02284cSSzymon Olewniczak		$execute = array();
35de02284cSSzymon Olewniczak		$where_q = array();
36de02284cSSzymon Olewniczak		foreach ($filters as $filter => $value) {
37de02284cSSzymon Olewniczak            $field = $this->filter_field_map($filter);
38de02284cSSzymon Olewniczak
39de02284cSSzymon Olewniczak            //parser
40de02284cSSzymon Olewniczak			$operator = '=';
41de02284cSSzymon Olewniczak            $function = '';
42de02284cSSzymon Olewniczak            $function_args = array();
43de02284cSSzymon Olewniczak			if (is_array($value)) {
44de02284cSSzymon Olewniczak                $operators = array('!=', '<', '>', '<=', '>=', 'LIKE', 'BETWEEN', 'OR');
45de02284cSSzymon Olewniczak                $functions = array('', 'date');
46de02284cSSzymon Olewniczak
47de02284cSSzymon Olewniczak                $operator = $value[0];
48de02284cSSzymon Olewniczak                $function = isset($value[2]) ? $value[2] : '';
49de02284cSSzymon Olewniczak
50de02284cSSzymon Olewniczak                if (is_array($function)) {
51de02284cSSzymon Olewniczak                    $function = $function[0];
52de02284cSSzymon Olewniczak                    $function_args = array_slice($value[2], 1);
53de02284cSSzymon Olewniczak                }
54de02284cSSzymon Olewniczak
55de02284cSSzymon Olewniczak                $value = $value[1];
56de02284cSSzymon Olewniczak
57de02284cSSzymon Olewniczak				if (!in_array($operator, $operators)) {
58de02284cSSzymon Olewniczak                    throw new \Exception('unknown operator: '.$operator);
59de02284cSSzymon Olewniczak                }
60de02284cSSzymon Olewniczak
61de02284cSSzymon Olewniczak                if (!in_array($function, $functions)) {
62de02284cSSzymon Olewniczak                    throw new \Exception('unknown function: '.$function);
63de02284cSSzymon Olewniczak                }
64de02284cSSzymon Olewniczak			}
65de02284cSSzymon Olewniczak
66de02284cSSzymon Olewniczak            //builder
67de02284cSSzymon Olewniczak            if ($operator === 'BETWEEN') {
68de02284cSSzymon Olewniczak                if (count($value) < 2) {
69de02284cSSzymon Olewniczak                    throw new \Exception('wrong BETWEEN argument. provide two values');
70de02284cSSzymon Olewniczak                }
71de02284cSSzymon Olewniczak                if ($function !== '') {
72de02284cSSzymon Olewniczak                    array_unshift($function_args, $field);
73de02284cSSzymon Olewniczak                    $where_q[] = "$function(".implode(',', $function_args).") BETWEEN :${filter}_start AND :${filter}_end";
74de02284cSSzymon Olewniczak                } else {
75de02284cSSzymon Olewniczak                    $where_q[] = "$field BETWEEN :${filter}_start AND :${filter}_end";
76de02284cSSzymon Olewniczak                }
77de02284cSSzymon Olewniczak                $execute[":${filter}_start"] = $value[0];
78de02284cSSzymon Olewniczak                $execute[":${filter}_end"] = $value[1];
79de02284cSSzymon Olewniczak            } elseif ($operator === 'OR') {
80de02284cSSzymon Olewniczak                if (!is_array($value)) {
81de02284cSSzymon Olewniczak                    throw new \Exception('$data should be an array');
82de02284cSSzymon Olewniczak                }
83de02284cSSzymon Olewniczak
84de02284cSSzymon Olewniczak                $where_array = array();
85de02284cSSzymon Olewniczak
86de02284cSSzymon Olewniczak                foreach ($value as $k => $v) {
87de02284cSSzymon Olewniczak                    $exec = ":${filter}_$k";
88de02284cSSzymon Olewniczak                    $where_array[] = "$field = $exec";
89de02284cSSzymon Olewniczak                    $execute[$exec] = $v;
90de02284cSSzymon Olewniczak                }
91de02284cSSzymon Olewniczak                $where_q[] = '('.implode('OR', $where_array).')';
92de02284cSSzymon Olewniczak
93de02284cSSzymon Olewniczak
94de02284cSSzymon Olewniczak            } else {
95de02284cSSzymon Olewniczak                if ($function !== '') {
96de02284cSSzymon Olewniczak                    array_unshift($function_args, $field);
97de02284cSSzymon Olewniczak                    $where_q[] = "$function(".implode(',', $function_args).") $operator :$filter";
98*53df74e7SSzymon Olewniczak                    $execute[":$filter"] = $value;
99*53df74e7SSzymon Olewniczak                } elseif (empty($value)) {
100*53df74e7SSzymon Olewniczak                    $where_q[] = "($field IS NULL OR $field = '')";
101de02284cSSzymon Olewniczak                } else {
102de02284cSSzymon Olewniczak                    $where_q[] = "$field $operator :$filter";
103de02284cSSzymon Olewniczak                    $execute[":$filter"] = $value;
104de02284cSSzymon Olewniczak                }
105*53df74e7SSzymon Olewniczak
106*53df74e7SSzymon Olewniczak            }
107de02284cSSzymon Olewniczak		}
108de02284cSSzymon Olewniczak
109de02284cSSzymon Olewniczak		$where = '';
110de02284cSSzymon Olewniczak		if (count($where_q) > 0) {
111de02284cSSzymon Olewniczak			$where = ' WHERE '.implode(' AND ', $where_q);
112de02284cSSzymon Olewniczak		}
113de02284cSSzymon Olewniczak		return array($where, $execute);
114de02284cSSzymon Olewniczak	}
115de02284cSSzymon Olewniczak
116de02284cSSzymon Olewniczak	public function __construct(Model $model) {
117de02284cSSzymon Olewniczak		$this->model = $model;
118de02284cSSzymon Olewniczak	}
119de02284cSSzymon Olewniczak
120de02284cSSzymon Olewniczak	public function acl_static($field) {
121de02284cSSzymon Olewniczak        return $this->model->acl->check_static_field($this->get_table_name(), $field);
122de02284cSSzymon Olewniczak    }
123de02284cSSzymon Olewniczak
124de02284cSSzymon Olewniczak    //chek acl
125e8827d73SSzymon Olewniczak    public function get_all($filters=array(), $orderby='', $desc=true, $defaults=array(), $limit=false) {
126de02284cSSzymon Olewniczak
127de02284cSSzymon Olewniczak        list($where_q, $execute) = $this->build_where($filters);
128de02284cSSzymon Olewniczak
129de02284cSSzymon Olewniczak		$q = $this->select_query() . $where_q;
130de02284cSSzymon Olewniczak
131fe5d6d1eSSzymon Olewniczak		if ($orderby != '') {
132fe5d6d1eSSzymon Olewniczak		    $fields = call_user_func(array($this->get_object_class_name(), 'get_columns'));
133fe5d6d1eSSzymon Olewniczak		    if (!in_array($orderby, $fields)) {
134fe5d6d1eSSzymon Olewniczak		        throw new \Exception('unknown field '.$orderby);
135fe5d6d1eSSzymon Olewniczak            }
136fe5d6d1eSSzymon Olewniczak		    $q .= " ORDER BY $orderby";
137fe5d6d1eSSzymon Olewniczak		    if ($desc) {
138fe5d6d1eSSzymon Olewniczak		        $q .= " DESC";
139fe5d6d1eSSzymon Olewniczak            }
140fe5d6d1eSSzymon Olewniczak        }
141fe5d6d1eSSzymon Olewniczak
142e8827d73SSzymon Olewniczak        if (is_int($limit)) {
143e8827d73SSzymon Olewniczak		    $q .= " LIMIT $limit";
144e8827d73SSzymon Olewniczak        }
145e8827d73SSzymon Olewniczak
146de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($q);
147de02284cSSzymon Olewniczak
148de02284cSSzymon Olewniczak        $sth->setFetchMode(\PDO::FETCH_CLASS, $this->get_object_class_name(),
1498a638198SSzymon Olewniczak                           array($this->model, $defaults));
150de02284cSSzymon Olewniczak
151de02284cSSzymon Olewniczak		$sth->execute($execute);
152de02284cSSzymon Olewniczak
153de02284cSSzymon Olewniczak		return $sth;
154de02284cSSzymon Olewniczak    }
155de02284cSSzymon Olewniczak
156de02284cSSzymon Olewniczak    public function count($filters=array()) {
157ff14b107SSzymon Olewniczak        $table = $this->get_table_view();
158ff14b107SSzymon Olewniczak        if (!$table) {
159ff14b107SSzymon Olewniczak            $table = $this->get_table_name();
160ff14b107SSzymon Olewniczak        }
161de02284cSSzymon Olewniczak        if ($this->acl_static('id') < BEZ_PERMISSION_VIEW) {
162de02284cSSzymon Olewniczak            throw new PermissionDeniedException();
163de02284cSSzymon Olewniczak        }
164de02284cSSzymon Olewniczak
165de02284cSSzymon Olewniczak        list($where_q, $execute) = $this->build_where($filters);
166de02284cSSzymon Olewniczak
167ff14b107SSzymon Olewniczak        $q = "SELECT COUNT(*) FROM $table " . $where_q;
168de02284cSSzymon Olewniczak        $sth = $this->model->db->prepare($q);
169de02284cSSzymon Olewniczak        $sth->execute($execute);
170de02284cSSzymon Olewniczak
171de02284cSSzymon Olewniczak        $count = $sth->fetchColumn();
172de02284cSSzymon Olewniczak        return $count;
173de02284cSSzymon Olewniczak    }
174de02284cSSzymon Olewniczak
1758a638198SSzymon Olewniczak    public function get_one($id, $defaults=array()) {
176ff14b107SSzymon Olewniczak        $table = $this->get_table_view();
177ff14b107SSzymon Olewniczak        if (!$table) {
178ff14b107SSzymon Olewniczak            $table = $this->get_table_name();
179ff14b107SSzymon Olewniczak        }
180de02284cSSzymon Olewniczak
181ff14b107SSzymon Olewniczak		$q = $this->select_query()." WHERE $table.id = ?";
182de02284cSSzymon Olewniczak
183de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($q);
184de02284cSSzymon Olewniczak		$sth->execute(array($id));
185de02284cSSzymon Olewniczak
186de02284cSSzymon Olewniczak		$obj = $sth->fetchObject($this->get_object_class_name(),
1878a638198SSzymon Olewniczak					array($this->model, $defaults));
188de02284cSSzymon Olewniczak
189de02284cSSzymon Olewniczak        if ($obj === false) {
190de02284cSSzymon Olewniczak            throw new \Exception('there is no '.$this->get_table_name().' with id: '.$id);
191de02284cSSzymon Olewniczak        }
192de02284cSSzymon Olewniczak
193de02284cSSzymon Olewniczak		return $obj;
194de02284cSSzymon Olewniczak	}
195de02284cSSzymon Olewniczak
196de02284cSSzymon Olewniczak	public function get_table_name() {
197de02284cSSzymon Olewniczak        $class = (new \ReflectionClass($this))->getShortName();
198de02284cSSzymon Olewniczak        return lcfirst(str_replace('Factory', '', $class));
199de02284cSSzymon Olewniczak	}
200de02284cSSzymon Olewniczak
201de02284cSSzymon Olewniczak    public function get_object_class_name() {
202de02284cSSzymon Olewniczak        $class = (new \ReflectionClass($this))->getName();
203de02284cSSzymon Olewniczak        return str_replace('Factory', '', $class);
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
225*53df74e7SSzymon Olewniczak	protected function insert(Entity $obj) {
226*53df74e7SSzymon Olewniczak        if ($obj->id != NULL) {
227*53df74e7SSzymon Olewniczak            throw new \Exception('row already saved');
228*53df74e7SSzymon Olewniczak        }
229*53df74e7SSzymon Olewniczak
230de02284cSSzymon Olewniczak        $set = array();
231de02284cSSzymon Olewniczak        $execute = array();
232de02284cSSzymon Olewniczak        $columns = array();
233de02284cSSzymon Olewniczak        foreach ($obj->get_columns() as $column) {
234de02284cSSzymon Olewniczak            if ($obj->$column === null) continue;
235de02284cSSzymon Olewniczak            $set[] = ":$column";
236de02284cSSzymon Olewniczak            $columns[] = $column;
237de02284cSSzymon Olewniczak            $value = $obj->$column;
238de02284cSSzymon Olewniczak            if ($value === '') {
239de02284cSSzymon Olewniczak                $execute[':'.$column] = null;
240de02284cSSzymon Olewniczak            } else {
241de02284cSSzymon Olewniczak                $execute[':'.$column] = $value;
242de02284cSSzymon Olewniczak            }
243de02284cSSzymon Olewniczak        }
244de02284cSSzymon Olewniczak
245*53df74e7SSzymon Olewniczak        $query = 'INSERT INTO '.$this->get_table_name().'
246de02284cSSzymon Olewniczak							('.implode(',', $columns).')
247de02284cSSzymon Olewniczak							VALUES ('.implode(',', $set).')';
248de02284cSSzymon Olewniczak
249de02284cSSzymon Olewniczak        $sth = $this->model->db->prepare($query);
250*53df74e7SSzymon Olewniczak        $sth->execute($execute);
251de02284cSSzymon Olewniczak
252de02284cSSzymon Olewniczak        $reflectionClass = new \ReflectionClass($obj);
253de02284cSSzymon Olewniczak        $reflectionProperty = $reflectionClass->getProperty('id');
254de02284cSSzymon Olewniczak        $reflectionProperty->setAccessible(true);
255de02284cSSzymon Olewniczak        $reflectionProperty->setValue($obj, $this->model->db->lastInsertId());
256*53df74e7SSzymon Olewniczak
257de02284cSSzymon Olewniczak    }
258*53df74e7SSzymon Olewniczak
259*53df74e7SSzymon Olewniczak    protected function update(Entity $obj) {
260*53df74e7SSzymon Olewniczak        if ($obj->id == NULL) {
261*53df74e7SSzymon Olewniczak            throw new \Exception('row not inserted');
262*53df74e7SSzymon Olewniczak        }
263*53df74e7SSzymon Olewniczak
264*53df74e7SSzymon Olewniczak        $set = array();
265*53df74e7SSzymon Olewniczak        $execute = array(':id' => $obj->id);
266*53df74e7SSzymon Olewniczak        foreach ($obj->get_columns() as $column) {
267*53df74e7SSzymon Olewniczak            if ($column == 'id') continue;
268*53df74e7SSzymon Olewniczak            $set[] = "$column=:$column";
269*53df74e7SSzymon Olewniczak            $value = $obj->$column;
270*53df74e7SSzymon Olewniczak            if ($value === '') {
271*53df74e7SSzymon Olewniczak                $execute[':'.$column] = null;
272*53df74e7SSzymon Olewniczak            } else {
273*53df74e7SSzymon Olewniczak                $execute[':'.$column] = $value;
274*53df74e7SSzymon Olewniczak            }
275*53df74e7SSzymon Olewniczak        }
276*53df74e7SSzymon Olewniczak
277*53df74e7SSzymon Olewniczak        $query = 'UPDATE ' . $this->get_table_name() .
278*53df74e7SSzymon Olewniczak                    ' SET ' . implode(',', $set) .
279*53df74e7SSzymon Olewniczak                    ' WHERE id=:id';
280*53df74e7SSzymon Olewniczak
281*53df74e7SSzymon Olewniczak        $sth = $this->model->db->prepare($query);
282*53df74e7SSzymon Olewniczak        $sth->execute($execute);
283de02284cSSzymon Olewniczak    }
284de02284cSSzymon Olewniczak
2858a638198SSzymon Olewniczak    public function initial_save(Entity $obj, $data) {
286*53df74e7SSzymon Olewniczak	    $obj->set_data($data);
287*53df74e7SSzymon Olewniczak	    $this->insert($obj);
2888a638198SSzymon Olewniczak    }
2898a638198SSzymon Olewniczak
2908a638198SSzymon Olewniczak    public function update_save(Entity $obj, $data) {
291*53df74e7SSzymon Olewniczak	    $obj->set_data($data);
292*53df74e7SSzymon Olewniczak	    $this->update($obj);
293*53df74e7SSzymon Olewniczak    }
294*53df74e7SSzymon Olewniczak
295*53df74e7SSzymon Olewniczak    public function save(Entity $obj) {
2968a638198SSzymon Olewniczak	    if ($obj->id == NULL) {
297*53df74e7SSzymon Olewniczak	        $this->insert($obj);
298*53df74e7SSzymon Olewniczak        } else {
299*53df74e7SSzymon Olewniczak	        $this->update($obj);
3008a638198SSzymon Olewniczak        }
3018a638198SSzymon Olewniczak    }
3028a638198SSzymon Olewniczak
303de02284cSSzymon Olewniczak	protected function delete_from_db($id) {
304de02284cSSzymon Olewniczak		$q = 'DELETE FROM '.$this->get_table_name().' WHERE id = ?';
305de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($q);
306de02284cSSzymon Olewniczak		$sth->execute(array($id));
307de02284cSSzymon Olewniczak	}
308de02284cSSzymon Olewniczak
309de02284cSSzymon Olewniczak	public function delete(Entity $obj) {
3108a638198SSzymon Olewniczak        $this->model->acl->can($obj, 'id', BEZ_PERMISSION_DELETE);
311de02284cSSzymon Olewniczak		$this->delete_from_db($obj->id);
312de02284cSSzymon Olewniczak	}
313de02284cSSzymon Olewniczak}
314