xref: /plugin/bez/mdl/Entity.php (revision 8a6381983135ed7de69b33e64aa0c1b16dbf69b0)
1<?php
2
3//if(!defined('DOKU_INC')) die();
4
5
6//~ abstract class BEZ_mdl_Dummy_Entity {
7
8    //~ protected $model;
9
10    //~ protected $id = NULL;
11
12    //~ public function __get($property) {
13		//~ if ($property === 'id') {
14            //~ return $this->id;
15        //~ }
16	//~ }
17
18    //~ public function get_table_singular() {
19        //~ $class = get_class($this);
20		//~ $exp = explode('_', $class);
21		//~ $singular = array_pop($exp);
22		//~ return lcfirst($singular);
23    //~ }
24
25    //~ public function get_table_name() {
26		//~ $singlar = $this->get_table_singular();
27		//~ return $singular.'s';
28	//~ }
29
30    //~ public function acl_of($field) {
31        //~ return $this->model->acl->check_field($this, $field);
32    //~ }
33
34    //~ public function __construct($model) {
35		//~ $this->model = $model;
36	//~ }
37//~ }
38
39namespace dokuwiki\plugin\bez\mdl;
40/*
41 * All fields are stored in object as strings.
42 * NULLs are converted to empty string.
43 * If any attribute in object === NULL -> it means that it was not initialized
44 * But we always inserts NULLs instead of empty strings.
45 * https://stackoverflow.com/questions/1267999/mysql-better-to-insert-null-or-empty-string
46 **/
47
48use dokuwiki\plugin\bez\meta\PermissionDeniedException;
49use dokuwiki\plugin\bez\meta\ValidationException;
50
51abstract class Entity {// extends BEZ_mdl_Dummy_Entity {
52
53    /** @var  Model */
54    protected $model;
55
56    /** @var Validator */
57    protected $validator;
58
59    //protected $columns_demendencies = array();
60
61	//protected $parse_int = array();
62
63	abstract public static function get_columns();
64
65	public static function get_select_columns() {
66        $class = get_called_class();
67	    return $class::get_columns();
68    }
69
70//    abstract public static function get_virtual_columns();
71
72//    private function is_dummy() {
73//        if (strstr(get_class(), 'Dummy') === false) {
74//            return false;
75//        }
76//        return true;
77//    }
78//
79//    private function not_for_dummies() {
80//        if ($this->is_dummy()) {
81//            throw new Exception('dummy object doesn\'t contains data.');
82//        }
83//    }
84
85	public function get_assoc($filter=NULL) {
86        //$this->not_for_dummies();
87
88		$assoc = array();
89		//$columns = array_merge($this->get_columns(), $this->get_virtual_columns());
90
91        $columns = $this->get_select_columns();
92        if ($filter !== NULL) {
93            $columns = array_intersect($columns, $filter);
94        }
95
96		foreach ($columns as $col) {
97			$assoc[$col] = $this->$col;
98		}
99		return $assoc;
100	}
101
102//    public function get_table_singular() {
103//        $class = get_class($this);
104//		$exp = explode('_', $class);
105//		$singular = array_pop($exp);
106//		return lcfirst($singular);
107//    }
108//
109    public function get_table_name() {
110        $class = (new \ReflectionClass($this))->getShortName();
111		return lcfirst($class);
112	}
113
114//    private function create_DateTime_from_column($column) {
115//        $cols = array_merge($this->get_columns(), $this->get_virtual_columns());
116//        if (!in_array($column, $cols)) {
117//            throw new Exception("$column is not a column");
118//        }
119//        $dt = $this->$column;
120//        if (is_numeric($dt)) {
121//            return new DateTime('@'.$dt);
122//        }
123//        return new DateTime($dt);
124//    }
125//
126//    public function date_format($column) {
127//        $date = $this->create_DateTime_from_column($column);
128//
129//        return $date->format('Y-m-d');
130//    }
131//
132//    public function datetime_format($column, $format='comment') {
133//        $date = $this->create_DateTime_from_column($column);;
134//
135//        if ($format === 'comment') {
136//            return $dt->format('j') . ' ' .
137//                    $this->model->action->getLang('mon'.$dt->format('n').'_a') . ' ' .
138//                    ($dt->format('Y') === date('Y') ? '' : $dt->format('Y') . ' ') .
139//                    $this->model->action->getLang('at_hour') . ' ' .
140//                    $dt->format('G:i');
141//        }
142//    }
143//
144//    public function days_ago($column, $first_date = null) {
145//        if ($first_date === null) {
146//            $first_date = new DateTime();
147//        } elseif (is_string($first_date)) {
148//            $first_date = $this->create_DateTime_from_column($first_date);
149//        }
150//        $interval = $first_date->diff($this->create_DateTime_from_column($column));
151//        $sign = $interval->format('%R');
152//        $days = $interval->format('%a');
153//        if ($sign === '-') {
154//            return $days . ' ' . $this->model->action->getLang('days') . ' ' .
155//                    $this->model->action->getLang('ago');
156//        }
157//        return $days . ' ' . $this->model->action->getLang('days');
158//
159//    }
160//
161//    public function float_localized($column) {
162//        $cols = array_merge($this->get_columns(), $this->get_virtual_columns());
163//        if (!in_array($column, $cols)) {
164//            throw new Exception("$column is not a column");
165//        }
166//        if ($this->$column === '') {
167//            return '';
168//        }
169//
170//        if (!is_numeric($this->$column)) {
171//            throw new Exception('Column ' . $column . ' isn\'t numeric');
172//        }
173//
174//        return sprintf('%.2f', $this->$column);
175//    }
176
177    //set id when object is saved in database
178//    public function set_id($id) {
179////        $this->not_for_dummies();
180//
181//        if ($this->id === NULL) {
182//            $this->id = $id;
183//        } else {
184//            throw new \Exception('id already set for issue #'.$this->id);
185//        }
186//    }
187
188//	public function sqlite_date($time=NULL) {
189//		//SQLITE format: https://www.sqlite.org/lang_datefunc.html
190//		if ($time === NULL) {
191//			return date('Y-m-d H:i:s');
192//		} else {
193//			return date('Y-m-d H:i:s', $time);
194//		}
195//	}
196
197	public function __get($property) {
198//        $this->not_for_dummies();
199
200//		$columns = array_merge($this->get_columns(), $this->get_virtual_columns());
201        if (!property_exists($this, $property) || !in_array($property, $this->get_columns())) {
202            throw new \Exception('there is no column: "'.$property. '"" in table: "' . $this->get_table_name() . '"');
203        }
204
205        //now only normal db columns has ACL, it should be fixed
206        if ($this->acl_of($property) < BEZ_PERMISSION_VIEW) {
207            throw new PermissionDeniedException();
208        }
209
210        return $this->$property;
211
212//		if (property_exists($this, $property) && in_array($property, $this->get_columns())) {
213////			if (in_array($property, $this->parse_int)) {
214////				return (int)$this->$property;
215////			} else {
216//				return $this->$property;
217////			}
218//		}
219	}
220
221    protected function set_property($property, $value) {
222//        $this->not_for_dummies();
223
224        if (!in_array($property, $this->get_columns())) {
225            throw new \Exception('trying to set not existing column');
226        }
227
228        //throws ValidationException
229        $this->validator->validate_field($property, $value);
230
231        //throws PermissionDeniedException
232        $this->model->acl->can($this, $property, BEZ_PERMISSION_CHANGE);
233
234        $this->$property = $value;
235
236//        if (isset($this->columns_demendencies[$property])) {
237//            $method = $this->columns_demendencies[$property];
238//            //convention -> run the method with the same name as $property
239//            if (!method_exists($this, $method)) {
240//                throw new Exception("denepndency method: $property not implemented");
241//            }
242//            $this->$method();
243//        }
244    }
245
246    protected function set_property_array($array) {
247        foreach ($array as $k => $v) {
248            $this->set_property($k, $v);
249        }
250    }
251
252    //by default do nothing
253//    private function update_virtual_columns() {
254//    }
255//
256
257    public function set_data($post) {
258//        $input = array_intersect($this->changable_fields($filter), array_keys($post), array_keys($this->validator->get_rules()));
259
260        $val_data = $this->validator->validate($post);
261		if ($val_data === false) {
262			throw new ValidationException($this->get_table_name(), $this->validator->get_errors());
263		}
264
265		$this->set_property_array($val_data);
266
267//        $this->update_virtual_columns();
268    }
269
270    public function changable_fields($filter=NULL) {
271       $fields = $this->model->acl->check($this);
272
273       if ($filter !== NULL) {
274           $fields = array_filter($fields, function ($k) use ($filter) {
275                return in_array($k, $filter);
276           }, ARRAY_FILTER_USE_KEY);
277       }
278
279       return array_keys(array_filter($fields, function ($var) {
280           return $var >= BEZ_PERMISSION_CHANGE;
281       }));
282    }
283
284    public function acl_of($field) {
285        return $this->model->acl->check_field($this, $field);
286    }
287
288    public function __construct($model) {
289        //by convention all defaults must be strings
290//        foreach ($defaults as $val) {
291//            if (!is_string($val)) {
292//                throw new Exception('all defaults must be strings');
293//            }
294//        }
295//		$this->model = $model;
296//
297//        if (!$this->is_dummy()) {
298//            $this->validator = new BEZ_mdl_Validator($this->model);
299//        }
300		//$this->helper = plugin_load('helper', 'bez');
301
302        $this->model = $model;
303        $this->validator = new Validator($this->model);
304	}
305}
306