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