xref: /plugin/bez/mdl/Factory.php (revision a7028d8f925d727c41ccf12591f4111c9b4e6ae5)
1de02284cSSzymon Olewniczak<?php
2de02284cSSzymon Olewniczak
3de02284cSSzymon Olewniczaknamespace dokuwiki\plugin\bez\mdl;
4de02284cSSzymon Olewniczak
5a0cd8c78SSzymon Olewniczakuse dokuwiki\plugin\bez\meta\PermissionDeniedException;
6a0cd8c78SSzymon Olewniczak
7a0cd8c78SSzymon Olewniczakdefine('BEZ_TABLE_PERMISSION_UNKNOWN', -1);
8a0cd8c78SSzymon Olewniczakdefine('BEZ_TABLE_PERMISSION_SELECT', 0);
9a0cd8c78SSzymon Olewniczakdefine('BEZ_TABLE_PERMISSION_INSERT', 1);
10a0cd8c78SSzymon Olewniczak
11de02284cSSzymon Olewniczakabstract class Factory {
12de02284cSSzymon Olewniczak    /** @var Model */
13de02284cSSzymon Olewniczak	protected $model;
14de02284cSSzymon Olewniczak
15a0cd8c78SSzymon Olewniczak	public function permission() {
16a0cd8c78SSzymon Olewniczak	    return BEZ_TABLE_PERMISSION_INSERT;
17a0cd8c78SSzymon Olewniczak    }
18e8827d73SSzymon Olewniczak
19de02284cSSzymon Olewniczak	protected function filter_field_map($field) {
20ff14b107SSzymon Olewniczak        $table = $this->get_table_view();
21ff14b107SSzymon Olewniczak        if (!$table) {
22ff14b107SSzymon Olewniczak            $table = $this->get_table_name();
23de02284cSSzymon Olewniczak        }
24de02284cSSzymon Olewniczak
25ff14b107SSzymon Olewniczak	    return "$table.$field";
26ff14b107SSzymon Olewniczak    }
27ff14b107SSzymon Olewniczak
28ff14b107SSzymon Olewniczak    protected function select_query() {
29ff14b107SSzymon Olewniczak	    $table = $this->get_table_view();
30ff14b107SSzymon Olewniczak	    if (!$table) {
31ff14b107SSzymon Olewniczak	        $table = $this->get_table_name();
32ff14b107SSzymon Olewniczak        }
33ff14b107SSzymon Olewniczak        return "SELECT * FROM $table";
34ff14b107SSzymon Olewniczak    }
35ff14b107SSzymon Olewniczak
36ff14b107SSzymon Olewniczak    public function get_table_view() {
37ff14b107SSzymon Olewniczak	    return false;
38ff14b107SSzymon Olewniczak    }
39de02284cSSzymon Olewniczak
40de02284cSSzymon Olewniczak    protected function build_where($filters=array()) {
41de02284cSSzymon Olewniczak		$execute = array();
42de02284cSSzymon Olewniczak		$where_q = array();
43de02284cSSzymon Olewniczak		foreach ($filters as $filter => $value) {
44de02284cSSzymon Olewniczak            $field = $this->filter_field_map($filter);
45de02284cSSzymon Olewniczak
46de02284cSSzymon Olewniczak            //parser
47de02284cSSzymon Olewniczak			$operator = '=';
48de02284cSSzymon Olewniczak            $function = '';
49de02284cSSzymon Olewniczak            $function_args = array();
50de02284cSSzymon Olewniczak			if (is_array($value)) {
51de02284cSSzymon Olewniczak                $operators = array('!=', '<', '>', '<=', '>=', 'LIKE', 'BETWEEN', 'OR');
52de02284cSSzymon Olewniczak                $functions = array('', 'date');
53de02284cSSzymon Olewniczak
54de02284cSSzymon Olewniczak                $operator = $value[0];
55de02284cSSzymon Olewniczak                $function = isset($value[2]) ? $value[2] : '';
56de02284cSSzymon Olewniczak
57de02284cSSzymon Olewniczak                if (is_array($function)) {
58de02284cSSzymon Olewniczak                    $function = $function[0];
59de02284cSSzymon Olewniczak                    $function_args = array_slice($value[2], 1);
60de02284cSSzymon Olewniczak                }
61de02284cSSzymon Olewniczak
62de02284cSSzymon Olewniczak                $value = $value[1];
63de02284cSSzymon Olewniczak
64de02284cSSzymon Olewniczak				if (!in_array($operator, $operators)) {
65de02284cSSzymon Olewniczak                    throw new \Exception('unknown operator: '.$operator);
66de02284cSSzymon Olewniczak                }
67de02284cSSzymon Olewniczak
68de02284cSSzymon Olewniczak                if (!in_array($function, $functions)) {
69de02284cSSzymon Olewniczak                    throw new \Exception('unknown function: '.$function);
70de02284cSSzymon Olewniczak                }
71de02284cSSzymon Olewniczak			}
72de02284cSSzymon Olewniczak
73de02284cSSzymon Olewniczak            //builder
74de02284cSSzymon Olewniczak            if ($operator === 'BETWEEN') {
75de02284cSSzymon Olewniczak                if (count($value) < 2) {
76de02284cSSzymon Olewniczak                    throw new \Exception('wrong BETWEEN argument. provide two values');
77de02284cSSzymon Olewniczak                }
78de02284cSSzymon Olewniczak                if ($function !== '') {
79de02284cSSzymon Olewniczak                    array_unshift($function_args, $field);
80de02284cSSzymon Olewniczak                    $where_q[] = "$function(".implode(',', $function_args).") BETWEEN :${filter}_start AND :${filter}_end";
81de02284cSSzymon Olewniczak                } else {
82de02284cSSzymon Olewniczak                    $where_q[] = "$field BETWEEN :${filter}_start AND :${filter}_end";
83de02284cSSzymon Olewniczak                }
84de02284cSSzymon Olewniczak                $execute[":${filter}_start"] = $value[0];
85de02284cSSzymon Olewniczak                $execute[":${filter}_end"] = $value[1];
86de02284cSSzymon Olewniczak            } elseif ($operator === 'OR') {
87de02284cSSzymon Olewniczak                if (!is_array($value)) {
88de02284cSSzymon Olewniczak                    throw new \Exception('$data should be an array');
89de02284cSSzymon Olewniczak                }
90de02284cSSzymon Olewniczak
91de02284cSSzymon Olewniczak                $where_array = array();
92de02284cSSzymon Olewniczak
93de02284cSSzymon Olewniczak                foreach ($value as $k => $v) {
94de02284cSSzymon Olewniczak                    $exec = ":${filter}_$k";
95de02284cSSzymon Olewniczak                    $where_array[] = "$field = $exec";
96de02284cSSzymon Olewniczak                    $execute[$exec] = $v;
97de02284cSSzymon Olewniczak                }
98de02284cSSzymon Olewniczak                $where_q[] = '('.implode(' OR ', $where_array).')';
99de02284cSSzymon Olewniczak
100de02284cSSzymon Olewniczak
101de02284cSSzymon Olewniczak            } else {
102de02284cSSzymon Olewniczak                if ($function !== '') {
103de02284cSSzymon Olewniczak                    array_unshift($function_args, $field);
104de02284cSSzymon Olewniczak                    $where_q[] = "$function(".implode(',', $function_args).") $operator :$filter";
10553df74e7SSzymon Olewniczak                    $execute[":$filter"] = $value;
106*a7028d8fSSzymon Olewniczak                } elseif ($value === NULL || $value === '') {
10753df74e7SSzymon Olewniczak                    $where_q[] = "($field IS NULL OR $field = '')";
108*a7028d8fSSzymon Olewniczak                } elseif(is_int($value)) {
109*a7028d8fSSzymon Olewniczak                    $where_q[] = "$field $operator $value";
110de02284cSSzymon Olewniczak                } else {
111de02284cSSzymon Olewniczak                    $where_q[] = "$field $operator :$filter";
112de02284cSSzymon Olewniczak                    $execute[":$filter"] = $value;
113de02284cSSzymon Olewniczak                }
11453df74e7SSzymon Olewniczak
11553df74e7SSzymon Olewniczak            }
116de02284cSSzymon Olewniczak		}
117de02284cSSzymon Olewniczak
118de02284cSSzymon Olewniczak		$where = '';
119de02284cSSzymon Olewniczak		if (count($where_q) > 0) {
120de02284cSSzymon Olewniczak			$where = ' WHERE '.implode(' AND ', $where_q);
121de02284cSSzymon Olewniczak		}
122de02284cSSzymon Olewniczak		return array($where, $execute);
123de02284cSSzymon Olewniczak	}
124de02284cSSzymon Olewniczak
125de02284cSSzymon Olewniczak	public function __construct(Model $model) {
126de02284cSSzymon Olewniczak		$this->model = $model;
127de02284cSSzymon Olewniczak	}
128de02284cSSzymon Olewniczak
129038c5d4aSSzymon Olewniczak    public function get_all($filters=array(), $orderby='', $defaults=array(), $limit=false) {
130de02284cSSzymon Olewniczak
131de02284cSSzymon Olewniczak        list($where_q, $execute) = $this->build_where($filters);
132de02284cSSzymon Olewniczak
133de02284cSSzymon Olewniczak		$q = $this->select_query() . $where_q;
134de02284cSSzymon Olewniczak
135fe5d6d1eSSzymon Olewniczak		if ($orderby != '') {
136038c5d4aSSzymon Olewniczak		    if (is_array($orderby)) $orderby = implode(', ', $orderby);
137fe5d6d1eSSzymon Olewniczak		    $q .= " ORDER BY $orderby";
138fe5d6d1eSSzymon Olewniczak        }
139fe5d6d1eSSzymon Olewniczak
140e8827d73SSzymon Olewniczak        if (is_int($limit)) {
141e8827d73SSzymon Olewniczak		    $q .= " LIMIT $limit";
142e8827d73SSzymon Olewniczak        }
143e8827d73SSzymon Olewniczak
144de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($q);
145de02284cSSzymon Olewniczak
146de02284cSSzymon Olewniczak        $sth->setFetchMode(\PDO::FETCH_CLASS, $this->get_object_class_name(),
1478a638198SSzymon Olewniczak                           array($this->model, $defaults));
148de02284cSSzymon Olewniczak
149de02284cSSzymon Olewniczak		$sth->execute($execute);
150de02284cSSzymon Olewniczak
151de02284cSSzymon Olewniczak		return $sth;
152de02284cSSzymon Olewniczak    }
153de02284cSSzymon Olewniczak
154de02284cSSzymon Olewniczak    public function count($filters=array()) {
155ff14b107SSzymon Olewniczak        $table = $this->get_table_view();
156ff14b107SSzymon Olewniczak        if (!$table) {
157ff14b107SSzymon Olewniczak            $table = $this->get_table_name();
158ff14b107SSzymon Olewniczak        }
159de02284cSSzymon Olewniczak
160de02284cSSzymon Olewniczak        list($where_q, $execute) = $this->build_where($filters);
161de02284cSSzymon Olewniczak
162ff14b107SSzymon Olewniczak        $q = "SELECT COUNT(*) FROM $table " . $where_q;
163de02284cSSzymon Olewniczak        $sth = $this->model->db->prepare($q);
164de02284cSSzymon Olewniczak        $sth->execute($execute);
165de02284cSSzymon Olewniczak
166de02284cSSzymon Olewniczak        $count = $sth->fetchColumn();
167de02284cSSzymon Olewniczak        return $count;
168de02284cSSzymon Olewniczak    }
169de02284cSSzymon Olewniczak
170b0590826SSzymon Olewniczak    public function exists($id) {
171b0590826SSzymon Olewniczak        $table = $this->get_table_name();
172b0590826SSzymon Olewniczak        $q = "SELECT id FROM $table WHERE id = ?";
173b0590826SSzymon Olewniczak
174b0590826SSzymon Olewniczak        $sth = $this->model->db->prepare($q);
175b0590826SSzymon Olewniczak        $sth->execute(array($id));
176b0590826SSzymon Olewniczak
177b0590826SSzymon Olewniczak        if ($sth->fetch()) {
178b0590826SSzymon Olewniczak            return true;
179b0590826SSzymon Olewniczak        }
180b0590826SSzymon Olewniczak
181b0590826SSzymon Olewniczak        return false;
182b0590826SSzymon Olewniczak    }
183b0590826SSzymon Olewniczak
1848a638198SSzymon Olewniczak    public function get_one($id, $defaults=array()) {
185ff14b107SSzymon Olewniczak        $table = $this->get_table_view();
186ff14b107SSzymon Olewniczak        if (!$table) {
187ff14b107SSzymon Olewniczak            $table = $this->get_table_name();
188ff14b107SSzymon Olewniczak        }
189de02284cSSzymon Olewniczak
190ff14b107SSzymon Olewniczak		$q = $this->select_query()." WHERE $table.id = ?";
191de02284cSSzymon Olewniczak
192de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($q);
193de02284cSSzymon Olewniczak		$sth->execute(array($id));
194de02284cSSzymon Olewniczak
195de02284cSSzymon Olewniczak		$obj = $sth->fetchObject($this->get_object_class_name(),
1968a638198SSzymon Olewniczak					array($this->model, $defaults));
197de02284cSSzymon Olewniczak
198de02284cSSzymon Olewniczak        if ($obj === false) {
199de02284cSSzymon Olewniczak            throw new \Exception('there is no '.$this->get_table_name().' with id: '.$id);
200de02284cSSzymon Olewniczak        }
201de02284cSSzymon Olewniczak
202de02284cSSzymon Olewniczak		return $obj;
203de02284cSSzymon Olewniczak	}
204de02284cSSzymon Olewniczak
205de02284cSSzymon Olewniczak	public function get_table_name() {
206de02284cSSzymon Olewniczak        $class = (new \ReflectionClass($this))->getShortName();
207de02284cSSzymon Olewniczak        return lcfirst(str_replace('Factory', '', $class));
208de02284cSSzymon Olewniczak	}
209de02284cSSzymon Olewniczak
210de02284cSSzymon Olewniczak    public function get_object_class_name() {
211de02284cSSzymon Olewniczak        $class = (new \ReflectionClass($this))->getName();
212de02284cSSzymon Olewniczak        return str_replace('Factory', '', $class);
213de02284cSSzymon Olewniczak    }
214de02284cSSzymon Olewniczak
215de02284cSSzymon Olewniczak    public function create_object($defaults=array()) {
216de02284cSSzymon Olewniczak        $object_name = $this->get_object_class_name();
217de02284cSSzymon Olewniczak
218de02284cSSzymon Olewniczak		$obj = new $object_name($this->model, $defaults);
219de02284cSSzymon Olewniczak		return $obj;
220de02284cSSzymon Olewniczak	}
221de02284cSSzymon Olewniczak
2227fbf4c39SSzymon Olewniczak	protected function beginTransaction() {
223de02284cSSzymon Olewniczak        $this->model->sqlite->query('BEGIN TRANSACTION');
224de02284cSSzymon Olewniczak    }
225de02284cSSzymon Olewniczak
2267fbf4c39SSzymon Olewniczak    protected function commitTransaction() {
227de02284cSSzymon Olewniczak        $this->model->sqlite->query('COMMIT TRANSACTION');
228de02284cSSzymon Olewniczak    }
229de02284cSSzymon Olewniczak
2307fbf4c39SSzymon Olewniczak    protected function rollbackTransaction() {
231de02284cSSzymon Olewniczak        $this->model->sqlite->query('ROLLBACK');
232de02284cSSzymon Olewniczak    }
233de02284cSSzymon Olewniczak
23453df74e7SSzymon Olewniczak	protected function insert(Entity $obj) {
23553df74e7SSzymon Olewniczak        if ($obj->id != NULL) {
23653df74e7SSzymon Olewniczak            throw new \Exception('row already saved');
23753df74e7SSzymon Olewniczak        }
23853df74e7SSzymon Olewniczak
239de02284cSSzymon Olewniczak        $set = array();
240de02284cSSzymon Olewniczak        $execute = array();
241de02284cSSzymon Olewniczak        $columns = array();
242de02284cSSzymon Olewniczak        foreach ($obj->get_columns() as $column) {
243de02284cSSzymon Olewniczak            if ($obj->$column === null) continue;
244de02284cSSzymon Olewniczak            $set[] = ":$column";
245de02284cSSzymon Olewniczak            $columns[] = $column;
246de02284cSSzymon Olewniczak            $value = $obj->$column;
247de02284cSSzymon Olewniczak            if ($value === '') {
248de02284cSSzymon Olewniczak                $execute[':'.$column] = null;
249de02284cSSzymon Olewniczak            } else {
250de02284cSSzymon Olewniczak                $execute[':'.$column] = $value;
251de02284cSSzymon Olewniczak            }
252de02284cSSzymon Olewniczak        }
253de02284cSSzymon Olewniczak
25453df74e7SSzymon Olewniczak        $query = 'INSERT INTO '.$this->get_table_name().'
255de02284cSSzymon Olewniczak							('.implode(',', $columns).')
256de02284cSSzymon Olewniczak							VALUES ('.implode(',', $set).')';
257de02284cSSzymon Olewniczak
258de02284cSSzymon Olewniczak        $sth = $this->model->db->prepare($query);
25953df74e7SSzymon Olewniczak        $sth->execute($execute);
260de02284cSSzymon Olewniczak
261de02284cSSzymon Olewniczak        $reflectionClass = new \ReflectionClass($obj);
262de02284cSSzymon Olewniczak        $reflectionProperty = $reflectionClass->getProperty('id');
263de02284cSSzymon Olewniczak        $reflectionProperty->setAccessible(true);
264de02284cSSzymon Olewniczak        $reflectionProperty->setValue($obj, $this->model->db->lastInsertId());
26553df74e7SSzymon Olewniczak
266de02284cSSzymon Olewniczak    }
26753df74e7SSzymon Olewniczak
26853df74e7SSzymon Olewniczak    protected function update(Entity $obj) {
26953df74e7SSzymon Olewniczak        if ($obj->id == NULL) {
27053df74e7SSzymon Olewniczak            throw new \Exception('row not inserted');
27153df74e7SSzymon Olewniczak        }
27253df74e7SSzymon Olewniczak
27353df74e7SSzymon Olewniczak        $set = array();
27453df74e7SSzymon Olewniczak        $execute = array(':id' => $obj->id);
27553df74e7SSzymon Olewniczak        foreach ($obj->get_columns() as $column) {
27653df74e7SSzymon Olewniczak            if ($column == 'id') continue;
27753df74e7SSzymon Olewniczak            $set[] = "$column=:$column";
27853df74e7SSzymon Olewniczak            $value = $obj->$column;
27953df74e7SSzymon Olewniczak            if ($value === '') {
28053df74e7SSzymon Olewniczak                $execute[':'.$column] = null;
28153df74e7SSzymon Olewniczak            } else {
28253df74e7SSzymon Olewniczak                $execute[':'.$column] = $value;
28353df74e7SSzymon Olewniczak            }
28453df74e7SSzymon Olewniczak        }
28553df74e7SSzymon Olewniczak
28653df74e7SSzymon Olewniczak        $query = 'UPDATE ' . $this->get_table_name() .
28753df74e7SSzymon Olewniczak                    ' SET ' . implode(',', $set) .
28853df74e7SSzymon Olewniczak                    ' WHERE id=:id';
28953df74e7SSzymon Olewniczak
29053df74e7SSzymon Olewniczak        $sth = $this->model->db->prepare($query);
29153df74e7SSzymon Olewniczak        $sth->execute($execute);
292de02284cSSzymon Olewniczak    }
293de02284cSSzymon Olewniczak
2948a638198SSzymon Olewniczak    public function initial_save(Entity $obj, $data) {
29553df74e7SSzymon Olewniczak	    $obj->set_data($data);
29653df74e7SSzymon Olewniczak	    $this->insert($obj);
2978a638198SSzymon Olewniczak    }
2988a638198SSzymon Olewniczak
2998a638198SSzymon Olewniczak    public function update_save(Entity $obj, $data) {
30053df74e7SSzymon Olewniczak	    $obj->set_data($data);
30153df74e7SSzymon Olewniczak	    $this->update($obj);
30253df74e7SSzymon Olewniczak    }
30353df74e7SSzymon Olewniczak
30453df74e7SSzymon Olewniczak    public function save(Entity $obj) {
3058a638198SSzymon Olewniczak	    if ($obj->id == NULL) {
30653df74e7SSzymon Olewniczak	        $this->insert($obj);
30753df74e7SSzymon Olewniczak        } else {
30853df74e7SSzymon Olewniczak	        $this->update($obj);
3098a638198SSzymon Olewniczak        }
3108a638198SSzymon Olewniczak    }
3118a638198SSzymon Olewniczak
312de02284cSSzymon Olewniczak	protected function delete_from_db($id) {
313de02284cSSzymon Olewniczak		$q = 'DELETE FROM '.$this->get_table_name().' WHERE id = ?';
314de02284cSSzymon Olewniczak		$sth = $this->model->db->prepare($q);
315de02284cSSzymon Olewniczak		$sth->execute(array($id));
316de02284cSSzymon Olewniczak	}
317de02284cSSzymon Olewniczak
318de02284cSSzymon Olewniczak	public function delete(Entity $obj) {
319a0cd8c78SSzymon Olewniczak        if ($obj->acl_of('id') < BEZ_PERMISSION_DELETE) {
320a0cd8c78SSzymon Olewniczak            throw new PermissionDeniedException('cannot delete');
321a0cd8c78SSzymon Olewniczak        }
322de02284cSSzymon Olewniczak		$this->delete_from_db($obj->id);
323de02284cSSzymon Olewniczak	}
324de02284cSSzymon Olewniczak}
325