PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/application/models/project_task_lists/ProjectTaskList.class.php

https://github.com/fb83/Project-Pier
PHP | 793 lines | 360 code | 78 blank | 355 comment | 65 complexity | 8f2894f60bf064f6ac080c8aaaf9d362 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, AGPL-3.0, LGPL-2.1, GPL-3.0
  1. <?php
  2. /**
  3. * ProjectTaskList class
  4. *
  5. * @http://www.projectpier.org/
  6. */
  7. class ProjectTaskList extends BaseProjectTaskList {
  8. /**
  9. * Project task list is taggable
  10. *
  11. * @var boolean
  12. */
  13. protected $is_taggable = true;
  14. /**
  15. * Project task list is commentable
  16. *
  17. * @var boolean
  18. */
  19. protected $is_commentable = true;
  20. /**
  21. * Project task list comments are searchable
  22. *
  23. * @var boolean
  24. */
  25. protected $is_searchable = true;
  26. /**
  27. * Array of searchable columns
  28. *
  29. * @var array
  30. */
  31. protected $searchable_columns = array('name', 'description');
  32. /**
  33. * Cached task array
  34. *
  35. * @var array
  36. */
  37. private $all_tasks;
  38. /**
  39. * Cached open task array
  40. *
  41. * @var array
  42. */
  43. private $open_tasks;
  44. /**
  45. * Cached completed task array
  46. *
  47. * @var array
  48. */
  49. private $completed_tasks;
  50. /**
  51. * Cached number of open tasks
  52. *
  53. * @var integer
  54. */
  55. private $count_all_tasks;
  56. /**
  57. * Cached number of open tasks in this list
  58. *
  59. * @var integer
  60. */
  61. private $count_open_tasks = null;
  62. /**
  63. * Cached number of completed tasks in this list
  64. *
  65. * @var integer
  66. */
  67. private $count_completed_tasks = null;
  68. /**
  69. * Cached array of related forms
  70. *
  71. * @var array
  72. */
  73. private $related_forms;
  74. /**
  75. * Cached completed by reference
  76. *
  77. * @var User
  78. */
  79. private $completed_by;
  80. /**
  81. * Cached milestone
  82. *
  83. * @var Milestone
  84. */
  85. private $milestone;
  86. // ---------------------------------------------------
  87. // Operations
  88. // ---------------------------------------------------
  89. /**
  90. * Add task to this list
  91. *
  92. * @param string $text
  93. * @param User $assigned_to_user
  94. * @param Company $assigned_to_company
  95. * @return ProjectTask
  96. * @throws DAOValidationError
  97. */
  98. function addTask($text, $assigned_to_user = null, $assigned_to_company = null) {
  99. $task = new ProjectTask();
  100. $task->setText($text);
  101. if ($assigned_to_user instanceof User) {
  102. $task->setAssignedToUserId($assigned_to_user->getId());
  103. $task->setAssignedToCompanyId($assigned_to_user->getCompanyId());
  104. } elseif ($assigned_to_company instanceof Company) {
  105. $task->setAssignedToCompanyId($assigned_to_company->getId());
  106. } // if
  107. $this->attachTask($task); // this one will save task
  108. return $task;
  109. } // addTask
  110. /**
  111. * Attach task to this lists
  112. *
  113. * @param ProjectTask $task
  114. * @return null
  115. */
  116. function attachTask(ProjectTask $task) {
  117. if ($task->getTaskListId() == $this->getId()) {
  118. return;
  119. }
  120. $task->setTaskListId($this->getId());
  121. $task->save();
  122. if ($this->isCompleted()) {
  123. $this->open();
  124. }
  125. } // attachTask
  126. /**
  127. * Detach task from this list
  128. *
  129. * @param ProjectTask $task
  130. * @param ProjectTaskList $attach_to If you wish you can detach and attach task to
  131. * other list with one save query
  132. * @return null
  133. */
  134. function detachTask(ProjectTask $task, $attach_to = null) {
  135. if ($task->getTaskListId() <> $this->getId()) {
  136. return;
  137. }
  138. if ($attach_to instanceof ProjectTaskList) {
  139. $attach_to->attachTask($task);
  140. } else {
  141. $task->setTaskListId(0);
  142. $task->save();
  143. } // if
  144. $close = true;
  145. $open_tasks = $this->getOpenTasks();
  146. if (is_array($open_tasks)) {
  147. foreach ($open_tasks as $open_task) {
  148. if ($open_task->getId() <> $task->getId()) {
  149. $close = false;
  150. }
  151. } // if
  152. } // if
  153. if ($close) {
  154. $this->complete(DateTimeValueLib::now(), logged_user());
  155. }
  156. } // detachTask
  157. /**
  158. * Complete this task lists
  159. *
  160. * @access public
  161. * @param DateTimeValue $on Completed on
  162. * @param User $by Completed by
  163. * @return null
  164. */
  165. function complete(DateTimeValue $on, User $by) {
  166. $this->setCompletedOn($on);
  167. $this->setCompletedById($by->getId());
  168. $this->save();
  169. ApplicationLogs::createLog($this, $this->getProject(), ApplicationLogs::ACTION_CLOSE);
  170. } // complete
  171. /**
  172. * Open this list
  173. *
  174. * @access public
  175. * @param void
  176. * @return null
  177. */
  178. function open() {
  179. $this->setCompletedOn(NULL);
  180. $this->setCompletedById(0);
  181. $this->save();
  182. ApplicationLogs::createLog($this, $this->getProject(), ApplicationLogs::ACTION_OPEN);
  183. } // open
  184. // ---------------------------------------------------
  185. // Related object
  186. // ---------------------------------------------------
  187. /**
  188. * Return milestone
  189. *
  190. * @access public
  191. * @param void
  192. * @return array
  193. */
  194. function getMilestone() {
  195. if(is_null($this->milestone)) {
  196. $this->milestone = ProjectMilestones::findById($this->getMilestoneId());
  197. } // if
  198. return $this->milestone;
  199. } // getMilestone
  200. /**
  201. * Return all tasks from this list
  202. *
  203. * @access public
  204. * @param void
  205. * @return array
  206. */
  207. function getTasks() {
  208. if (is_null($this->all_tasks)) {
  209. $this->all_tasks = ProjectTasks::findAll(array(
  210. 'conditions' => '`task_list_id` = ' . DB::escape($this->getId()),
  211. 'order' => '`order`, `created_on`'
  212. )); // findAll
  213. } // if
  214. return $this->all_tasks;
  215. } // getTasks
  216. /**
  217. * Return open tasks
  218. *
  219. * @access public
  220. * @param void
  221. * @return array
  222. */
  223. function getOpenTasks() {
  224. if (is_null($this->open_tasks)) {
  225. $this->open_tasks = ProjectTasks::findAll(array(
  226. 'conditions' => '`task_list_id` = ' . DB::escape($this->getId()) . ' AND `completed_on` = ' . DB::escape(EMPTY_DATETIME),
  227. 'order' => '`order`, `created_on`'
  228. )); // findAll
  229. } // if
  230. return $this->open_tasks;
  231. } // getOpenTasks
  232. /**
  233. * Return completed tasks
  234. *
  235. * @access public
  236. * @param void
  237. * @return array
  238. */
  239. function getCompletedTasks() {
  240. if (is_null($this->completed_tasks)) {
  241. $this->completed_tasks = ProjectTasks::findAll(array(
  242. 'conditions' => '`task_list_id` = ' . DB::escape($this->getId()) . ' AND `completed_on` > ' . DB::escape(EMPTY_DATETIME),
  243. 'order' => '`completed_on` DESC'
  244. )); // findAll
  245. } // if
  246. return $this->completed_tasks;
  247. } // getCompletedTasks
  248. /**
  249. * Return number of all tasks in this list
  250. *
  251. * @access public
  252. * @param void
  253. * @return integer
  254. */
  255. function countAllTasks() {
  256. if (is_null($this->count_all_tasks)) {
  257. if (is_array($this->all_tasks)) {
  258. $this->count_all_tasks = count($this->all_tasks);
  259. } else {
  260. $this->count_all_tasks = ProjectTasks::count('`task_list_id` = ' . DB::escape($this->getId()));
  261. } // if
  262. } // if
  263. return $this->count_all_tasks;
  264. } // countAllTasks
  265. /**
  266. * Return number of open tasks
  267. *
  268. * @access public
  269. * @param void
  270. * @return integer
  271. */
  272. function countOpenTasks() {
  273. if (is_null($this->count_open_tasks)) {
  274. if (is_array($this->open_tasks)) {
  275. $this->count_open_tasks = count($this->open_tasks);
  276. } else {
  277. $this->count_open_tasks = ProjectTasks::count('`task_list_id` = ' . DB::escape($this->getId()) . ' AND `completed_on` = ' . DB::escape(EMPTY_DATETIME));
  278. } // if
  279. } // if
  280. return $this->count_open_tasks;
  281. } // countOpenTasks
  282. /**
  283. * Return number of completed tasks
  284. *
  285. * @access public
  286. * @param void
  287. * @return integer
  288. */
  289. function countCompletedTasks() {
  290. if (is_null($this->count_completed_tasks)) {
  291. if (is_array($this->completed_tasks)) {
  292. $this->count_completed_tasks = count($this->completed_tasks);
  293. } else {
  294. $this->count_completed_tasks = ProjectTasks::count('`task_list_id` = ' . DB::escape($this->getId()) . ' AND `completed_on` > ' . DB::escape(EMPTY_DATETIME));
  295. } // if
  296. } // if
  297. return $this->count_completed_tasks;
  298. } // countCompletedTasks
  299. /**
  300. * Return download text for task list
  301. *
  302. * @access public
  303. * @param void
  304. * @return string
  305. */
  306. function getDownloadText(&$count, $sep, $header = false) {
  307. if ($header) {
  308. $download_text = lang('task download header');
  309. $download_text = strtr($download_text, "\t", $sep);
  310. } else {
  311. $download_text = '';
  312. }
  313. $milestone_name='';
  314. $milestone=$this->getMilestone();
  315. if ($milestone instanceof ProjectMilestone) {
  316. $milestone_name=$milestone->getName();
  317. }
  318. $project_name=$this->getProject()->getName();
  319. $task_list_name=$this->getName();
  320. if ($this->isCompleted()) {
  321. $task_list_status = lang('completed');
  322. } else {
  323. $task_list_status = lang('open');
  324. }
  325. $desc = $this->getDescription();
  326. $desc = strtr($desc,"\r\n\t"," ");
  327. $desc100 = substr($desc,0,100);
  328. $task_list_info = "{$project_name}$sep{$milestone_name}$sep{$task_list_name}$sep{$task_list_status}$sep{$desc100}$sep";
  329. $tasks = $this->getTasks();
  330. if (is_array($tasks)) {
  331. foreach($tasks as $task) {
  332. $count++;
  333. if ($task->isCompleted()) {
  334. $task_status = lang('completed');
  335. $task_completion_info = format_date($task->getCompletedOn());
  336. } else {
  337. $task_status = lang('open');
  338. $task_completion_info = format_date($task->getDueDate());
  339. }
  340. if ($task->getAssignedTo()) {
  341. $task_assignee = $task->getAssignedTo()->getObjectName();
  342. } else {
  343. $task_assignee = lang('not assigned');
  344. }
  345. $task_text = $task->getText();
  346. $task_text = strtr($task_text,"\r\n\t"," ");
  347. $task_text50 = substr($task_text,0,50);
  348. $task_line = "$task_list_info{$task->getId()}$sep{$task_status}$sep{$task_completion_info}$sep{$task_assignee}$sep{$task_text50}";
  349. $download_text .= "$task_line\r\n";
  350. }
  351. }
  352. //die($download_text);
  353. return $download_text;
  354. }
  355. /**
  356. * Return owner project obj
  357. *
  358. * @access public
  359. * @param void
  360. * @return Project
  361. */
  362. function getProject() {
  363. return Projects::findById($this->getProjectId());
  364. } // getProject
  365. /**
  366. * Get project forms that are in relation with this task list
  367. *
  368. * @param void
  369. * @return array
  370. */
  371. function getRelatedForms() {
  372. if(!plugin_active('forms')) { return null; }
  373. if (is_null($this->related_forms)) {
  374. $this->related_forms = ProjectForms::findAll(array(
  375. 'conditions' => '`action` = ' . DB::escape(ProjectForm::ADD_TASK_ACTION) . ' AND `in_object_id` = ' . DB::escape($this->getId()),
  376. 'order' => '`order`'
  377. )); // findAll
  378. } // if
  379. return $this->related_forms;
  380. } // getRelatedForms
  381. /**
  382. * Return user who completed this task
  383. *
  384. * @access public
  385. * @param void
  386. * @return User
  387. */
  388. function getCompletedBy() {
  389. if (!($this->completed_by instanceof User)) {
  390. $this->completed_by = Users::findById($this->getCompletedById());
  391. } // if
  392. return $this->completed_by;
  393. } // getCompletedBy
  394. /**
  395. * Check if this list is completed
  396. *
  397. * @access public
  398. * @param void
  399. * @return boolean
  400. */
  401. function isCompleted() {
  402. return (boolean) $this->getCompletedOn();
  403. } // isCompleted
  404. /**
  405. * Returns true if this list is open
  406. *
  407. * @access public
  408. * @param void
  409. * @return boolean
  410. */
  411. function isOpen() {
  412. return !$this->isCompleted();
  413. } // isOpen
  414. // ---------------------------------------------------
  415. // Permissions
  416. // ---------------------------------------------------
  417. /**
  418. * Check if user have task management permissions for project this list belongs to
  419. *
  420. * @param User $user
  421. * @return boolean
  422. */
  423. function canManage(User $user) {
  424. return $user->getProjectPermission($this->getProject(), PermissionManager::CAN_MANAGE_TASKS);
  425. } // canManage
  426. /**
  427. * Return true if $user can view this task lists
  428. *
  429. * @param User $user
  430. * @return boolean
  431. */
  432. function canView(User $user) {
  433. if ($user->isAdministrator()) {
  434. return true;
  435. } // if
  436. if (!$user->isProjectUser($this->getProject())) {
  437. return false; // user have access to project
  438. } // if
  439. if ($this->isPrivate() && !$user->isMemberOfOwnerCompany()) {
  440. return false; // user that is not member of owner company can't access private objects
  441. } // if
  442. return true;
  443. } // canView
  444. /**
  445. * Check if user can add task lists in specific project
  446. *
  447. * @param User $user
  448. * @param Project $project
  449. * @return boolean
  450. */
  451. function canAdd(User $user, Project $project) {
  452. if ($user->isAccountOwner()) {
  453. return true;
  454. } // if
  455. if ($user->isAdministrator()) {
  456. return true;
  457. } // if
  458. return $user->getProjectPermission($project, PermissionManager::CAN_MANAGE_TASKS);
  459. } // canAdd
  460. /**
  461. * Check if specific user can update this list
  462. *
  463. * @param User $user
  464. * @return boolean
  465. */
  466. function canEdit(User $user) {
  467. if (!$user->isProjectUser($this->getProject())) {
  468. return false; // user is on project
  469. } // if
  470. if ($user->isAdministrator()) {
  471. return true; // user is administrator or root
  472. } // if
  473. if ($this->isPrivate() && !$user->isMemberOfOwnerCompany()) {
  474. return false; // user that is not member of owner company can't edit private objects
  475. } // if
  476. if ($user->getId() == $this->getCreatedById()) {
  477. return true; // user is list author
  478. } // if
  479. return false; // no no
  480. } // canEdit
  481. /**
  482. * Check if specific user can delete this list
  483. *
  484. * @param User $user
  485. * @return boolean
  486. */
  487. function canDelete(User $user) {
  488. if (!$user->isProjectUser($this->getProject())) {
  489. return false; // user is on project
  490. } // if
  491. if ($user->isAdministrator()) {
  492. return true; // user is administrator or root
  493. } // if
  494. return false; // no no
  495. } // canDelete
  496. /**
  497. * Check if specific user can add task to this list
  498. *
  499. * @param User $user
  500. * @return boolean
  501. */
  502. function canAddTask(User $user) {
  503. if (!$user->isProjectUser($this->getProject())) {
  504. return false; // user is on project
  505. } // if
  506. if ($user->isAdministrator()) {
  507. return true; // user is administrator or root
  508. } // if
  509. if ($this->isPrivate() && !$user->isMemberOfOwnerCompany()) {
  510. return false; // user that is not member of owner company can't add task lists
  511. } // if
  512. return $this->canManage($user, $this->getProject());
  513. } // canAddTask
  514. /**
  515. * Check if user can reorder tasks in this list
  516. *
  517. * @param User $user
  518. * @return boolean
  519. */
  520. function canReorderTasks(User $user) {
  521. if (!$user->isProjectUser($this->getProject())) {
  522. return false; // user is on project
  523. } // if
  524. if ($user->isAdministrator()) {
  525. return true; // user is administrator or root
  526. } // if
  527. if ($this->isPrivate() && !$user->isMemberOfOwnerCompany()) {
  528. return false; // user that is not member of owner company can't add task lists
  529. } // if
  530. return $this->canManage($user, $this->getProject());
  531. } // canReorderTasks
  532. // ---------------------------------------------------
  533. // URLs
  534. // ---------------------------------------------------
  535. /**
  536. * Return view list URL
  537. *
  538. * @param void
  539. * @return string
  540. */
  541. function getViewUrl() {
  542. return get_url('task', 'view_list', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
  543. } // getViewUrl
  544. /**
  545. * This function will return URL of this specific list on project tasks page
  546. *
  547. * @param void
  548. * @return string
  549. */
  550. function getOverviewUrl() {
  551. $project = $this->getProject();
  552. if ($project instanceof Project) {
  553. return $project->getTasksUrl() . '#taskList' . $this->getId();
  554. } // if
  555. return '';
  556. } // getOverviewUrl
  557. /**
  558. * Edit this task list
  559. *
  560. * @param void
  561. * @return string
  562. */
  563. function getEditUrl() {
  564. return get_url('task', 'edit_list', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
  565. } // getEditUrl
  566. /**
  567. * Copy this task list
  568. *
  569. * @param void
  570. * @return string
  571. */
  572. function getCopyUrl() {
  573. return get_url('task', 'copy_list', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
  574. } // getEditUrl
  575. /**
  576. * Move this task list
  577. *
  578. * @param void
  579. * @return string
  580. */
  581. function getMoveUrl() {
  582. return get_url('task', 'move_list', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
  583. } // getEditUrl
  584. /**
  585. * Download this task list
  586. *
  587. * @param void
  588. * @return string
  589. */
  590. function getDownloadUrl($output = 'csv') {
  591. return get_url('task', 'download_list', array('id' => $this->getId(), 'active_project' => $this->getProjectId(), 'output' => $output));
  592. } // getDownloadUrl
  593. /**
  594. * Delete this task list
  595. *
  596. * @param void
  597. * @return string
  598. */
  599. function getDeleteUrl() {
  600. return get_url('task', 'delete_list', array('id' => $this->getId(), 'active_project' => $this->getProjectId()));
  601. } // getDeleteUrl
  602. /**
  603. * Return add task url
  604. *
  605. * @param boolean $redirect_to_list Redirect back to the list when task is added. If false
  606. * after submission user will be redirected to projects tasks page
  607. * @return string
  608. */
  609. function getAddTaskUrl($redirect_to_list = true) {
  610. $attributes = array('task_list_id' => $this->getId(), 'active_project' => $this->getProjectId());
  611. if ($redirect_to_list) {
  612. $attributes['back_to_list'] = true;
  613. } // if
  614. return get_url('task', 'add_task', $attributes);
  615. } // getAddTaskUrl
  616. /**
  617. * Return reorder tasks URL
  618. *
  619. * @param boolean $redirect_to_list
  620. * @return string
  621. */
  622. function getReorderTasksUrl($redirect_to_list = true) {
  623. $attributes = array('task_list_id' => $this->getId(), 'active_project' => $this->getProjectId());
  624. if ($redirect_to_list) {
  625. $attributes['back_to_list'] = true;
  626. } // if
  627. return get_url('task', 'reorder_tasks', $attributes);
  628. } // getReorderTasksUrl
  629. // ---------------------------------------------------
  630. // System
  631. // ---------------------------------------------------
  632. /**
  633. * Validate before save
  634. *
  635. * @access public
  636. * @param array $errors
  637. * @return null
  638. */
  639. function validate(&$errors) {
  640. if (!$this->validatePresenceOf('name')) {
  641. $errors[] = lang('task list name required');
  642. } // if
  643. } // validate
  644. /**
  645. * Delete this task lists
  646. *
  647. * @access public
  648. * @param void
  649. * @return boolean
  650. */
  651. function delete() {
  652. $this->deleteTasks();
  653. $related_forms = $this->getRelatedForms();
  654. if (is_array($related_forms)) {
  655. foreach ($related_forms as $related_form) {
  656. $related_form->setInObjectId(0);
  657. $related_form->save();
  658. } // foreach
  659. } // if
  660. return parent::delete();
  661. } // delete
  662. /**
  663. * Save this list
  664. *
  665. * @param void
  666. * @return boolean
  667. */
  668. function save() {
  669. parent::save();
  670. $tasks = $this->getTasks();
  671. if (is_array($tasks)) {
  672. $task_ids = array();
  673. foreach ($tasks as $task) {
  674. $task_ids[] = $task->getId();
  675. } // if
  676. if (count($task_ids)) {
  677. ApplicationLogs::setIsPrivateForType($this->isPrivate(), 'ProjectTasks', $task_ids);
  678. } // if
  679. } // if
  680. return true;
  681. } // save
  682. /**
  683. * Drop all tasks that are in this list
  684. *
  685. * @access public
  686. * @param void
  687. * @return boolean
  688. */
  689. function deleteTasks() {
  690. return ProjectTasks::delete(DB::escapeField('task_list_id') . ' = ' . DB::escape($this->getId()));
  691. } // deleteTasks
  692. // ---------------------------------------------------
  693. // ApplicationDataObject implementation
  694. // ---------------------------------------------------
  695. /**
  696. * Return object type name
  697. *
  698. * @param void
  699. * @return string
  700. */
  701. function getObjectTypeName() {
  702. return lang('task list');
  703. } // getObjectTypeName
  704. /**
  705. * Return object URl
  706. *
  707. * @access public
  708. * @param void
  709. * @return string
  710. */
  711. function getObjectUrl() {
  712. return $this->getViewUrl();
  713. } // getObjectUrl
  714. } // ProjectTaskList
  715. ?>