xref: /plugin/bez/mdl/Factory.php (revision ff14b1073c2dab2f863cab3b8baf8b1a01f7993a)
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) {
13*ff14b107SSzymon Olewniczak        $table = $this->get_table_view();
14*ff14b107SSzymon Olewniczak        if (!$table) {
15*ff14b107SSzymon Olewniczak            $table = $this->get_table_name();
16de02284cSSzymon Olewniczak        }
17de02284cSSzymon Olewniczak
18*ff14b107SSzymon Olewniczak	    return "$table.$field";
19*ff14b107SSzymon Olewniczak    }
20*ff14b107SSzymon Olewniczak
21*ff14b107SSzymon Olewniczak    protected function select_query() {
22*ff14b107SSzymon Olewniczak	    $table = $this->get_table_view();
23*ff14b107SSzymon Olewniczak	    if (!$table) {
24*ff14b107SSzymon Olewniczak	        $table = $this->get_table_name();
25*ff14b107SSzymon Olewniczak        }
26*ff14b107SSzymon Olewniczak        return "SELECT * FROM $table";
27*ff14b107SSzymon Olewniczak    }
28*ff14b107SSzymon Olewniczak
29*ff14b107SSzymon Olewniczak    public function get_table_view() {
30*ff14b107SSzymon Olewniczak	    return false;
31*ff14b107SSzymon 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";
98de02284cSSzymon Olewniczak                } else {
99de02284cSSzymon Olewniczak                    $where_q[] = "$field $operator :$filter";
100de02284cSSzymon Olewniczak                }
101de02284cSSzymon Olewniczak                $execute[":$filter"] = $value;
102de02284cSSzymon Olewniczak            }
103de02284cSSzymon Olewniczak		}
104de02284cSSzymon Olewniczak
105de02284cSSzymon Olewniczak		$where = '';
106de02284cSSzymon Olewniczak		if (count($where_q) > 0) {
107de02284cSSzymon Olewniczak			$where = ' WHERE '.implode(' AND ', $where_q);
108de02284cSSzymon Olewniczak		}
109de02284cSSzymon Olewniczak		return array($where, $execute);
110de02284cSSzymon Olewniczak	}
111de02284cSSzymon Olewniczak
112de02284cSSzymon Olewniczak	public function __construct(Model $model) {
113de02284cSSzymon Olewniczak		$this->model = $model;
114de02284cSSzymon Olewniczak	}
115de02284cSSzymon Olewniczak
116de02284cSSzymon Olewniczak	public function acl_static($field) {
117de02284cSSzymon Olewniczak        return $this->model->acl->check_static_field($this->get_table_name(), $field);
118de02284cSSzymon Olewniczak    }
119de02284cSSzymon Olewniczak
120de02284cSSzymon Olewniczak    //chek acl
121e8827d73SSzymon Olewniczak    public function get_all($filters=array(), $orderby='', $desc=true, $defaults=array(), $limit=false) {
122de02284cSSzymon Olewniczak
123de02284cSSzymon Olewniczak        list($where_q, $execute) = $this->build_where($filters);
124de02284cSSzymon Olewniczak
125de02284cSSzymon Olewniczak		$q = $this->select_query() . $where_q;
126de02284cSSzymon Olewniczak
127fe5d6d1eSSzymon Olewniczak		if ($orderby != '') {
128fe5d6d1eSSzymon Olewniczak		    $fields = call_user_func(array($this->get_object_class_name(), 'get_columns'));
129fe5d6d1eSSzymon Olewniczak		    if (!in_array($orderby, $fields)) {
130fe5d6d1eSSzymon Olewniczak		        throw new \Exception('unknown field '.$orderby);
131fe5d6d1eSSzymon Olewniczak            }
132fe5d6d1eSSzymon Olewniczak		    $q .= " ORDER BY $orderby";
133fe5d6d1eSSzymon Olewniczak		    if ($desc) {
134fe5d6d1eSSzymon Olewniczak		        $q .= " DESC";
135fe5d6d1eSSzymon Olewniczak            }
136fe5d6d1eSSzymon Olewniczak        }
137fe5d6d1eSSzymon Olewniczak
138e8827d73SSzymon Olewniczak        if (is_int($limit)) {
139e8827d73SSzymon Olewniczak		    $q .= " LIMIT $limit";
140e8827d73SSzymon Olewniczak        }
141e8827d73SSzymon Olewniczak
142de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($q);
143de02284cSSzymon Olewniczak
144de02284cSSzymon Olewniczak        $sth->setFetchMode(\PDO::FETCH_CLASS, $this->get_object_class_name(),
1458a638198SSzymon Olewniczak                           array($this->model, $defaults));
146de02284cSSzymon Olewniczak
147de02284cSSzymon Olewniczak		$sth->execute($execute);
148de02284cSSzymon Olewniczak
149de02284cSSzymon Olewniczak		return $sth;
150de02284cSSzymon Olewniczak    }
151de02284cSSzymon Olewniczak
152de02284cSSzymon Olewniczak    public function count($filters=array()) {
153*ff14b107SSzymon Olewniczak        $table = $this->get_table_view();
154*ff14b107SSzymon Olewniczak        if (!$table) {
155*ff14b107SSzymon Olewniczak            $table = $this->get_table_name();
156*ff14b107SSzymon Olewniczak        }
157de02284cSSzymon Olewniczak        if ($this->acl_static('id') < BEZ_PERMISSION_VIEW) {
158de02284cSSzymon Olewniczak            throw new PermissionDeniedException();
159de02284cSSzymon Olewniczak        }
160de02284cSSzymon Olewniczak
161de02284cSSzymon Olewniczak        list($where_q, $execute) = $this->build_where($filters);
162de02284cSSzymon Olewniczak
163*ff14b107SSzymon Olewniczak        $q = "SELECT COUNT(*) FROM $table " . $where_q;
164de02284cSSzymon Olewniczak        $sth = $this->model->db->prepare($q);
165de02284cSSzymon Olewniczak        $sth->execute($execute);
166de02284cSSzymon Olewniczak
167de02284cSSzymon Olewniczak        $count = $sth->fetchColumn();
168de02284cSSzymon Olewniczak        return $count;
169de02284cSSzymon Olewniczak    }
170de02284cSSzymon Olewniczak
1718a638198SSzymon Olewniczak    public function get_one($id, $defaults=array()) {
172*ff14b107SSzymon Olewniczak        $table = $this->get_table_view();
173*ff14b107SSzymon Olewniczak        if (!$table) {
174*ff14b107SSzymon Olewniczak            $table = $this->get_table_name();
175*ff14b107SSzymon Olewniczak        }
176de02284cSSzymon Olewniczak
177*ff14b107SSzymon Olewniczak		$q = $this->select_query()." WHERE $table.id = ?";
178de02284cSSzymon Olewniczak
179de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($q);
180de02284cSSzymon Olewniczak		$sth->execute(array($id));
181de02284cSSzymon Olewniczak
182de02284cSSzymon Olewniczak		$obj = $sth->fetchObject($this->get_object_class_name(),
1838a638198SSzymon Olewniczak					array($this->model, $defaults));
184de02284cSSzymon Olewniczak
185de02284cSSzymon Olewniczak        if ($obj === false) {
186de02284cSSzymon Olewniczak            throw new \Exception('there is no '.$this->get_table_name().' with id: '.$id);
187de02284cSSzymon Olewniczak        }
188de02284cSSzymon Olewniczak
189de02284cSSzymon Olewniczak		return $obj;
190de02284cSSzymon Olewniczak	}
191de02284cSSzymon Olewniczak
192de02284cSSzymon Olewniczak	public function get_table_name() {
193de02284cSSzymon Olewniczak        $class = (new \ReflectionClass($this))->getShortName();
194de02284cSSzymon Olewniczak        return lcfirst(str_replace('Factory', '', $class));
195de02284cSSzymon Olewniczak	}
196de02284cSSzymon Olewniczak
197de02284cSSzymon Olewniczak    public function get_object_class_name() {
198de02284cSSzymon Olewniczak        $class = (new \ReflectionClass($this))->getName();
199de02284cSSzymon Olewniczak        return str_replace('Factory', '', $class);
200de02284cSSzymon Olewniczak    }
201de02284cSSzymon Olewniczak//
202de02284cSSzymon Olewniczak//    public function get_table_singular() {
203de02284cSSzymon Olewniczak//        $table = $this->get_table_name();
204de02284cSSzymon Olewniczak//        $singular = substr($table, 0, -1);
205de02284cSSzymon Olewniczak//        return $singular;
206de02284cSSzymon Olewniczak//    }
207de02284cSSzymon Olewniczak//
208de02284cSSzymon Olewniczak//    private function get_singular_object_name() {
209de02284cSSzymon Olewniczak//        return ucfirst($this->get_table_singular());
210de02284cSSzymon Olewniczak//    }
211de02284cSSzymon Olewniczak//
212de02284cSSzymon Olewniczak//    private function get_object_class_name() {
213de02284cSSzymon Olewniczak//        return 'BEZ_mdl_'.$this->get_singular_object_name();
214de02284cSSzymon Olewniczak//    }
215de02284cSSzymon Olewniczak
216de02284cSSzymon Olewniczak//    private function get_dummy_object_class_name() {
217de02284cSSzymon Olewniczak//        return 'BEZ_mdl_Dummy_'.$this->get_singular_object_name();
218de02284cSSzymon Olewniczak//    }
219de02284cSSzymon Olewniczak
220de02284cSSzymon Olewniczak    public function create_object($defaults=array()) {
221de02284cSSzymon Olewniczak        $object_name = $this->get_object_class_name();
222de02284cSSzymon Olewniczak
223de02284cSSzymon Olewniczak		$obj = new $object_name($this->model, $defaults);
224de02284cSSzymon Olewniczak		return $obj;
225de02284cSSzymon Olewniczak	}
226de02284cSSzymon Olewniczak
2277fbf4c39SSzymon Olewniczak	protected function beginTransaction() {
228de02284cSSzymon Olewniczak        $this->model->sqlite->query('BEGIN TRANSACTION');
229de02284cSSzymon Olewniczak    }
230de02284cSSzymon Olewniczak
2317fbf4c39SSzymon Olewniczak    protected function commitTransaction() {
232de02284cSSzymon Olewniczak        $this->model->sqlite->query('COMMIT TRANSACTION');
233de02284cSSzymon Olewniczak    }
234de02284cSSzymon Olewniczak
2357fbf4c39SSzymon Olewniczak    protected function rollbackTransaction() {
236de02284cSSzymon Olewniczak        $this->model->sqlite->query('ROLLBACK');
237de02284cSSzymon Olewniczak    }
238de02284cSSzymon Olewniczak
239de02284cSSzymon Olewniczak//    public function get_dummy_object() {
240de02284cSSzymon Olewniczak//        if ($this->dummy_object === NULL) {
241de02284cSSzymon Olewniczak//            $dummy_object_name = $this->get_dummy_object_class_name();
242de02284cSSzymon Olewniczak//            $this->dummy_object = new $dummy_object_name($this->model);
243de02284cSSzymon Olewniczak//        }
244de02284cSSzymon Olewniczak//        return $this->dummy_object;
245de02284cSSzymon Olewniczak//	}
246de02284cSSzymon Olewniczak
247de02284cSSzymon Olewniczak	public function save(Entity $obj) {
248de02284cSSzymon Olewniczak        //if user can change id, he can modify record
249de02284cSSzymon Olewniczak        //$this->model->acl->can_change($obj, 'id');
250de02284cSSzymon Olewniczak
251de02284cSSzymon Olewniczak		$set = array();
252de02284cSSzymon Olewniczak		$execute = array();
253de02284cSSzymon Olewniczak		$columns = array();
254de02284cSSzymon Olewniczak		foreach ($obj->get_columns() as $column) {
255de02284cSSzymon Olewniczak            if ($obj->$column === null) continue;
256de02284cSSzymon Olewniczak            //id is special -> when null we insert new row
257de02284cSSzymon Olewniczak//		    if ($column == 'id' && $obj->id == NULL) continue;
258de02284cSSzymon Olewniczak
259de02284cSSzymon Olewniczak//            if ($obj->$column === null) {
260de02284cSSzymon Olewniczak//                throw new \Exception('cannot save object becouse it has uninitialized parameter: '.$column);
261de02284cSSzymon Olewniczak//            }
262de02284cSSzymon Olewniczak			$set[] = ":$column";
263de02284cSSzymon Olewniczak			$columns[] = $column;
264de02284cSSzymon Olewniczak            $value = $obj->$column;
265de02284cSSzymon Olewniczak            if ($value === '') {
266de02284cSSzymon Olewniczak                $execute[':'.$column] = null;
267de02284cSSzymon Olewniczak            } else {
268de02284cSSzymon Olewniczak                $execute[':'.$column] = $value;
269de02284cSSzymon Olewniczak            }
270de02284cSSzymon Olewniczak		}
271de02284cSSzymon Olewniczak
272de02284cSSzymon Olewniczak		$query = 'REPLACE INTO '.$this->get_table_name().'
273de02284cSSzymon Olewniczak							('.implode(',', $columns).')
274de02284cSSzymon Olewniczak							VALUES ('.implode(',', $set).')';
275de02284cSSzymon Olewniczak
276de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($query);
2778a638198SSzymon Olewniczak		$res = $sth->execute($execute);
278de02284cSSzymon Olewniczak
279de02284cSSzymon Olewniczak        //new object is created
280de02284cSSzymon Olewniczak        if ($obj->id === NULL) {
281de02284cSSzymon Olewniczak            $reflectionClass = new \ReflectionClass($obj);
282de02284cSSzymon Olewniczak            $reflectionProperty = $reflectionClass->getProperty('id');
283de02284cSSzymon Olewniczak            $reflectionProperty->setAccessible(true);
284de02284cSSzymon Olewniczak            $reflectionProperty->setValue($obj, $this->model->db->lastInsertId());
285de02284cSSzymon Olewniczak        }
286de02284cSSzymon Olewniczak//            $id = $this->model->db->lastInsertId();
287de02284cSSzymon Olewniczak//            $obj->set_id($id);
288de02284cSSzymon Olewniczak
289de02284cSSzymon Olewniczak//        }
290de02284cSSzymon Olewniczak
291de02284cSSzymon Olewniczak//		return $id;
292de02284cSSzymon Olewniczak	}
293de02284cSSzymon Olewniczak
2948a638198SSzymon Olewniczak	public function initial_save(Entity $obj, $data) {
2958a638198SSzymon Olewniczak        if ($obj->id != NULL) {
2968a638198SSzymon Olewniczak            throw new \Exception('row already saved. use update_save');
2978a638198SSzymon Olewniczak        }
2988a638198SSzymon Olewniczak    }
2998a638198SSzymon Olewniczak
3008a638198SSzymon Olewniczak    public function update_save(Entity $obj, $data) {
3018a638198SSzymon Olewniczak        if ($obj->id == NULL) {
3028a638198SSzymon Olewniczak            throw new \Exception('row not saved. use initial_save()');
3038a638198SSzymon Olewniczak        }
3048a638198SSzymon Olewniczak    }
3058a638198SSzymon Olewniczak
306de02284cSSzymon Olewniczak	protected function delete_from_db($id) {
307de02284cSSzymon Olewniczak		$q = 'DELETE FROM '.$this->get_table_name().' WHERE id = ?';
308de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($q);
309de02284cSSzymon Olewniczak		$sth->execute(array($id));
310de02284cSSzymon Olewniczak	}
311de02284cSSzymon Olewniczak
312de02284cSSzymon Olewniczak	public function delete(Entity $obj) {
3138a638198SSzymon Olewniczak        $this->model->acl->can($obj, 'id', BEZ_PERMISSION_DELETE);
314de02284cSSzymon Olewniczak		$this->delete_from_db($obj->id);
315de02284cSSzymon Olewniczak	}
316de02284cSSzymon Olewniczak}
317