xref: /plugin/bez/mdl/Thread.php (revision fe5d6d1ebd253c129098b67fff8cf438a54d8650)
1de02284cSSzymon Olewniczak<?php
2de02284cSSzymon Olewniczak
3de02284cSSzymon Olewniczak//if(!defined('DOKU_INC')) die();
4de02284cSSzymon Olewniczak
5de02284cSSzymon Olewniczak//require_once 'entity.php';
6de02284cSSzymon Olewniczak
7de02284cSSzymon Olewniczaknamespace dokuwiki\plugin\bez\mdl;
8de02284cSSzymon Olewniczak
9de02284cSSzymon Olewniczakuse dokuwiki\plugin\bez\meta\PermissionDeniedException;
10de02284cSSzymon Olewniczakuse dokuwiki\plugin\bez\meta\ValidationException;
11de02284cSSzymon Olewniczak
12de02284cSSzymon Olewniczakclass Thread extends Entity {
13de02284cSSzymon Olewniczak
14de02284cSSzymon Olewniczak    protected $id;
15de02284cSSzymon Olewniczak
16de02284cSSzymon Olewniczak    protected $original_poster, $coordinator;
17de02284cSSzymon Olewniczak
18de02284cSSzymon Olewniczak    protected $private, $lock;
19de02284cSSzymon Olewniczak
20de02284cSSzymon Olewniczak    protected $type, $state;
21de02284cSSzymon Olewniczak
22*fe5d6d1eSSzymon Olewniczak    protected $create_date, $last_activity_date, $last_modification_date, $close_date;
23de02284cSSzymon Olewniczak
24de02284cSSzymon Olewniczak    protected $title, $content, $content_html;
25de02284cSSzymon Olewniczak
26de02284cSSzymon Olewniczak    protected $task_count, $task_count_open, $task_sum_cost;
27de02284cSSzymon Olewniczak
28de02284cSSzymon Olewniczak    public static function get_columns() {
29de02284cSSzymon Olewniczak        return array('id',
30de02284cSSzymon Olewniczak                     'original_poster', 'coordinator',
31de02284cSSzymon Olewniczak                     'private', 'lock',
32de02284cSSzymon Olewniczak                     'type', 'state',
33*fe5d6d1eSSzymon Olewniczak                     'create_date', 'last_activity_date', 'last_modification_date', 'close_date',
34de02284cSSzymon Olewniczak                     'title', 'content', 'content_html',
35de02284cSSzymon Olewniczak                     'task_count', 'task_count_open', 'task_sum_cost');
36de02284cSSzymon Olewniczak    }
37de02284cSSzymon Olewniczak
38de02284cSSzymon Olewniczak    public static function get_states() {
39de02284cSSzymon Olewniczak        return array('proposal', 'opened', 'done', 'closed', 'rejected');
40de02284cSSzymon Olewniczak    }
41de02284cSSzymon Olewniczak
42de02284cSSzymon Olewniczak
43de02284cSSzymon Olewniczak//    private function state_string() {
44de02284cSSzymon Olewniczak//        if ($this->state === '2') {
45de02284cSSzymon Olewniczak//            return 'state_rejected';
46de02284cSSzymon Olewniczak//        } else if ($this->coordinator === '-proposal') {
47de02284cSSzymon Olewniczak//            return 'state_proposal';
48de02284cSSzymon Olewniczak//        } else if ( $this->state === '0' &&
49de02284cSSzymon Olewniczak//                    (int)$this->assigned_tasks_count > 0 &&
50de02284cSSzymon Olewniczak//                    (int)$this->opened_tasks_count === 0) {
51de02284cSSzymon Olewniczak//            return 'state_done';
52de02284cSSzymon Olewniczak//        } else if ($this->state === '0') {
53de02284cSSzymon Olewniczak//            return 'state_opened';
54de02284cSSzymon Olewniczak//        } else if ($this->state === '1') {
55de02284cSSzymon Olewniczak//            return 'state_closed';
56de02284cSSzymon Olewniczak//        }
57de02284cSSzymon Olewniczak//    }
58de02284cSSzymon Olewniczak//
59de02284cSSzymon Olewniczak//    private function type_string() {
60de02284cSSzymon Olewniczak//        if ($this->type === '') {
61de02284cSSzymon Olewniczak//            return '';
62de02284cSSzymon Olewniczak//        }
63de02284cSSzymon Olewniczak//        $issuetype = $this->model->issuetypes->get_one($this->type)->get_assoc();
64de02284cSSzymon Olewniczak//        return $issuetype[$this->model->conf['lang']];
65de02284cSSzymon Olewniczak//    }
66de02284cSSzymon Olewniczak//
67de02284cSSzymon Olewniczak//    private function priority() {
68de02284cSSzymon Olewniczak//        if ($this->state === '2') {
69de02284cSSzymon Olewniczak//            return '3';
70de02284cSSzymon Olewniczak//        }
71de02284cSSzymon Olewniczak//        $min_pr = $this->model->tasks->min_priority(array('issue' => $this->id));
72de02284cSSzymon Olewniczak//        if ($min_pr === NULL) {
73de02284cSSzymon Olewniczak//            return 'None';
74de02284cSSzymon Olewniczak//        }
75de02284cSSzymon Olewniczak//        return $min_pr;
76de02284cSSzymon Olewniczak//    }
77de02284cSSzymon Olewniczak
78de02284cSSzymon Olewniczak    public function user_is_coordinator() {
79de02284cSSzymon Olewniczak        if ($this->coordinator === $this->model->user_nick ||
80de02284cSSzymon Olewniczak           $this->model->acl->get_level() >= BEZ_AUTH_ADMIN) {
81de02284cSSzymon Olewniczak            return true;
82de02284cSSzymon Olewniczak        }
83de02284cSSzymon Olewniczak    }
84de02284cSSzymon Olewniczak
85de02284cSSzymon Olewniczak	public function __construct($model, $defaults=array()) {
86de02284cSSzymon Olewniczak		parent::__construct($model);
87de02284cSSzymon Olewniczak
88de02284cSSzymon Olewniczak        $this->validator->set_rules(array(
89de02284cSSzymon Olewniczak            'coordinator' => array(array('dw_user'), 'NULL'),
90de02284cSSzymon Olewniczak            'title' => array(array('length', 200), 'NOT NULL'),
91de02284cSSzymon Olewniczak            'content' => array(array('length', 10000), 'NOT NULL')
92de02284cSSzymon Olewniczak        ));
93de02284cSSzymon Olewniczak
94de02284cSSzymon Olewniczak//		$this->validator->set_rules(array(
95de02284cSSzymon Olewniczak//			'title' => array(array('length', 200), 'NOT NULL'),
96de02284cSSzymon Olewniczak//			'description' => array(array('length', 10000), 'NOT NULL'),
97de02284cSSzymon Olewniczak//			'state' => array(array('select', array('0', '1', '2')), 'NULL'),
98de02284cSSzymon Olewniczak//			'opinion' => array(array('length', 10000), 'NOT NULL'),
99de02284cSSzymon Olewniczak//			'type' => array(array('numeric'), 'NULL'),
100de02284cSSzymon Olewniczak//			'coordinator' => array(array('dw_user'), 'NOT NULL'),
101de02284cSSzymon Olewniczak//			'reporter' => array(array('dw_user'), 'NOT NULL'),
102de02284cSSzymon Olewniczak//			'date' => array(array('unix_timestamp'), 'NOT NULL'),
103de02284cSSzymon Olewniczak//			'last_mod' => array(array('unix_timestamp'), 'NULL'),
104de02284cSSzymon Olewniczak//			'last_activity' => array(array('sqlite_datetime'), 'NOT NULL')
105de02284cSSzymon Olewniczak//		));
106de02284cSSzymon Olewniczak
107de02284cSSzymon Olewniczak//        $this->validator->set_rules(array(
108de02284cSSzymon Olewniczak            //'coordinator' => array(array('dw_user'), 'NULL'),
109de02284cSSzymon Olewniczak//            'original_poster' => array(array('dw_user'), 'NOT NULL'),
110de02284cSSzymon Olewniczak//			'title' => array(array('length', 200), 'NOT NULL'),
111de02284cSSzymon Olewniczak//			'content' => array(array('length', 10000), 'NOT NULL'),
112de02284cSSzymon Olewniczak//			'state' => array(array('select', array('0', '1', '2')), 'NULL'),
113de02284cSSzymon Olewniczak//			'opinion' => array(array('length', 10000), 'NOT NULL'),
114de02284cSSzymon Olewniczak//			'type' => array(array('select'), 'NULL'),
115de02284cSSzymon Olewniczak
116de02284cSSzymon Olewniczak//			'create_date' => array(array('sqlite_datetime'), 'NOT NULL'),
117de02284cSSzymon Olewniczak//			'last_mod' => array(array('sqlite_datetime'), 'NULL'),
118de02284cSSzymon Olewniczak//			'last_activity' => array(array('sqlite_datetime'), 'NOT NULL')
119de02284cSSzymon Olewniczak//		));
120de02284cSSzymon Olewniczak
121de02284cSSzymon Olewniczak		//we've created empty object (new record)
122de02284cSSzymon Olewniczak		if ($this->id === NULL) {
123de02284cSSzymon Olewniczak			$this->original_poster = $this->model->user_nick;
124de02284cSSzymon Olewniczak			$this->create_date = date('c');
125de02284cSSzymon Olewniczak			$this->last_activity_date = $this->create_date;
126*fe5d6d1eSSzymon Olewniczak            $this->last_modification_date = $this->create_date;
127de02284cSSzymon Olewniczak
128de02284cSSzymon Olewniczak			$this->state = 'proposal';
129de02284cSSzymon Olewniczak
130de02284cSSzymon Olewniczak//			$this->close_date = '';
131de02284cSSzymon Olewniczak
132de02284cSSzymon Olewniczak//			$this->lock = '0';
133de02284cSSzymon Olewniczak//			$this->private = '0';
134de02284cSSzymon Olewniczak//            $this->type = '1';//type 1 - issue
135de02284cSSzymon Olewniczak//            $this->state = '0';//state 0 - proposal
136de02284cSSzymon Olewniczak
137de02284cSSzymon Olewniczak			//$this->update_last_activity();
138de02284cSSzymon Olewniczak
139de02284cSSzymon Olewniczak			//$this->state = '0';
140de02284cSSzymon Olewniczak
141de02284cSSzymon Olewniczak            if ($this->model->acl->get_level() >= BEZ_AUTH_LEADER) {
142de02284cSSzymon Olewniczak//                $this->validator->add_rule('cooridnator', array(array('dw_user'), 'NOT NULL'));
143de02284cSSzymon Olewniczak                //throws ValidationException
144de02284cSSzymon Olewniczak//                $this->coordinator = $this->validator->validate_field('coordinator', $defaults['coordinator']);
145de02284cSSzymon Olewniczak                if (!$this->model->userFactory->exists($defaults['coordinator'])) {
146*fe5d6d1eSSzymon Olewniczak                    throw new ValidationException('thread', array('coordinator' => 'is_null'));
147de02284cSSzymon Olewniczak                }
148de02284cSSzymon Olewniczak                $this->coordinator = $defaults['coordinator'];
149de02284cSSzymon Olewniczak                $this->state = 'opened';
150de02284cSSzymon Olewniczak            }
151de02284cSSzymon Olewniczak//            } else {
152de02284cSSzymon Olewniczak//                $this->coordinator = '-proposal';
153de02284cSSzymon Olewniczak//            }
154de02284cSSzymon Olewniczak
155de02284cSSzymon Olewniczak
156de02284cSSzymon Olewniczak//			$this->add_participant($this->reporter);
157de02284cSSzymon Olewniczak//			$this->add_subscribent($this->reporter);
158de02284cSSzymon Olewniczak//            if ($this->coordinator !== '-proposal') {
159de02284cSSzymon Olewniczak//                $this->add_participant($this->coordinator);
160de02284cSSzymon Olewniczak//                $this->add_subscribent($this->coordinator);
161de02284cSSzymon Olewniczak//            }
162de02284cSSzymon Olewniczak
163de02284cSSzymon Olewniczak		}
164de02284cSSzymon Olewniczak        //close_date required
165de02284cSSzymon Olewniczak//		if ($this->state !== 'state_proposal' && $this->state !== 'state_opened') {
166de02284cSSzymon Olewniczak//			$this->validator->set_rules(array(
167de02284cSSzymon Olewniczak//				'close_date' => array(array('unix_timestamp'), 'NOT NULL')
168de02284cSSzymon Olewniczak//			));
169de02284cSSzymon Olewniczak//		}
170de02284cSSzymon Olewniczak
171de02284cSSzymon Olewniczak
172de02284cSSzymon Olewniczak//		if ($this->participants !== NULL) {
173de02284cSSzymon Olewniczak//			$exp_part = explode(',', $this->participants);
174de02284cSSzymon Olewniczak//			foreach ($exp_part as $participant) {
175de02284cSSzymon Olewniczak//				$this->participants_array[$participant] = $participant;
176de02284cSSzymon Olewniczak//			}
177de02284cSSzymon Olewniczak//		}
178de02284cSSzymon Olewniczak//
179de02284cSSzymon Olewniczak//		if ($this->subscribents !== NULL) {
180de02284cSSzymon Olewniczak//			$exp_part = explode(',', $this->subscribents);
181de02284cSSzymon Olewniczak//			foreach ($exp_part as $subscribent) {
182de02284cSSzymon Olewniczak//				$this->subscribents_array[$subscribent] = $subscribent;
183de02284cSSzymon Olewniczak//			}
184de02284cSSzymon Olewniczak//		}
185de02284cSSzymon Olewniczak	}
186de02284cSSzymon Olewniczak
187de02284cSSzymon Olewniczak	public function set_data($data, $filter=NULL) {
188de02284cSSzymon Olewniczak        $input = array('title', 'content', 'coordinator');
189de02284cSSzymon Olewniczak        $val_data = $this->validator->validate($data, $input);
190de02284cSSzymon Olewniczak
191de02284cSSzymon Olewniczak		if ($val_data === false) {
192de02284cSSzymon Olewniczak			throw new ValidationException('issues',	$this->validator->get_errors());
193de02284cSSzymon Olewniczak        }
194de02284cSSzymon Olewniczak
195de02284cSSzymon Olewniczak
196de02284cSSzymon Olewniczak        //change coordinator at the end(!)
197de02284cSSzymon Olewniczak        if (isset($val_data['coordinator'])) {
198de02284cSSzymon Olewniczak            $val_coordinator = $val_data['coordinator'];
199de02284cSSzymon Olewniczak            unset($val_data['coordinator']);
200de02284cSSzymon Olewniczak        }
201de02284cSSzymon Olewniczak
202de02284cSSzymon Olewniczak        $this->set_property_array($val_data);
203de02284cSSzymon Olewniczak
204de02284cSSzymon Olewniczak        if (isset($val_coordinator)) {
205de02284cSSzymon Olewniczak           $this->set_property('coordinator', $val_coordinator);
206de02284cSSzymon Olewniczak        }
207de02284cSSzymon Olewniczak
208de02284cSSzymon Olewniczak		//!!! don't update activity on issue update
209de02284cSSzymon Olewniczak		$this->content_html = p_render('xhtml',p_get_instructions($this->content), $ignore);
210de02284cSSzymon Olewniczak//		$this->opinion_cache = $this->helper->wiki_parse($this->opinion);
211de02284cSSzymon Olewniczak
212de02284cSSzymon Olewniczak        //update virtuals
213de02284cSSzymon Olewniczak        //$this->update_virtual_columns();
214de02284cSSzymon Olewniczak	}
215de02284cSSzymon Olewniczak
216de02284cSSzymon Olewniczak    public function get_meta_fields() {
217de02284cSSzymon Olewniczak        return array('reporter', 'date', 'last_mod', 'last_activity');
218de02284cSSzymon Olewniczak    }
219de02284cSSzymon Olewniczak
220de02284cSSzymon Olewniczak    public function set_meta($post) {
221de02284cSSzymon Olewniczak
222de02284cSSzymon Olewniczak        if (isset($post['date'])) {
223de02284cSSzymon Olewniczak            $unix = strtotime($post['date']);
224de02284cSSzymon Olewniczak            //if $unix === false validator will catch it
225de02284cSSzymon Olewniczak            if ($unix !== false) {
226de02284cSSzymon Olewniczak                $post['date'] = (string)$unix;
227de02284cSSzymon Olewniczak            }
228de02284cSSzymon Olewniczak        }
229de02284cSSzymon Olewniczak
230de02284cSSzymon Olewniczak        if (isset($post['last_mod'])) {
231de02284cSSzymon Olewniczak            $unix = strtotime($post['last_mod']);
232de02284cSSzymon Olewniczak            //if $unix === false validator will catch it
233de02284cSSzymon Olewniczak            if ($unix !== false) {
234de02284cSSzymon Olewniczak                $post['last_mod'] = (string)$unix;
235de02284cSSzymon Olewniczak            }
236de02284cSSzymon Olewniczak        }
237de02284cSSzymon Olewniczak
238de02284cSSzymon Olewniczak        parent::set_data($post, $this->get_meta_fields());
239de02284cSSzymon Olewniczak    }
240de02284cSSzymon Olewniczak
241de02284cSSzymon Olewniczak//    public function update_cache() {
242de02284cSSzymon Olewniczak//        if ($this->model->acl->get_level() < BEZ_AUTH_ADMIN) {
243de02284cSSzymon Olewniczak//			return false;
244de02284cSSzymon Olewniczak//		}
245de02284cSSzymon Olewniczak//		$this->description_cache = $this->helper->wiki_parse($this->description);
246de02284cSSzymon Olewniczak//		$this->opinion_cache = $this->helper->wiki_parse($this->opinion);
247de02284cSSzymon Olewniczak//	}
248de02284cSSzymon Olewniczak//
249de02284cSSzymon Olewniczak//	public function set_state($data) {
250de02284cSSzymon Olewniczak//
251de02284cSSzymon Olewniczak//        $input = array('state', 'opinion');
252de02284cSSzymon Olewniczak//        $val_data = $this->validator->validate($data, $input);
253de02284cSSzymon Olewniczak//
254de02284cSSzymon Olewniczak//		if ($val_data === false) {
255de02284cSSzymon Olewniczak//			throw new ValidationException('issues',	$this->validator->get_errors());
256de02284cSSzymon Olewniczak//		}
257de02284cSSzymon Olewniczak//
258de02284cSSzymon Olewniczak//        $this->set_property_array($val_data);
259de02284cSSzymon Olewniczak//
260de02284cSSzymon Olewniczak//        if (count($this->validator->get_errors()) > 0)  {
261de02284cSSzymon Olewniczak//			throw new ValidationException('issues',	$this->validator->get_errors());
262de02284cSSzymon Olewniczak//		}
263de02284cSSzymon Olewniczak//
264de02284cSSzymon Olewniczak//		//update activity on state update
265de02284cSSzymon Olewniczak//		$this->last_mod = time();
266de02284cSSzymon Olewniczak//		$this->update_last_activity();
267de02284cSSzymon Olewniczak//		$this->opinion_cache = $this->helper->wiki_parse($this->opinion);
268de02284cSSzymon Olewniczak//
269de02284cSSzymon Olewniczak//        //update virtuals
270de02284cSSzymon Olewniczak//        //$this->update_virtual_columns();
271de02284cSSzymon Olewniczak//	}
272de02284cSSzymon Olewniczak
273de02284cSSzymon Olewniczak//    public function update_last_activity() {
274de02284cSSzymon Olewniczak//        $this->last_activity = $this->sqlite_date();
275de02284cSSzymon Olewniczak//    }
276de02284cSSzymon Olewniczak
277de02284cSSzymon Olewniczak    private $participants;
278de02284cSSzymon Olewniczak    public function get_participants() {
279de02284cSSzymon Olewniczak        if ($this->acl_of('participants') < BEZ_PERMISSION_VIEW) {
280de02284cSSzymon Olewniczak            throw new PermissionDeniedException();
281de02284cSSzymon Olewniczak        }
282de02284cSSzymon Olewniczak        if ($this->id === NULL) {
283de02284cSSzymon Olewniczak            $this->participants = array();
284de02284cSSzymon Olewniczak        }
285de02284cSSzymon Olewniczak        if (is_null($this->participants)) {
286de02284cSSzymon Olewniczak            $r = $this->model->sqlite->query('SELECT * FROM thread_participant WHERE thread_id=? ORDER BY user_id', $this->id);
287de02284cSSzymon Olewniczak            $this->participants = $this->model->sqlite->res2arr($r);
288de02284cSSzymon Olewniczak        }
289de02284cSSzymon Olewniczak        return $this->participants;
290de02284cSSzymon Olewniczak    }
291de02284cSSzymon Olewniczak
292de02284cSSzymon Olewniczak    public function get_participant($user_id) {
293de02284cSSzymon Olewniczak        $participants = $this->get_participants();
294de02284cSSzymon Olewniczak        foreach ($participants as $participant) {
295de02284cSSzymon Olewniczak            if ($participant['user_id'] == $user_id) {
296de02284cSSzymon Olewniczak                return $participant;
297de02284cSSzymon Olewniczak            }
298de02284cSSzymon Olewniczak        }
299de02284cSSzymon Olewniczak        return false;
300de02284cSSzymon Olewniczak    }
301de02284cSSzymon Olewniczak
302de02284cSSzymon Olewniczak	public function set_participant_flags($user_id, $flags=array()) {
303de02284cSSzymon Olewniczak        if ($this->acl_of('participants') < BEZ_PERMISSION_CHANGE) {
304de02284cSSzymon Olewniczak            throw new PermissionDeniedException();
305de02284cSSzymon Olewniczak        }
306de02284cSSzymon Olewniczak
307de02284cSSzymon Olewniczak        $possible_flags = array('original_poster', 'coordinator', 'commentator', 'task_assignee', 'subscribent');
308de02284cSSzymon Olewniczak        if (array_intersect($flags, $possible_flags) != $flags) {
309de02284cSSzymon Olewniczak            throw new \Exception('unknown flags');
310de02284cSSzymon Olewniczak        }
311de02284cSSzymon Olewniczak
312de02284cSSzymon Olewniczak        $participant = $this->get_participant($user_id);
313de02284cSSzymon Olewniczak        if ($participant == false) {
314de02284cSSzymon Olewniczak            $participant = array_fill_keys($possible_flags, 0);
315de02284cSSzymon Olewniczak        }
316de02284cSSzymon Olewniczak        $values = array_merge($participant, array_fill_keys($flags, 1));
317de02284cSSzymon Olewniczak
318de02284cSSzymon Olewniczak        $values['thread_id'] = $this->id;
319de02284cSSzymon Olewniczak        $values['user_id'] = $user_id;
320de02284cSSzymon Olewniczak        $values['added_by'] = $this->model->dw_user;
321de02284cSSzymon Olewniczak        $valuse['added_date'] = date('c');
322de02284cSSzymon Olewniczak
323de02284cSSzymon Olewniczak        $keys = join(',', array_keys($values));
324de02284cSSzymon Olewniczak        $vals = join(',', array_fill(0,count($values),'?'));
325de02284cSSzymon Olewniczak
326de02284cSSzymon Olewniczak        $sql = "REPLACE INTO thread_participant ($keys) VALUES ($vals)";
327de02284cSSzymon Olewniczak        $this->model->sqlite->query($sql, array_values($valuse));
328de02284cSSzymon Olewniczak
329de02284cSSzymon Olewniczak
330de02284cSSzymon Olewniczak
331de02284cSSzymon Olewniczak//		if (! (	$this->user_is_coordinator() ||
332de02284cSSzymon Olewniczak//				$participant === $this->model->user_nick ||
333de02284cSSzymon Olewniczak//                $participant === $this->coordinator) //dodajemy nowego koordynatora
334de02284cSSzymon Olewniczak//			) {
335de02284cSSzymon Olewniczak//			throw new PermissionDeniedException();
336de02284cSSzymon Olewniczak//		}
337de02284cSSzymon Olewniczak//		if ($this->model->users->exists($participant)) {
338de02284cSSzymon Olewniczak//			$this->participants_array[$participant] = $participant;
339de02284cSSzymon Olewniczak//			$this->participants = implode(',', $this->participants_array);
340de02284cSSzymon Olewniczak//		}
341de02284cSSzymon Olewniczak	}
342de02284cSSzymon Olewniczak
343de02284cSSzymon Olewniczak	private $labels;
344de02284cSSzymon Olewniczak    public function get_labels() {
345de02284cSSzymon Olewniczak        if ($this->acl_of('labels') < BEZ_PERMISSION_VIEW) {
346de02284cSSzymon Olewniczak            throw new PermissionDeniedException();
347de02284cSSzymon Olewniczak        }
348de02284cSSzymon Olewniczak        if ($this->id === NULL) {
349de02284cSSzymon Olewniczak            $this->labels = array();
350de02284cSSzymon Olewniczak        }
351de02284cSSzymon Olewniczak        if (is_null($this->labels)) {
352de02284cSSzymon Olewniczak            $r = $this->model->sqlite->query('SELECT * FROM label JOIN thread_label WHERE thread_label.thread_id=?', $this->id);
353de02284cSSzymon Olewniczak            $this->labels = $this->model->sqlite->res2arr($r);
354de02284cSSzymon Olewniczak        }
355de02284cSSzymon Olewniczak        return $this->labels;
356de02284cSSzymon Olewniczak    }
357de02284cSSzymon Olewniczak
358de02284cSSzymon Olewniczak//    public function get_label_id($name) {
359de02284cSSzymon Olewniczak//        $labels = $this->get_labels();
360de02284cSSzymon Olewniczak//
361de02284cSSzymon Olewniczak//        foreach ($labels as $label) {
362de02284cSSzymon Olewniczak//            if ($label['name'] == $name) {
363de02284cSSzymon Olewniczak//                return $label['label_id'];
364de02284cSSzymon Olewniczak//            }
365de02284cSSzymon Olewniczak//        }
366de02284cSSzymon Olewniczak//        return false;
367de02284cSSzymon Olewniczak//    }
368de02284cSSzymon Olewniczak
369de02284cSSzymon Olewniczak    public function add_label($label_id) {
370de02284cSSzymon Olewniczak        if ($this->acl_of('labels') < BEZ_PERMISSION_CHANGE) {
371de02284cSSzymon Olewniczak            throw new PermissionDeniedException();
372de02284cSSzymon Olewniczak        }
373de02284cSSzymon Olewniczak
374de02284cSSzymon Olewniczak        //issue not saved yet
375de02284cSSzymon Olewniczak        if ($this->id === NULL) {
376de02284cSSzymon Olewniczak            throw new \Exception('cannot add labels to not saved thread. use set_labels() instead');
377de02284cSSzymon Olewniczak        }
378de02284cSSzymon Olewniczak
379de02284cSSzymon Olewniczak        //label already assigned, nothing to do
380de02284cSSzymon Olewniczak//        if ($this->get_label_id($name)) return;
381de02284cSSzymon Olewniczak
382de02284cSSzymon Olewniczak//        $r = $this->model->sqlite->query('SELECT id FROM label WHERE id=?', $label_id);
383de02284cSSzymon Olewniczak//        $label_id = $this->model->sqlite->res2single($r);
384de02284cSSzymon Olewniczak//        if (!$label_id) {
385de02284cSSzymon Olewniczak//            throw new \Exception('label does not exist');
386de02284cSSzymon Olewniczak//        }
387de02284cSSzymon Olewniczak
388de02284cSSzymon Olewniczak        $this->model->sqlite->storeEntry('thread_label',
389de02284cSSzymon Olewniczak                                         array('thread_id' => $this->id,
390de02284cSSzymon Olewniczak                                               'label_id' => $label_id));
391de02284cSSzymon Olewniczak
392de02284cSSzymon Olewniczak    }
393de02284cSSzymon Olewniczak
394de02284cSSzymon Olewniczak//    public function remove_label($name) {
395de02284cSSzymon Olewniczak//        if ($this->acl_of('labels') < BEZ_PERMISSION_CHANGE) {
396de02284cSSzymon Olewniczak//            throw new PermissionDeniedException();
397de02284cSSzymon Olewniczak//        }
398de02284cSSzymon Olewniczak//        //label not assigned
399de02284cSSzymon Olewniczak//        $label_id = $this->get_label($name);
400de02284cSSzymon Olewniczak//
401de02284cSSzymon Olewniczak//        if ($label_id === false) {
402de02284cSSzymon Olewniczak//            throw new \Exception('label don not exists');
403de02284cSSzymon Olewniczak//        }
404de02284cSSzymon Olewniczak//
405de02284cSSzymon Olewniczak//        $this->model->sqlite->query('DELETE FROM thread_label WHERE thread_id=?, label_id=?', $this->id, $label_id);
406de02284cSSzymon Olewniczak//    }
407de02284cSSzymon Olewniczak
408de02284cSSzymon Olewniczak//	public function add_subscribent($subscribent) {
409de02284cSSzymon Olewniczak//		if (! (	$this->user_is_coordinator() ||
410de02284cSSzymon Olewniczak//				$subscribent === $this->model->user_nick ||
411de02284cSSzymon Olewniczak//                $subscribent === $this->coordinator) //dodajemy nowego koordynatora)
412de02284cSSzymon Olewniczak//			) {
413de02284cSSzymon Olewniczak//			throw new PermissionDeniedException();
414de02284cSSzymon Olewniczak//		}
415de02284cSSzymon Olewniczak//
416de02284cSSzymon Olewniczak//		if ($this->model->users->exists($subscribent) &&
417de02284cSSzymon Olewniczak//            !in_array($subscribent, $this->subscribents_array)) {
418de02284cSSzymon Olewniczak//			$this->subscribents_array[$subscribent] = $subscribent;
419de02284cSSzymon Olewniczak//			$this->subscribents = implode(',', $this->subscribents_array);
420de02284cSSzymon Olewniczak//            return true;
421de02284cSSzymon Olewniczak//		}
422de02284cSSzymon Olewniczak//        return false;
423de02284cSSzymon Olewniczak//	}
424de02284cSSzymon Olewniczak//
425de02284cSSzymon Olewniczak//	public function remove_subscribent($subscribent) {
426de02284cSSzymon Olewniczak//		if (! (	$this->user_is_coordinator() ||
427de02284cSSzymon Olewniczak//				$subscribent === $this->model->user_nick)
428de02284cSSzymon Olewniczak//			) {
429de02284cSSzymon Olewniczak//			throw new PermissionDeniedException();
430de02284cSSzymon Olewniczak//		}
431de02284cSSzymon Olewniczak//		unset($this->subscribents_array[$subscribent]);
432de02284cSSzymon Olewniczak//		$this->subscribents = implode(',', $this->subscribents_array);
433de02284cSSzymon Olewniczak//	}
434de02284cSSzymon Olewniczak//
435de02284cSSzymon Olewniczak//    public function get_subscribents() {
436de02284cSSzymon Olewniczak//        return $this->subscribents_array;
437de02284cSSzymon Olewniczak//    }
438de02284cSSzymon Olewniczak
439de02284cSSzymon Olewniczak//	public function get_participants() {
440de02284cSSzymon Olewniczak//		$full_names = [];
441de02284cSSzymon Olewniczak//
442de02284cSSzymon Olewniczak//        $involved = array_merge($this->subscribents_array, $this->participants_array);
443de02284cSSzymon Olewniczak//		foreach ($involved as $par) {
444de02284cSSzymon Olewniczak//			$name = $this->model->users->get_user_full_name($par);
445de02284cSSzymon Olewniczak//			if ($name == '') {
446de02284cSSzymon Olewniczak//				$full_names[$par] = $par;
447de02284cSSzymon Olewniczak//			} else {
448de02284cSSzymon Olewniczak//				$full_names[$par] = $name;
449de02284cSSzymon Olewniczak//			}
450de02284cSSzymon Olewniczak//		}
451de02284cSSzymon Olewniczak//		//coordinator on top
452de02284cSSzymon Olewniczak//		uksort($full_names, function ($a, $b) use($full_names) {
453de02284cSSzymon Olewniczak//			if ($a === $this->coordinator) {
454de02284cSSzymon Olewniczak//				return -1;
455de02284cSSzymon Olewniczak//			} else if ($b === $this->coordinator) {
456de02284cSSzymon Olewniczak//				return 1;
457de02284cSSzymon Olewniczak//			}
458de02284cSSzymon Olewniczak//			return $full_names[$a] > $full_names[$b];
459de02284cSSzymon Olewniczak//		});
460de02284cSSzymon Olewniczak//
461de02284cSSzymon Olewniczak//		return $full_names;
462de02284cSSzymon Olewniczak//	}
463de02284cSSzymon Olewniczak
464de02284cSSzymon Olewniczak//	public function is_subscribent($user=NULL) {
465de02284cSSzymon Olewniczak//		if ($user === NULL) {
466de02284cSSzymon Olewniczak//			$user = $this->model->user_nick;
467de02284cSSzymon Olewniczak//		}
468de02284cSSzymon Olewniczak//		if (in_array($user, $this->subscribents_array)) {
469de02284cSSzymon Olewniczak//			return true;
470de02284cSSzymon Olewniczak//		}
471de02284cSSzymon Olewniczak//		return false;
472de02284cSSzymon Olewniczak//	}
473de02284cSSzymon Olewniczak//
474de02284cSSzymon Olewniczak//	public function is_task_executor($user=NULL) {
475de02284cSSzymon Olewniczak//		if ($user === NULL) {
476de02284cSSzymon Olewniczak//			$user = $this->model->user_nick;
477de02284cSSzymon Olewniczak//		}
478de02284cSSzymon Olewniczak//		$sth = $this->model->db->prepare('SELECT COUNT(*) FROM tasks
479de02284cSSzymon Olewniczak//										WHERE issue=:issue AND executor=:executor');
480de02284cSSzymon Olewniczak//		$sth->execute(array(':issue' => $this->id, ':executor' => $user));
481de02284cSSzymon Olewniczak//		$fetch = $sth->fetch();
482de02284cSSzymon Olewniczak//		if ($fetch[0] === '0') {
483de02284cSSzymon Olewniczak//			return false;
484de02284cSSzymon Olewniczak//		} else {
485de02284cSSzymon Olewniczak//			return true;
486de02284cSSzymon Olewniczak//		}
487de02284cSSzymon Olewniczak//	}
488de02284cSSzymon Olewniczak//
489de02284cSSzymon Olewniczak//	public function is_commentator($user=NULL) {
490de02284cSSzymon Olewniczak//		if ($user === NULL) {
491de02284cSSzymon Olewniczak//			$user = $this->model->user_nick;
492de02284cSSzymon Olewniczak//		}
493de02284cSSzymon Olewniczak//		$sth = $this->model->db->prepare('SELECT COUNT(*) FROM commcauses
494de02284cSSzymon Olewniczak//										WHERE issue=:issue AND reporter=:reporter');
495de02284cSSzymon Olewniczak//		$sth->execute(array(':issue' => $this->id, ':reporter' => $user));
496de02284cSSzymon Olewniczak//		$fetch = $sth->fetch();
497de02284cSSzymon Olewniczak//		if ($fetch[0] === '0') {
498de02284cSSzymon Olewniczak//			return false;
499de02284cSSzymon Olewniczak//		} else {
500de02284cSSzymon Olewniczak//			return true;
501de02284cSSzymon Olewniczak//		}
502de02284cSSzymon Olewniczak//	}
503de02284cSSzymon Olewniczak//
504de02284cSSzymon Olewniczak//    private $causes_without_tasks = -1;
505de02284cSSzymon Olewniczak//	public function causes_without_tasks_count() {
506de02284cSSzymon Olewniczak//        if ($this->causes_without_tasks === -1) {
507de02284cSSzymon Olewniczak//            $sth = $this->model->db->prepare('SELECT COUNT(*) FROM
508de02284cSSzymon Olewniczak//                (SELECT tasks.id
509de02284cSSzymon Olewniczak//                    FROM commcauses LEFT JOIN tasks ON commcauses.id = tasks.cause
510de02284cSSzymon Olewniczak//                    WHERE commcauses.type > 0 AND commcauses.issue = ?
511de02284cSSzymon Olewniczak//                    GROUP BY commcauses.id)
512de02284cSSzymon Olewniczak//                WHERE id IS NULL');
513de02284cSSzymon Olewniczak//            $sth->execute(array($this->id));
514de02284cSSzymon Olewniczak//            $count = $sth->fetchColumn();
515de02284cSSzymon Olewniczak//
516de02284cSSzymon Olewniczak//            $this->causes_without_tasks = (int)$count;
517de02284cSSzymon Olewniczak//        }
518de02284cSSzymon Olewniczak//        return $this->causes_without_tasks;
519de02284cSSzymon Olewniczak//	}
520de02284cSSzymon Olewniczak
521de02284cSSzymon Olewniczak    //http://data.agaric.com/capture-all-sent-mail-locally-postfix
522de02284cSSzymon Olewniczak    //https://askubuntu.com/questions/192572/how-do-i-read-local-email-in-thunderbird
523de02284cSSzymon Olewniczak    public function mail_notify($replacements=array(), $users=false) {
524de02284cSSzymon Olewniczak        $plain = io_readFile($this->model->action->localFN('issue-notification'));
525de02284cSSzymon Olewniczak        $html = io_readFile($this->model->action->localFN('issue-notification', 'html'));
526de02284cSSzymon Olewniczak
527de02284cSSzymon Olewniczak        $issue_link =  DOKU_URL . 'doku.php?id='.$this->model->action->id('issue', 'id', $this->id);
528de02284cSSzymon Olewniczak        $issue_unsubscribe = DOKU_URL . 'doku.php?id='.$this->model->action->id('issue', 'id', $this->id, 'action', 'unsubscribe');
529de02284cSSzymon Olewniczak
530de02284cSSzymon Olewniczak        $issue_reps = array(
531de02284cSSzymon Olewniczak                                'issue_id' => $this->id,
532de02284cSSzymon Olewniczak                                'issue_link' => $issue_link,
533de02284cSSzymon Olewniczak                                'issue_unsubscribe' => $issue_unsubscribe,
534de02284cSSzymon Olewniczak                                'custom_content' => false,
535de02284cSSzymon Olewniczak                                'action_border_color' => 'transparent',
536de02284cSSzymon Olewniczak                                'action_color' => 'transparent',
537de02284cSSzymon Olewniczak                           );
538de02284cSSzymon Olewniczak
539de02284cSSzymon Olewniczak        //$replacements can override $issue_reps
540de02284cSSzymon Olewniczak        $rep = array_merge($issue_reps, $replacements);
541de02284cSSzymon Olewniczak        //auto title
542de02284cSSzymon Olewniczak        if (!isset($rep['subject'])) {
543de02284cSSzymon Olewniczak            $rep['subject'] =  '#'.$this->id. ' ' .$this->title;
544de02284cSSzymon Olewniczak        }
545de02284cSSzymon Olewniczak        if (!isset($rep['content_html'])) {
546de02284cSSzymon Olewniczak            $rep['content_html'] = $rep['content'];
547de02284cSSzymon Olewniczak        }
548de02284cSSzymon Olewniczak        if (!isset($rep['who_full_name'])) {
549de02284cSSzymon Olewniczak            $rep['who_full_name'] =
550de02284cSSzymon Olewniczak                $this->model->users->get_user_full_name($rep['who']);
551de02284cSSzymon Olewniczak        }
552de02284cSSzymon Olewniczak
553de02284cSSzymon Olewniczak        //format when
554de02284cSSzymon Olewniczak        $rep['when'] =  $this->date_format($rep['when']);
555de02284cSSzymon Olewniczak
556de02284cSSzymon Olewniczak        if ($rep['custom_content'] === false) {
557de02284cSSzymon Olewniczak            $html = str_replace('@CONTENT_HTML@', '
558de02284cSSzymon Olewniczak                <div style="margin: 5px 0;">
559de02284cSSzymon Olewniczak                    <strong>@WHO_FULL_NAME@</strong> <br>
560de02284cSSzymon Olewniczak                    <span style="color: #888">@WHEN@</span>
561de02284cSSzymon Olewniczak                </div>
562de02284cSSzymon Olewniczak                @CONTENT_HTML@
563de02284cSSzymon Olewniczak            ', $html);
564de02284cSSzymon Olewniczak        }
565de02284cSSzymon Olewniczak
566de02284cSSzymon Olewniczak        //we must do it manually becouse Mailer uses htmlspecialchars()
567de02284cSSzymon Olewniczak        $html = str_replace('@CONTENT_HTML@', $rep['content_html'], $html);
568de02284cSSzymon Olewniczak
569de02284cSSzymon Olewniczak        $mailer = new BEZ_Mailer();
570de02284cSSzymon Olewniczak        $mailer->setBody($plain, $rep, $rep, $html, false);
571de02284cSSzymon Olewniczak
572de02284cSSzymon Olewniczak        if ($users === FALSE) {
573de02284cSSzymon Olewniczak            $users = $this->subscribents_array;
574de02284cSSzymon Olewniczak            unset($users[$this->model->user_nick]);
575de02284cSSzymon Olewniczak        }
576de02284cSSzymon Olewniczak
577de02284cSSzymon Olewniczak        $emails = array_map(function($user) {
578de02284cSSzymon Olewniczak            return $this->model->users->get_user_email($user);
579de02284cSSzymon Olewniczak        }, $users);
580de02284cSSzymon Olewniczak
581de02284cSSzymon Olewniczak
582de02284cSSzymon Olewniczak        $mailer->to($emails);
583de02284cSSzymon Olewniczak        $mailer->subject($rep['subject']);
584de02284cSSzymon Olewniczak
585de02284cSSzymon Olewniczak        $send = $mailer->send();
586de02284cSSzymon Olewniczak        if ($send === false) {
587de02284cSSzymon Olewniczak            //this may mean empty $emails
588de02284cSSzymon Olewniczak            //throw new Exception("can't send email");
589de02284cSSzymon Olewniczak        }
590de02284cSSzymon Olewniczak    }
591de02284cSSzymon Olewniczak
592de02284cSSzymon Olewniczak    protected function mail_issue_box_reps($replacements=array()) {
593de02284cSSzymon Olewniczak        $replacements['custom_content'] = true;
594de02284cSSzymon Olewniczak
595de02284cSSzymon Olewniczak        $html =  '<h2 style="font-size: 1.2em;">';
596de02284cSSzymon Olewniczak	    $html .=    '<a style="font-size:115%" href="@ISSUE_LINK@">#@ISSUE_ID@</a> ';
597de02284cSSzymon Olewniczak
598de02284cSSzymon Olewniczak        if ( ! empty($this->type_string)) {
599de02284cSSzymon Olewniczak            $html .= $this->type_string;
600de02284cSSzymon Olewniczak        } else {
601de02284cSSzymon Olewniczak            $html .= '<i style="color: #777"> '.
602de02284cSSzymon Olewniczak                        $this->model->action->getLang('issue_type_no_specified').
603de02284cSSzymon Olewniczak                    '</i>';
604de02284cSSzymon Olewniczak        }
605de02284cSSzymon Olewniczak
606de02284cSSzymon Olewniczak        $html .= ' ('.$this->state_string.') ';
607de02284cSSzymon Olewniczak
608de02284cSSzymon Olewniczak        $html .= '<span style="color: #777; font-weight: normal; font-size: 90%;">';
609de02284cSSzymon Olewniczak        $html .= $this->model->action->getLang('coordinator') . ': ';
610de02284cSSzymon Olewniczak        $html .= '<span style="font-weight: bold;">';
611de02284cSSzymon Olewniczak
612de02284cSSzymon Olewniczak        if ($this->coordinator === '-proposal') {
613de02284cSSzymon Olewniczak            $html .= '<i style="font-weight: normal;">' .
614de02284cSSzymon Olewniczak                $this->model->action->getLang('proposal') .
615de02284cSSzymon Olewniczak                '</i>';
616de02284cSSzymon Olewniczak        } else {
617de02284cSSzymon Olewniczak            $html .= $this->model->users->get_user_full_name($this->coordinator);
618de02284cSSzymon Olewniczak        }
619de02284cSSzymon Olewniczak        $html .= '</span></span></h2>';
620de02284cSSzymon Olewniczak
621de02284cSSzymon Olewniczak        $html .= '<h2 style="font-size: 1.2em;border-bottom: 1px solid @ACTION_BORDER_COLOR@">' . $this->title . '</h2>';
622de02284cSSzymon Olewniczak
623de02284cSSzymon Olewniczak        $html .= $this->description_cache;
624de02284cSSzymon Olewniczak
625de02284cSSzymon Olewniczak        if ($this->state !== '0') {
626de02284cSSzymon Olewniczak            $html .= '<h3 style="font-size:100%; border-bottom: 1px dotted #bbb">';
627de02284cSSzymon Olewniczak                if ($this->state === '1') {
628de02284cSSzymon Olewniczak                    $html .= $this->model->action->getLang('opinion');
629de02284cSSzymon Olewniczak                } else {
630de02284cSSzymon Olewniczak                    $html .= $this->model->action->getLang('reason');
631de02284cSSzymon Olewniczak                }
632de02284cSSzymon Olewniczak            $html .= '</h3>';
633de02284cSSzymon Olewniczak            $html .= $this->opinion_cache;
634de02284cSSzymon Olewniczak        }
635de02284cSSzymon Olewniczak
636de02284cSSzymon Olewniczak        $replacements['content_html'] = $html;
637de02284cSSzymon Olewniczak
638de02284cSSzymon Olewniczak
639de02284cSSzymon Olewniczak         switch ($this->priority) {
640de02284cSSzymon Olewniczak            case '0':
641de02284cSSzymon Olewniczak                $replacements['action_color'] = '#F8E8E8';
642de02284cSSzymon Olewniczak                $replacements['action_border_color'] = '#F0AFAD';
643de02284cSSzymon Olewniczak                break;
644de02284cSSzymon Olewniczak            case '1':
645de02284cSSzymon Olewniczak                $replacements['action_color'] = '#ffd';
646de02284cSSzymon Olewniczak                $replacements['action_border_color'] = '#dd9';
647de02284cSSzymon Olewniczak                break;
648de02284cSSzymon Olewniczak            case '2':
649de02284cSSzymon Olewniczak                $replacements['action_color'] = '#EEF6F0';
650de02284cSSzymon Olewniczak                $replacements['action_border_color'] = '#B0D2B6';
651de02284cSSzymon Olewniczak                break;
652de02284cSSzymon Olewniczak            case 'None':
653de02284cSSzymon Olewniczak                $replacements['action_color'] = '#e7f1ff';
654de02284cSSzymon Olewniczak                $replacements['action_border_color'] = '#a3c8ff';
655de02284cSSzymon Olewniczak                break;
656de02284cSSzymon Olewniczak            default:
657de02284cSSzymon Olewniczak                $replacements['action_color'] = '#fff';
658de02284cSSzymon Olewniczak                $replacements['action_border_color'] = '#bbb';
659de02284cSSzymon Olewniczak                break;
660de02284cSSzymon Olewniczak        }
661de02284cSSzymon Olewniczak
662de02284cSSzymon Olewniczak        return $replacements;
663de02284cSSzymon Olewniczak    }
664de02284cSSzymon Olewniczak
665de02284cSSzymon Olewniczak    public function mail_notify_change_state() {
666de02284cSSzymon Olewniczak        $this->mail_notify($this->mail_issue_box_reps(array(
667de02284cSSzymon Olewniczak            'who' => $this->model->user_nick,
668de02284cSSzymon Olewniczak            'action' => $this->model->action->getLang('mail_mail_notify_change_state_action'),
669de02284cSSzymon Olewniczak            //'subject' => $this->model->action->getLang('mail_mail_notify_change_state_subject') . ' #'.$this->id
670de02284cSSzymon Olewniczak        )));
671de02284cSSzymon Olewniczak    }
672de02284cSSzymon Olewniczak
673de02284cSSzymon Olewniczak    public function mail_notify_invite($client) {
674de02284cSSzymon Olewniczak        $this->mail_notify($this->mail_issue_box_reps(array(
675de02284cSSzymon Olewniczak            'who' => $this->model->user_nick,
676de02284cSSzymon Olewniczak            'action' => $this->model->action->getLang('mail_mail_notify_invite_action'),
677de02284cSSzymon Olewniczak            //'subject' => $this->model->action->getLang('mail_mail_notify_invite_subject') . ' #'.$this->id
678de02284cSSzymon Olewniczak        )), array($client));
679de02284cSSzymon Olewniczak    }
680de02284cSSzymon Olewniczak
681de02284cSSzymon Olewniczak    public function mail_inform_coordinator() {
682de02284cSSzymon Olewniczak        $this->mail_notify($this->mail_issue_box_reps(array(
683de02284cSSzymon Olewniczak            'who' => $this->model->user_nick,
684de02284cSSzymon Olewniczak            'action' => $this->model->action->getLang('mail_mail_inform_coordinator_action'),
685de02284cSSzymon Olewniczak            //'subject' => $this->model->action->getLang('mail_mail_inform_coordinator_subject') . ' #'.$this->id
686de02284cSSzymon Olewniczak        )), array($this->coordinator));
687de02284cSSzymon Olewniczak    }
688de02284cSSzymon Olewniczak
689de02284cSSzymon Olewniczak    public function mail_notify_issue_inactive($users=false) {
690de02284cSSzymon Olewniczak        $this->mail_notify($this->mail_issue_box_reps(array(
691de02284cSSzymon Olewniczak            'who' => '',
692de02284cSSzymon Olewniczak            'action' => $this->model->action->getLang('mail_mail_notify_issue_inactive'),
693de02284cSSzymon Olewniczak        )), $users);
694de02284cSSzymon Olewniczak    }
695de02284cSSzymon Olewniczak}
696