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