1<?php 2 3namespace dokuwiki\plugin\bez\mdl; 4/* 5 * All fields are stored in object as strings. 6 * NULLs are converted to empty string. 7 * If any attribute in object === NULL -> it means that it was not initialized 8 * But we always inserts NULLs instead of empty strings. 9 * https://stackoverflow.com/questions/1267999/mysql-better-to-insert-null-or-empty-string 10 **/ 11 12use dokuwiki\plugin\bez\meta\PermissionDeniedException; 13use dokuwiki\plugin\bez\meta\ValidationException; 14use PHPMailer\PHPMailer\Exception; 15use PHPMailer\PHPMailer\PHPMailer; 16 17abstract class Entity { 18 19 /** @var Model */ 20 protected $model; 21 22 /** @var Validator */ 23 protected $validator; 24 25 /** @var Acl */ 26 protected $acl; 27 28 abstract public static function get_columns(); 29 30 public static function get_select_columns() { 31 $class = get_called_class(); 32 return $class::get_columns(); 33 } 34 35 public static function get_acl_columns() { 36 $class = get_called_class(); 37 return $class::get_select_columns(); 38 } 39 40 public function get_assoc($filter=NULL) { 41 $assoc = array(); 42 43 $columns = $this->get_select_columns(); 44 if ($filter !== NULL) { 45 $columns = array_intersect($columns, $filter); 46 } 47 48 foreach ($columns as $col) { 49 $assoc[$col] = $this->$col; 50 } 51 return $assoc; 52 } 53 54 public function get_table_name() { 55 $class = (new \ReflectionClass($this))->getShortName(); 56 return lcfirst($class); 57 } 58 59 public function __get($property) { 60 if (!property_exists($this, $property) || !in_array($property, $this->get_columns())) { 61 throw new \Exception('there is no column: "'.$property. '"" in table: "' . $this->get_table_name() . '"'); 62 } 63 64 if ($this->acl_of($property) < BEZ_PERMISSION_VIEW) { 65 throw new PermissionDeniedException(); 66 } 67 68 return $this->$property; 69 70 } 71 72 protected function set_property($property, $value) { 73 if ($this->acl_of($property) < BEZ_PERMISSION_CHANGE) { 74 throw new PermissionDeniedException("cannot change field $property"); 75 } 76 $this->$property = $value; 77 } 78 79 protected function set_property_array($array) { 80 foreach ($array as $k => $v) { 81 $this->set_property($k, $v); 82 } 83 } 84 85 public function set_data($post) { 86 $val_data = $this->validator->validate($post); 87 if ($val_data === false) { 88 throw new ValidationException($this->get_table_name(), $this->validator->get_errors()); 89 } 90 91 $this->set_property_array($val_data); 92 } 93 94 95 public function purge() { 96 if (property_exists($this, 'content') && property_exists($this, 'content_html')) { 97 $rule = $this->validator->get_rule('content'); 98 99 $html = p_render('xhtml',p_get_instructions($this->content), $ignore); 100 101 //probably content contains only white spaces 102 if (empty($html) && $rule[1] == 'NOT NULL') { 103 $html = '<p></p>'; 104 } 105 $this->content_html = $html; 106 } 107 108 } 109 110 public function changable_fields($filter=NULL) { 111 $fields = $this->acl->get_list(); 112 113 if ($filter !== NULL) { 114 $fields = array_filter($fields, function ($k) use ($filter) { 115 return in_array($k, $filter); 116 }, ARRAY_FILTER_USE_KEY); 117 } 118 119 return array_keys(array_filter($fields, function ($var) { 120 return $var >= BEZ_PERMISSION_CHANGE; 121 })); 122 } 123 124 public function can_be_null($field) { 125 $rule = $this->validator->get_rule($field); 126 $null = $rule[1]; 127 if (strtolower($null) == 'null') { 128 return true; 129 } 130 131 return false; 132 } 133 134 public function __construct($model) { 135 $this->model = $model; 136 $this->validator = new Validator($this->model); 137 138 $this->acl = new Acl($this->model->get_level(), $this->get_acl_columns()); 139 } 140 141 public function acl_of($field) { 142 return $this->acl->acl_of($field); 143 } 144 145 protected function html_link_url() { 146 return '#'; 147 } 148 149 protected function html_link_content() { 150 echo $this->id; 151 } 152 153 public function html_link($pre='', $post='', $print=true) { 154 $ret = '<a href="'.$this->html_link_url().'">'; 155 $ret .= $pre . $this->html_link_content() . $post; 156 $ret .= '</a>'; 157 158 if ($print) { 159 echo $ret; 160 } 161 return $ret; 162 } 163 164 protected function getMailSubject() { 165 global $conf; 166 return $conf['title']; 167 } 168 169 //http://data.agaric.com/capture-all-sent-mail-locally-postfix 170 //https://askubuntu.com/questions/192572/how-do-i-read-local-email-in-thunderbird 171 public function mail_notify($content, $users=false, $attachedImages=array()) { 172 global $conf; 173 174 $mailer = new PHPMailer(true); 175 $mailer->CharSet = 'utf-8'; 176 $mailer->isHTML(true); 177 178 if (!empty($conf['mailfrom'])) { 179 $mailer->setFrom($conf['mailfrom']); 180 $mailer->addReplyTo($conf['mailfrom']); 181 } 182 183 $mailer->Subject = $this->getMailSubject(); 184 185 foreach ($attachedImages as $img) { 186 $mailer->AddEmbeddedImage($img['path'], $img['cid']); 187 } 188 189 if ($users == FALSE) { 190 $users = $this->get_participants('subscribent'); 191 192 //don't notify myself 193 unset($users[$this->model->user_nick]); 194 } 195 196 $muted_users = $this->model->factory('subscription')->getMutedUsers(); 197 foreach ($users as $user) { 198 if (is_array($user)) { 199 $user = $user['user_id']; 200 } 201 //omit muted users 202 if (in_array($user, $muted_users)) continue; 203 204 $email = $this->model->userFactory->get_user_email($user); 205 $name = $this->model->userFactory->get_user_full_name($user); 206 $mailer->addAddress($email, $name); 207 208 $token = $this->model->factory('subscription')->getUserToken($user); 209 $resign_link = $this->model->action->url('unsubscribe', array('GET' => array( 't' => $token))); 210 $oneClickUnsubscribe = $this->model->action->url('unsubscribe', array('GET' => array( 't' => $token, 'oneclick' => '1'))); 211 $mailer->AddCustomHeader("List-Unsubscribe: <$oneClickUnsubscribe>"); 212 $mailer->Body = str_replace('%%resign_link%%', $resign_link, $content); 213 214 $mailer->send(); 215 $mailer->clearAddresses(); 216 $mailer->clearCustomHeaders(); 217 } 218 } 219 220} 221