1<?php 2 3/* 4 * Task coordinator is taken from tasktypes 5 */ 6//require_once 'entity.php'; 7// 8//class BEZ_mdl_Dummy_Task extends BEZ_mdl_Entity { 9// protected $coordinator; 10// 11// function __construct($model, $defaults=array()) { 12// parent::__construct($model); 13// 14// if (isset($defaults['issue'])) { 15// $issue = $this->model->issues->get_one($defaults['issue']); 16// $this->coordinator = $issue->coordinator; 17// } else { 18// $this->coordinator = ''; 19// } 20// } 21// 22// public function __get($property) { 23// if ($property === 'coordinator') { 24// return $this->coordinator; 25// } 26// parent::__get($property); 27// } 28//} 29 30namespace dokuwiki\plugin\bez\mdl; 31 32use dokuwiki\plugin\bez\meta\Mailer; 33use dokuwiki\plugin\bez\meta\PermissionDeniedException; 34use dokuwiki\plugin\bez\meta\ValidationException; 35 36class Task extends Entity { 37 38 protected $id; 39 40 protected $original_poster, $assignee; 41 42 protected $private, $lock; 43 44 protected $state, $type; 45 46 protected $create_date, $last_activity_date, $last_modification_date, $close_date; 47 48 protected $cost, $plan_date, $all_day_event, $start_time, $finish_time; 49 50 protected $content, $content_html; 51 52 protected $thread_id, $thread_comment_id, $task_program_id; 53 54 /** @var \dokuwiki\plugin\bez\mdl\Thread */ 55 protected $thread; 56 57 /** @var Thread_comment */ 58 protected $thread_comment; 59 60 //virtual 61 protected $task_program_name; 62 63 public static function get_columns() { 64 return array('id', 65 'original_poster', 'assignee', 66 'private', 'lock', 67 'state', 'type', 68 'create_date', 'last_activity_date', 'last_modification_date', 'close_date', 69 'cost', 'plan_date', 'all_day_event', 'start_time', 'finish_time', 70 'content', 'content_html', 71 'thread_id', 'thread_comment_id', 'task_program_id'); 72 } 73 74 public function __get($property) { 75 if ($property == 'thread' || $property == 'thread_comment' || $property == 'task_program_name') { 76 return $this->$property; 77 } 78 return parent::__get($property); 79 } 80 81 82// private function state_string() { 83// switch($this->state) { 84// case '0': return 'task_opened'; 85// case '-outdated': return 'task_outdated'; 86// case '1': return 'task_done'; 87// case '2': return 'task_rejected'; 88// } 89// } 90// 91// private function action_string() { 92// switch($this->action) { 93// case '0': return 'correction'; 94// case '1': return 'corrective_action'; 95// case '2': return 'preventive_action'; 96// case '3': return 'programme'; 97// } 98// } 99// 100// public function cost_localized() { 101// if ($this->cost === '') { 102// return ''; 103// } 104// 105// return sprintf('%.2f', (float)$this->cost); 106// } 107// 108// private function update_virtual_columns() { 109// $this->state_string = $this->model->action->getLang($this->state_string()); 110// $this->action_string = $this->model->action->getLang($this->action_string()); 111// $this->tasktype_string = $this->model->tasktypes->get_one($this->tasktype)->type; 112// } 113// 114// public function user_is_executor() { 115// if ($this->executor === $this->model->user_nick || 116// $this->model->acl->get_level() >= BEZ_AUTH_ADMIN) { 117// return true; 118// } 119// } 120 121 //by defaults you can set: cause, tasktype and issue 122 //tasktype is required 123 public function __construct($model, $defaults=array()) { 124 parent::__construct($model, $defaults); 125 126 127 //array(filter, NULL) 128 $this->validator->set_rules(array( 129// 'reporter' => array(array('dw_user'), 'NOT NULL'), 130// 'date' => array(array('unix_timestamp'), 'NOT NULL'), 131// 'close_date' => array(array('unix_timestamp'), 'NULL'), 132// 'cause' => array(array('numeric'), 'NULL'), 133 134// 'executor' => array(array('dw_user'), 'NOT NULL'), 135 136// 'issue' => array(array('numeric'), 'NULL'), 137 138 'assignee' => array(array('dw_user'), 'NOT NULL'), 139 'cost' => array(array('numeric'), 'NULL'), 140 'plan_date' => array(array('iso_date'), 'NOT NULL'), 141 'all_day_event' => array(array('select', array('0', '1')), 'NOT NULL'), 142 'start_time' => array(array('time'), 'NULL'), 143 'finish_time' => array(array('time'), 'NULL'), 144 'content' => array(array('length', 10000), 'NOT NULL'), 145 'task_program_id' => array(array('numeric'), 'NULL') 146 147// 'state' => array(array('select', array('0', '1', '2')), 'NULL'), 148// 'reason' => array(array('length', 10000), 'NULL'), 149 150// 'coordinator' => array(array('dw_user', array('-none')), 'NOT NULL'), 151 )); 152 153 //we've created empty object 154 if ($this->id === NULL) { 155 $this->original_poster = $this->model->user_nick; 156 $this->create_date = date('c'); 157 $this->last_activity_date = $this->create_date; 158 $this->last_modification_date = $this->create_date; 159 160 $this->state = 'opened'; 161 162 if (isset($defaults['thread'])) { 163 $this->thread = $defaults['thread']; 164 $this->thread_id = $this->thread->id; 165 $this->type = 'correction'; 166 167 if (isset($defaults['thread_comment'])) { 168 $this->thread_comment = $defaults['thread_comment']; 169 $this->thread_comment_id = $this->thread_comment->id; 170 $this->type = 'corrective'; 171 } 172 } 173 174// //meta 175// $this->reporter = $this->model->user_nick; 176// $this->date = time(); 177// 178// $this->state = '0'; 179// $this->all_day_event = '1'; 180// 181// //throws ValidationException 182// $this->issue = $this->validator->validate_field('issue', $defaults['issue']); 183// 184// if ($this->issue !== '') { 185// $issue = $this->model->issues->get_one($defaults['issue']); 186// $this->coordinator = $issue->coordinator; 187// } else { 188// $this->coordinator = ''; 189// } 190// 191// //throws ValidationException 192// $this->validator->validate_field('cause', $defaults['cause']); 193// $this->cause = $defaults['cause']; 194// 195// //by default reporter is a executor 196// $this->executor = $this->reporter; 197 198 199 } 200 201 if ($this->thread_id == '') { 202 $this->validator->set_rules(array( 203 'task_program_id' => array(array('numeric'), 'NOT NULL') 204 )); 205 } 206 207// //close_date required 208// if ($this->state !== '0') { 209// $this->validator->set_rules(array( 210// 'close_date' => array(array('unix_timestamp'), 'NOT NULL') 211// )); 212// } 213 214 //explode subscribents 215// if ($this->subscribents !== NULL) { 216// $exp_part = explode(',', $this->subscribents); 217// foreach ($exp_part as $subscribent) { 218// $this->subscribents_array[$subscribent] = $subscribent; 219// } 220// } 221// 222// //we've created empty object 223// if ($this->id === NULL) { 224// //throws ValidationException 225// $this->validator->validate_field('tasktype', $defaults['tasktype']); 226// $this->tasktype = $defaults['tasktype']; 227// } 228 } 229 230 231 public function set_data($post, $filter=NULL) { 232 parent::set_data($post); 233 234 $this->content_html = p_render('xhtml',p_get_instructions($this->content), $ignore); 235 236 //update dates 237 $this->last_modification_date = date('c'); 238 $this->last_activity_date = $this->last_modification_date; 239 240 //specjalne reguły 241// if ($this->issue === '') { 242// $this->cause = ''; 243// } 244 245 //set parsed 246// $this->task_cache = $this->helper->wiki_parse($this->task); 247// $this->reason_cache = $this->helper->wiki_parse($this->reason); 248 249 //update virtuals 250 //$this->update_virtual_columns(); 251 252 return true; 253 } 254 255// public function update_cache() { 256// if ($this->model->acl->get_level() < BEZ_AUTH_ADMIN) { 257// return false; 258// } 259// $this->task_cache = $this->helper->wiki_parse($this->task); 260// $this->reason_cache = $this->helper->wiki_parse($this->reason); 261// } 262// 263// public function set_state($data) { 264// //reason is required while changing state 265// if ($data['state'] === '2') { 266// $this->validator->set_rules(array( 267// 'reason' => array(array('length', 10000), 'NOT NULL') 268// )); 269// } 270// 271// $val_data = $this->validator->validate($data, array('state', 'reason')); 272// if ($val_data === false) { 273// throw new ValidationException('tasks', $this->validator->get_errors()); 274// } 275// 276// //if state is changed 277// if ($this->state != $data['state']) { 278// $this->close_date = time(); 279// } 280// 281// $this->set_property_array($val_data); 282// $this->reason_cache = $this->helper->wiki_parse($this->reason); 283// 284// //update virtuals 285// $this->update_virtual_columns(); 286// 287// return true; 288// } 289// 290// public function get_meta_fields() { 291// return array('reporter', 'date', 'close_date'); 292// } 293// 294// public function set_meta($post) { 295// 296// if (isset($post['date'])) { 297// $unix = strtotime($post['date']); 298// //if $unix === false validator will catch it 299// if ($unix !== false) { 300// $post['date'] = (string)$unix; 301// } 302// } 303// 304// if (isset($post['close_date'])) { 305// $unix = strtotime($post['close_date']); 306// //if $unix === false validator will catch it 307// if ($unix !== false) { 308// $post['close_date'] = (string)$unix; 309// } 310// } 311// 312// parent::set_data($post, $this->get_meta_fields()); 313// } 314// 315// public function is_subscribent($user=NULL) { 316// if ($user === NULL) { 317// $user = $this->model->user_nick; 318// } 319// if (in_array($user, $this->subscribents_array)) { 320// return true; 321// } 322// return false; 323// } 324// 325// public function get_subscribents() { 326// return $this->subscribents_array; 327// } 328// 329// public function get_participants() { 330// $subscribents = array_merge(array($this->reporter, $this->executor), 331// $this->subscribents_array); 332// $full_names = array(); 333// foreach ($subscribents as $par) { 334// $name = $this->model->users->get_user_full_name($par); 335// if ($name == '') { 336// $full_names[$par] = $par; 337// } else { 338// $full_names[$par] = $name; 339// } 340// } 341// ksort($full_names); 342// return $full_names; 343// } 344// 345// public function remove_subscribent($subscribent) { 346// if ($subscribent !== $this->model->user_nick && 347// $this->acl_of('subscribents') < BEZ_PERMISSION_CHANGE) { 348// throw new PermissionDeniedException(); 349// } 350// 351// if ($this->issue != '') { 352// throw new ConsistencyViolationException('cannot modify subscribents from issue related tasks'); 353// } 354// 355// if (!isset($this->subscribents_array[$subscribent])) { 356// throw new ConsistencyViolationException('user '.$subscribent.' wasn\'t subscriber so cannot be removed'); 357// } 358// 359// unset($this->subscribents_array[$subscribent]); 360// $this->subscribents = implode(',', $this->subscribents_array); 361// } 362// 363// public function add_subscribent($subscribent) { 364// if ($subscribent !== $this->model->user_nick && 365// $this->acl_of('subscribents') < BEZ_PERMISSION_CHANGE) { 366// throw new PermissionDeniedException(); 367// } 368// 369// if ($this->issue != '') { 370// throw new ConsistencyViolationException('cannot add subscribents to issue related tasks'); 371// } 372// 373// if ($this->model->users->exists($subscribent) && 374// !in_array($subscribent, $this->subscribents_array)) { 375// $this->subscribents_array[$subscribent] = $subscribent; 376// $this->subscribents = implode(',', $this->subscribents_array); 377// 378// return true; 379// } 380// 381// return false; 382// } 383 384 private function mail_notify($replacements=array(), $users=false) { 385 $plain = io_readFile($this->model->action->localFN('task-notification')); 386 $html = io_readFile($this->model->action->localFN('task-notification', 'html')); 387 388 $task_link = DOKU_URL . 'doku.php?id='.$this->model->action->id('task', 'tid', $this->id); 389 390 $reps = array( 391 'task_id' => $this->id, 392 'task_link' => $task_link, 393 'who' => $this->reporter 394 ); 395 396 //$replacements can override $reps 397 $rep = array_merge($reps, $replacements); 398 399 if (!isset($rep['who_full_name'])) { 400 $rep['who_full_name'] = 401 $this->model->users->get_user_full_name($rep['who']); 402 } 403 404 //auto title 405 if (!isset($rep['subject'])) { 406// if (isset($rep['content'])) { 407// $rep['subject'] = array_shift(explode('.', $rep['content'], 2)); 408// } 409 $rep['subject'] = '#z'.$this->id.' '.$this->tasktype_string; 410 } 411 412 //we must do it manually becouse Mailer uses htmlspecialchars() 413 $html = str_replace('@TASK_TABLE@', $rep['task_table'], $html); 414 415 $mailer = new BEZ_Mailer(); 416 $mailer->setBody($plain, $rep, $rep, $html, false); 417 418 if ($users === FALSE) { 419 $users = $this->get_subscribents(); 420 421 //don't notify current user 422 unset($users[$this->model->user_nick]); 423 } 424 425 $emails = array_map(function($user) { 426 return $this->model->users->get_user_email($user); 427 }, $users); 428 429 $mailer->to($emails); 430 $mailer->subject($rep['subject']); 431 432 $send = $mailer->send(); 433 if ($send === false) { 434 //this may mean empty $emails 435 //throw new Exception("can't send email"); 436 } 437 } 438 439 public function mail_notify_task_box($issue_obj=NULL, $users=false, $replacements=array()) { 440 if ($issue_obj !== NULL && $issue_obj->id !== $this->issue) { 441 throw new Exception('issue object id and task->issue does not match'); 442 } 443 444 $top_row = array( 445 '<strong>'.$this->model->action->getLang('executor').': </strong>' . 446 $this->model->users->get_user_full_name($this->executor), 447 448 '<strong>'.$this->model->action->getLang('reporter').': </strong>' . 449 $this->model->users->get_user_full_name($this->reporter) 450 ); 451 452 if ($this->tasktype_string != '') { 453 $top_row[] = 454 '<strong>'.$this->model->action->getLang('task_type').': </strong>' . 455 $this->tasktype_string; 456 } 457 458 if ($this->cost != '') { 459 $top_row[] = 460 '<strong>'.$this->model->action->getLang('cost').': </strong>' . 461 $this->cost; 462 } 463 464 //BOTTOM ROW 465 $bottom_row = array( 466 '<strong>'.$this->model->action->getLang('plan_date').': </strong>' . 467 $this->plan_date 468 ); 469 470 if ($this->all_day_event == '0') { 471 $bottom_row[] = 472 '<strong>'.$this->model->action->getLang('start_time').': </strong>' . 473 $this->start_time; 474 $bottom_row[] = 475 '<strong>'.$this->model->action->getLang('finish_time').': </strong>' . 476 $this->finish_time; 477 } 478 479 $rep = array( 480 'content' => $this->task, 481 'content_html' => 482 '<h2 style="font-size: 1.2em;">'. 483 '<a href="'.DOKU_URL.'doku.php?id='.$this->model->action->id('task', 'tid', $this->id).'">' . 484 '#z'.$this->id . 485 '</a> ' . 486 lcfirst($this->action_string) . ' ' . 487 '(' . 488 lcfirst($this->state_string) . 489 ')' . 490 '</h2>' . 491 bez_html_irrtable(array( 492 'table' => array( 493 'border-collapse' => 'collapse', 494 'font-size' => '0.8em', 495 'width' => '100%' 496 ), 497 'td' => array( 498 'border-top' => '1px solid #8bbcbc', 499 'border-bottom' => '1px solid #8bbcbc', 500 'padding' => '.3em .5em' 501 ) 502 ), $top_row, $bottom_row) . $this->task_cache, 503 'who' => $this->model->user_nick, 504 'when' => date('c', (int)$this->date), 505 'custom_content' => true 506 ); 507 508 $rep['action_color'] = '#e4f4f4'; 509 $rep['action_border_color'] = '#8bbcbc'; 510 511 //$replacements can override $reps 512 $rep = array_merge($rep, $replacements); 513 514 if ($issue_obj === NULL) { 515 $this->mail_notify($rep, $users); 516 } else { 517 $issue_obj->mail_notify($rep); 518 } 519 } 520 521 public function mail_notify_subscribents( $issue_obj=NULL, 522 $replacements=array()) { 523 $this->mail_notify_task_box($issue_obj, false, $replacements); 524 } 525 526 public function mail_notify_add($issue_obj=NULL, $users=false, $replacements=array()) { 527 $replacements['action'] = $this->model->action->getLang('mail_task_added'); 528 $this->mail_notify_task_box($issue_obj, $users, $replacements); 529 } 530 531 public function mail_notify_remind($users=false) { 532 $replacements = array(); 533 534 $replacements['action'] = $this->model->action->getLang('mail_task_remind'); 535 //we don't want any who 536 $replacements['who_full_name'] = ''; 537 538 //$users = array($this->executor); 539 $this->mail_notify_task_box(null, $users, $replacements); 540 } 541 542 public function mail_notify_invite($client) { 543 $replacements = array(); 544 545 $replacements['action'] = $this->model->action->getLang('mail_task_invite'); 546 547 $users = array($client); 548 $this->mail_notify_task_box(null, $users, $replacements); 549 } 550} 551