diff --git a/Controller/CalendarController.php b/Controller/CalendarController.php index 9db7cf9..94a1e5e 100644 --- a/Controller/CalendarController.php +++ b/Controller/CalendarController.php @@ -4,6 +4,7 @@ namespace Kanboard\Plugin\Calendar\Controller; use Kanboard\Controller\BaseController; use Kanboard\Filter\TaskAssigneeFilter; +use Kanboard\Filter\TaskDueDateRangeFilter; use Kanboard\Filter\TaskProjectFilter; use Kanboard\Filter\TaskStatusFilter; use Kanboard\Model\TaskModel; @@ -11,17 +12,12 @@ use Kanboard\Model\TaskModel; /** * Calendar Controller * - * @package Kanboard\Controller + * @package Kanboard\Plugin\Calendar\Controller * @author Frederic Guillot * @author Timo Litzbarski */ class CalendarController extends BaseController { - /** - * Show calendar view for a user - * - * @access public - */ public function user() { $user = $this->getUser(); @@ -31,11 +27,6 @@ class CalendarController extends BaseController ))); } - /** - * Show calendar view for a project - * - * @access public - */ public function project() { $project = $this->getProject(); @@ -47,66 +38,75 @@ class CalendarController extends BaseController ))); } - /** - * Get tasks to display on the calendar (project view) - * - * @access public - */ public function projectEvents() { - $project_id = $this->request->getIntegerParam('project_id'); - $start = $this->request->getStringParam('start'); - $end = $this->request->getStringParam('end'); - $search = $this->userSession->getFilters($project_id); - $queryBuilder = $this->taskLexer->build($search)->withFilter(new TaskProjectFilter($project_id)); + $projectId = $this->request->getIntegerParam('project_id'); + $startRange = $this->request->getStringParam('start'); + $endRange = $this->request->getStringParam('end'); + $search = $this->userSession->getFilters($projectId); + $startColumn = $this->configModel->get('calendar_project_tasks', 'date_started'); - $events = $this->helper->calendar->getTaskDateDueEvents(clone($queryBuilder), $start, $end); - $events = array_merge($events, $this->helper->calendar->getTaskEvents(clone($queryBuilder), $start, $end)); + $dueDateOnlyEvents = $this->taskLexer->build($search) + ->withFilter(new TaskProjectFilter($projectId)) + ->withFilter(new TaskDueDateRangeFilter(array($startRange, $endRange))) + ->format($this->taskCalendarFormatter->setColumns('date_due')); + + $startAndDueDateQueryBuilder = $this->taskLexer->build($search) + ->withFilter(new TaskProjectFilter($projectId)); + + $startAndDueDateQueryBuilder + ->getQuery() + ->addCondition($this->getConditionForTasksWithStartAndDueDate($startRange, $endRange, $startColumn, 'date_due')); + + $startAndDueDateEvents = $startAndDueDateQueryBuilder + ->format($this->taskCalendarFormatter->setColumns($startColumn, 'date_due')); + + $events = array_merge($dueDateOnlyEvents, $startAndDueDateEvents); $events = $this->hook->merge('controller:calendar:project:events', $events, array( - 'project_id' => $project_id, - 'start' => $start, - 'end' => $end, + 'project_id' => $projectId, + 'start' => $startRange, + 'end' => $endRange, )); $this->response->json($events); } - /** - * Get tasks to display on the calendar (user view) - * - * @access public - */ public function userEvents() { $user_id = $this->request->getIntegerParam('user_id'); - $start = $this->request->getStringParam('start'); - $end = $this->request->getStringParam('end'); - $queryBuilder = $this->taskQuery + $startRange = $this->request->getStringParam('start'); + $endRange = $this->request->getStringParam('end'); + $startColumn = $this->configModel->get('calendar_project_tasks', 'date_started'); + + $dueDateOnlyEvents = $this->taskQuery + ->withFilter(new TaskAssigneeFilter($user_id)) + ->withFilter(new TaskStatusFilter(TaskModel::STATUS_OPEN)) + ->withFilter(new TaskDueDateRangeFilter(array($startRange, $endRange))) + ->format($this->taskCalendarFormatter->setColumns('date_due')); + + $startAndDueDateQueryBuilder = $this->taskQuery ->withFilter(new TaskAssigneeFilter($user_id)) ->withFilter(new TaskStatusFilter(TaskModel::STATUS_OPEN)); - $events = $this->helper->calendar->getTaskDateDueEvents(clone($queryBuilder), $start, $end); - $events = array_merge($events, $this->helper->calendar->getTaskEvents(clone($queryBuilder), $start, $end)); + $startAndDueDateQueryBuilder + ->getQuery() + ->addCondition($this->getConditionForTasksWithStartAndDueDate($startRange, $endRange, $startColumn, 'date_due')); - if ($this->configModel->get('calendar_user_subtasks_time_tracking') == 1) { - $events = array_merge($events, $this->helper->calendar->getSubtaskTimeTrackingEvents($user_id, $start, $end)); - } + $startAndDueDateEvents = $startAndDueDateQueryBuilder + ->format($this->taskCalendarFormatter->setColumns($startColumn, 'date_due')); + + $events = array_merge($dueDateOnlyEvents, $startAndDueDateEvents); $events = $this->hook->merge('controller:calendar:user:events', $events, array( 'user_id' => $user_id, - 'start' => $start, - 'end' => $end, + 'start' => $startRange, + 'end' => $endRange, )); $this->response->json($events); } - /** - * Update task due date - * - * @access public - */ public function save() { if ($this->request->isAjax() && $this->request->isPost()) { @@ -118,4 +118,20 @@ class CalendarController extends BaseController )); } } + + protected function getConditionForTasksWithStartAndDueDate($startTime, $endTime, $startColumn, $endColumn) + { + $startTime = strtotime($startTime); + $endTime = strtotime($endTime); + $startColumn = $this->db->escapeIdentifier($startColumn); + $endColumn = $this->db->escapeIdentifier($endColumn); + + $conditions = array( + "($startColumn >= '$startTime' AND $startColumn <= '$endTime')", + "($startColumn <= '$startTime' AND $endColumn >= '$startTime')", + "($startColumn <= '$startTime' AND ($endColumn = '0' OR $endColumn IS NULL))", + ); + + return $startColumn.' IS NOT NULL AND '.$startColumn.' > 0 AND ('.implode(' OR ', $conditions).')'; + } } diff --git a/Controller/ConfigController.php b/Controller/ConfigController.php index 64e0e46..61c67f9 100644 --- a/Controller/ConfigController.php +++ b/Controller/ConfigController.php @@ -19,7 +19,6 @@ class ConfigController extends \Kanboard\Controller\ConfigController public function save() { $values = $this->request->getValues(); - $values += array('calendar_user_subtasks_time_tracking' => 0); if ($this->configModel->save($values)) { $this->flash->success(t('Settings saved successfully.')); diff --git a/Formatter/BaseTaskCalendarFormatter.php b/Formatter/BaseTaskCalendarFormatter.php deleted file mode 100644 index c5a3b8f..0000000 --- a/Formatter/BaseTaskCalendarFormatter.php +++ /dev/null @@ -1,45 +0,0 @@ -startColumn = $start_column; - $this->endColumn = $end_column ?: $start_column; - return $this; - } -} diff --git a/Formatter/TaskCalendarFormatter.php b/Formatter/TaskCalendarFormatter.php index b9e3682..9286eaf 100644 --- a/Formatter/TaskCalendarFormatter.php +++ b/Formatter/TaskCalendarFormatter.php @@ -2,33 +2,46 @@ namespace Kanboard\Plugin\Calendar\Formatter; +use DateTime; use Kanboard\Core\Filter\FormatterInterface; +use Kanboard\Formatter\BaseFormatter; /** * Calendar event formatter for task filter * - * @package formatter + * @package Kanboard\Plugin\Calendar\Formatter * @author Frederic Guillot */ -class TaskCalendarFormatter extends BaseTaskCalendarFormatter implements FormatterInterface +class TaskCalendarFormatter extends BaseFormatter implements FormatterInterface { /** - * Full day event flag + * Column used for event start date * - * @access private - * @var boolean + * @access protected + * @var string */ - private $fullDay = false; + protected $startColumn = ''; /** - * When called calendar events will be full day + * Column used for event end date + * + * @access protected + * @var string + */ + protected $endColumn = ''; + + /** + * Transform results to calendar events * * @access public - * @return FormatterInterface + * @param string $start_column Column name for the start date + * @param string $end_column Column name for the end date + * @return $this */ - public function setFullDay() + public function setColumns($start_column, $end_column = '') { - $this->fullDay = true; + $this->startColumn = $start_column; + $this->endColumn = $end_column ?: $start_column; return $this; } @@ -43,6 +56,17 @@ class TaskCalendarFormatter extends BaseTaskCalendarFormatter implements Formatt $events = array(); foreach ($this->query->findAll() as $task) { + $startDate = new DateTime(); + $startDate->setTimestamp($task[$this->startColumn]); + + $endDate = new DateTime(); + if (! empty($task[$this->endColumn])) { + $endDate->setTimestamp($task[$this->endColumn]); + } + + $allDay = $startDate == $endDate && $endDate->format('Hi') == '0000'; + $format = $allDay ? 'Y-m-d' : 'Y-m-d\TH:i:s'; + $events[] = array( 'timezoneParam' => $this->timezoneModel->getCurrentTimezone(), 'id' => $task['id'], @@ -51,24 +75,13 @@ class TaskCalendarFormatter extends BaseTaskCalendarFormatter implements Formatt 'borderColor' => $this->colorModel->getBorderColor($task['color_id']), 'textColor' => 'black', 'url' => $this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), - 'start' => date($this->getDateTimeFormat(), $task[$this->startColumn]), - 'end' => date($this->getDateTimeFormat(), $task[$this->endColumn] ?: time()), - 'editable' => $this->fullDay, - 'allday' => $this->fullDay, + 'start' => $startDate->format($format), + 'end' => $endDate->format($format), + 'editable' => $allDay, + 'allday' => $allDay, ); } return $events; } - - /** - * Get DateTime format for event - * - * @access private - * @return string - */ - private function getDateTimeFormat() - { - return $this->fullDay ? 'Y-m-d' : 'Y-m-d\TH:i:s'; - } } diff --git a/Helper/CalendarHelper.php b/Helper/CalendarHelper.php index f3a6b17..5807b66 100644 --- a/Helper/CalendarHelper.php +++ b/Helper/CalendarHelper.php @@ -3,15 +3,12 @@ namespace Kanboard\Plugin\Calendar\Helper; use Kanboard\Core\Base; -use Kanboard\Core\Filter\QueryBuilder; -use Kanboard\Filter\TaskDueDateRangeFilter; /** * Calendar Helper * - * @package helper + * @package Kanboard\Plugin\Calendar\Helper * @author Frederic Guillot - * @property \Kanboard\Plugin\Calendar\Formatter\TaskCalendarFormatter $taskCalendarFormatter */ class CalendarHelper extends Base { @@ -31,97 +28,4 @@ class CalendarHelper extends Base return '
'; } - - /** - * Get formatted calendar task due events - * - * @access public - * @param QueryBuilder $queryBuilder - * @param string $start - * @param string $end - * @return array - */ - public function getTaskDateDueEvents(QueryBuilder $queryBuilder, $start, $end) - { - $formatter = $this->taskCalendarFormatter; - $formatter->setFullDay(); - $formatter->setColumns('date_due'); - - return $queryBuilder - ->withFilter(new TaskDueDateRangeFilter(array($start, $end))) - ->format($formatter); - } - - /** - * Get formatted calendar task events - * - * @access public - * @param QueryBuilder $queryBuilder - * @param string $start - * @param string $end - * @return array - */ - public function getTaskEvents(QueryBuilder $queryBuilder, $start, $end) - { - $startColumn = $this->configModel->get('calendar_project_tasks', 'date_started'); - - $queryBuilder->getQuery()->addCondition($this->getCalendarCondition( - $this->dateParser->getTimestampFromIsoFormat($start), - $this->dateParser->getTimestampFromIsoFormat($end), - $startColumn, - 'date_due' - )); - - $formatter = $this->taskCalendarFormatter; - $formatter->setColumns($startColumn, 'date_due'); - - return $queryBuilder->format($formatter); - } - - /** - * Get formatted calendar subtask time tracking events - * - * @access public - * @param integer $user_id - * @param string $start - * @param string $end - * @return array - */ - public function getSubtaskTimeTrackingEvents($user_id, $start, $end) - { - return $this->subtaskTimeTrackingCalendarFormatter - ->withQuery($this->subtaskTimeTrackingModel->getUserQuery($user_id) - ->addCondition($this->getCalendarCondition( - $this->dateParser->getTimestampFromIsoFormat($start), - $this->dateParser->getTimestampFromIsoFormat($end), - 'start', - 'end' - )) - ) - ->format(); - } - - /** - * Build SQL condition for a given time range - * - * @access public - * @param string $start_time Start timestamp - * @param string $end_time End timestamp - * @param string $start_column Start column name - * @param string $end_column End column name - * @return string - */ - public function getCalendarCondition($start_time, $end_time, $start_column, $end_column) - { - $start_column = $this->db->escapeIdentifier($start_column); - $end_column = $this->db->escapeIdentifier($end_column); - - $conditions = array( - "($start_column >= '$start_time' AND $start_column <= '$end_time')", - "($start_column <= '$start_time' AND $end_column >= '$start_time')", - "($start_column <= '$start_time' AND ($end_column = '0' OR $end_column IS NULL))", - ); - - return $start_column.' IS NOT NULL AND '.$start_column.' > 0 AND ('.implode(' OR ', $conditions).')'; - } } diff --git a/Plugin.php b/Plugin.php index f6a40bb..acc4f19 100644 --- a/Plugin.php +++ b/Plugin.php @@ -55,7 +55,7 @@ class Plugin extends Base public function getPluginVersion() { - return '1.0.1'; + return '1.1.0'; } public function getPluginHomepage() diff --git a/Template/config/calendar.php b/Template/config/calendar.php index 8d5a489..2221294 100644 --- a/Template/config/calendar.php +++ b/Template/config/calendar.php @@ -25,11 +25,6 @@ ) ?> - -