diff --git a/Controller/ApiController.php b/Controller/ApiController.php index 915025d..e8cf31b 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -25,10 +25,8 @@ use Modules\Media\Models\Reference; use Modules\Media\Models\ReferenceMapper; use Modules\Notification\Models\Notification; use Modules\Notification\Models\NotificationMapper; -use Modules\Notification\Models\NotificationStatus; use Modules\Notification\Models\NotificationType; use Modules\Profile\Models\ProfileMapper; -use Modules\Tasks\Models\DutyType; use Modules\Tasks\Models\PermissionCategory; use Modules\Tasks\Models\Task; use Modules\Tasks\Models\TaskElement; @@ -133,7 +131,7 @@ final class ApiController extends Controller */ public function createTaskReminderFromRequest(RequestAbstract $request) : array { - /** @var AccountRelation[] $responsible */ + /** @var \Modules\Tasks\Models\AccountRelation[] $responsible */ $responsible = TaskMapper::getResponsible((int) $request->getData('id')); $reminder = []; @@ -176,7 +174,10 @@ final class ApiController extends Controller $task = $this->createTaskFromRequest($request); $this->createModel($request->header->account, $task, TaskMapper::class, 'task', $request->getOrigin()); - $this->createNotifications(\reset($task->taskElements), NotificationType::CREATE, $request); + $first = \reset($task->taskElements); + if ($first !== false) { + $this->createNotifications($first, NotificationType::CREATE, $request); + } if (!empty($request->files) || !empty($request->getDataJson('media')) @@ -187,6 +188,19 @@ final class ApiController extends Controller $this->createStandardCreateResponse($request, $response, $task); } + /** + * Create notifications for users. + * + * This is usually called when creating a task or adding a new child element. + * + * @param TaskElement $ele Task element + * @param int $type Notification type (e.g. new, new child element, ...) + * @param RequestAbstract $request Request that caused this notification to get created + * + * @return void + * + * @since 1.0.0 + */ private function createNotifications(TaskElement $ele, int $type, RequestAbstract $request) : void { $accChecked = []; @@ -221,15 +235,15 @@ final class ApiController extends Controller continue; } - $notification = new Notification(); - $notification->module = self::NAME; - $notification->title = $task->title; - $notification->createdBy = $element->createdBy; + $notification = new Notification(); + $notification->module = self::NAME; + $notification->title = $task->title; + $notification->createdBy = $element->createdBy; $notification->createdFor = $rel->relation; - $notification->type = $type; - $notification->category = PermissionCategory::TASK; - $notification->element = $task->id; - $notification->redirect = '{/base}/task/view?{?}&id=' . $element->task; + $notification->type = $type; + $notification->category = PermissionCategory::TASK; + $notification->element = $task->id; + $notification->redirect = '{/base}/task/view?{?}&id=' . $element->task; $this->createModel($request->header->account, $notification, NotificationMapper::class, 'notification', $request->getOrigin()); $accChecked[] = $rel->relation->id; @@ -259,15 +273,15 @@ final class ApiController extends Controller continue; } - $notification = new Notification(); - $notification->module = self::NAME; - $notification->title = $task->title; - $notification->createdBy = $element->createdBy; + $notification = new Notification(); + $notification->module = self::NAME; + $notification->title = $task->title; + $notification->createdBy = $element->createdBy; $notification->createdFor = $account; - $notification->type = $type; - $notification->category = PermissionCategory::TASK; - $notification->element = $task->id; - $notification->redirect = '{/base}/task/view?{?}&id=' . $element->task; + $notification->type = $type; + $notification->category = PermissionCategory::TASK; + $notification->element = $task->id; + $notification->redirect = '{/base}/task/view?{?}&id=' . $element->task; $this->createModel($request->header->account, $notification, NotificationMapper::class, 'notification', $request->getOrigin()); $accChecked[] = $account->id; diff --git a/Controller/BackendController.php b/Controller/BackendController.php index c7629c8..b6378ff 100755 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -126,7 +126,6 @@ final class BackendController extends Controller implements DashboardElementInte ->execute(); } - /** @var \Modules\Tasks\Models\TaskSeen[] $unread */ $view->data['unread'] = TaskMapper::getUnread($request->header->account); return $view; @@ -195,6 +194,8 @@ final class BackendController extends Controller implements DashboardElementInte } $view->data['task_media'] = []; + + /** @var \Modules\Tasks\Models\Task $task */ foreach ($view->data['tasks'] as $task) { $view->data['task_media'][$task->id] = TaskMapper::has() ->with('files') @@ -203,7 +204,6 @@ final class BackendController extends Controller implements DashboardElementInte ->execute(); } - /** @var \Modules\Tasks\Models\TaskSeen[] $unread */ $view->data['unread'] = TaskMapper::getUnread($request->header->account); return $view; @@ -321,7 +321,7 @@ final class BackendController extends Controller implements DashboardElementInte // Shows all reminders if ($unseen->reminderBy !== null && ($unseen->reminderAt?->getTimestamp() ?? 0) < $request->header->getRequestTime() - && ($unseen->reminderAt?->getTimestamp() ?? 0) > ($unseen->seenAt?->getTimestamp() ?? 0) - 300 + && ($unseen->reminderAt?->getTimestamp() ?? 0) > $unseen->seenAt->getTimestamp() - 300 ) { $reminderStatus[] = $unseen; diff --git a/Controller/SearchController.php b/Controller/SearchController.php index 3bfff4f..fb5bf2a 100755 --- a/Controller/SearchController.php +++ b/Controller/SearchController.php @@ -68,7 +68,7 @@ final class SearchController extends Controller ->execute(); $results = []; - $count = 0; + $count = 0; foreach ($tasks as $task) { if ($count >= 8) { @@ -89,10 +89,10 @@ final class SearchController extends Controller 'link' => '{/base}/task/view?id=' . $task->id, 'account' => '', 'createdAt' => $task->createdAt, - 'image' => '', - 'tags' => $task->tags, - 'type' => 'list_links', - 'module' => 'Tasks', + 'image' => '', + 'tags' => $task->tags, + 'type' => 'list_links', + 'module' => 'Tasks', ]; } @@ -135,7 +135,7 @@ final class SearchController extends Controller ->execute(); $results = []; - $count = 0; + $count = 0; foreach ($tasks as $task) { if ($count >= 8) { @@ -156,10 +156,10 @@ final class SearchController extends Controller 'link' => '{/base}/task/view?id=' . $task->id, 'account' => '', 'createdAt' => $task->createdAt, - 'image' => '', - 'tags' => $task->tags, - 'type' => 'list_links', - 'module' => 'Tasks', + 'image' => '', + 'tags' => $task->tags, + 'type' => 'list_links', + 'module' => 'Tasks', ]; } diff --git a/Models/Task.php b/Models/Task.php index 26bd2f8..e1d44a6 100755 --- a/Models/Task.php +++ b/Models/Task.php @@ -428,6 +428,13 @@ class Task implements \JsonSerializable return $this->taskElements[$id] ?? new NullTaskElement(); } + /** + * Get accounts that are responsible for this task + * + * @return Account[] + * + * @since 1.0.0 + */ public function getResponsible() : array { $responsible = []; @@ -445,7 +452,7 @@ class Task implements \JsonSerializable } $responsible[] = $accRel->relation; - $first = false; + $first = false; } } } @@ -482,6 +489,17 @@ class Task implements \JsonSerializable return $this->toArray(); } + /** + * Create a new task from a task template. + * + * A task template is a normal task with the type of TEMPLATE. + * + * @param self $task Task to "clone" + * + * @return self + * + * @since 1.0.0 + */ public static function fromTemplate(self $task) : self { $now = new \DateTimeImmutable('now'); @@ -500,12 +518,12 @@ class Task implements \JsonSerializable // We need to create a new relation since the old one references the template foreach ($task->attributes as $attribute) { - $attribute->id = 0; + $attribute->id = 0; $attribute->ref = 0; } foreach ($task->taskElements as $element) { - $element->id = 0; + $element->id = 0; $element->task = 0; if ($element->due !== null) { @@ -519,12 +537,12 @@ class Task implements \JsonSerializable // We need to create a new relation since the old one references the template foreach ($element->accRelation as $relation) { - $relation->id = 0; + $relation->id = 0; $relation->element = 0; } foreach ($element->grpRelation as $relation) { - $relation->id = 0; + $relation->id = 0; $relation->element = 0; } } diff --git a/Models/TaskMapper.php b/Models/TaskMapper.php index ce91faa..fc0a224 100755 --- a/Models/TaskMapper.php +++ b/Models/TaskMapper.php @@ -411,7 +411,7 @@ final class TaskMapper extends DataMapperFactory ->innerJoin(AccountRelationMapper::TABLE) ->on(TaskElementMapper::TABLE . '.' . TaskElementMapper::PRIMARYFIELD, '=', AccountRelationMapper::TABLE . '.task_account_task_element') ->leftJoin(TaskSeenMapper::TABLE) - ->on(TaskMapper::TABLE . '.' . TaskMapper::PRIMARYFIELD, '=', TaskSeenMapper::TABLE . '.task_seen_task') + ->on(self::TABLE . '.' . self::PRIMARYFIELD, '=', TaskSeenMapper::TABLE . '.task_seen_task') ->where(self::TABLE . '.task_status', '=', TaskStatus::OPEN) ->andWhere(AccountRelationMapper::TABLE . '.task_account_account', '=', $user) ->andWhere(TaskSeenMapper::TABLE . '.task_seen_task', '=', null); diff --git a/Theme/Backend/Lang/de.lang.php b/Theme/Backend/Lang/de.lang.php index ab2b2bc..932761b 100755 --- a/Theme/Backend/Lang/de.lang.php +++ b/Theme/Backend/Lang/de.lang.php @@ -21,7 +21,7 @@ return ['Tasks' => [ 'Completion' => 'Abgeschlossen', 'Created' => 'Erstellt', 'Creator' => 'Ersteller', - 'Advanced' => 'Fortgeschritten', + 'Advanced' => 'Fortgeschritten', 'Due' => 'Fällig', 'Due/Priority' => 'Fällig / Priorität', 'For' => 'Für', diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index 4a4136c..dedd67e 100755 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -21,7 +21,7 @@ return ['Tasks' => [ 'Completion' => 'Completion', 'Created' => 'Created', 'Creator' => 'Creator', - 'Advanced' => 'Advanced', + 'Advanced' => 'Advanced', 'Due' => 'Due', 'Due/Priority' => 'Due/Priority', 'For' => 'For',