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