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