diff --git a/Admin/Install/db.json b/Admin/Install/db.json index 641f766..bfe756b 100644 --- a/Admin/Install/db.json +++ b/Admin/Install/db.json @@ -39,6 +39,11 @@ "type": "TINYINT", "null": false }, + "task_editable": { + "name": "task_editable", + "type": "TINYINT", + "null": false + }, "task_priority": { "name": "task_priority", "type": "TINYINT", @@ -110,42 +115,6 @@ } } }, - "task_account": { - "name": "task_account", - "fields": { - "task_account_id": { - "name": "task_account_id", - "type": "INT", - "null": false, - "primary": true, - "autoincrement": true - }, - "task_account_task": { - "name": "task_account_task", - "type": "INT", - "null": false, - "foreignTable": "task", - "foreignKey": "task_id" - }, - "task_account_account": { - "name": "task_account_account", - "type": "INT", - "null": false, - "foreignTable": "account", - "foreignKey": "account_id" - }, - "task_account_seen": { - "name": "task_account_seen", - "type": "TINYINT", - "null": false - }, - "task_account_type": { - "name": "task_account_type", - "type": "TINYINT", - "null": false - } - } - }, "task_element": { "name": "task_element", "fields": { @@ -195,14 +164,6 @@ "type": "DATETIME", "null": false }, - "task_element_forwarded": { - "name": "task_element_forwarded", - "type": "INT", - "default": null, - "null": true, - "foreignTable": "account", - "foreignKey": "account_id" - }, "task_element_created_at": { "name": "task_element_created_at", "type": "DATETIME", @@ -210,6 +171,76 @@ } } }, + "task_account": { + "name": "task_account", + "fields": { + "task_account_id": { + "name": "task_account_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "task_account_task_element": { + "name": "task_account_task_element", + "type": "INT", + "default": null, + "null": true, + "foreignTable": "task_element", + "foreignKey": "task_element_id" + }, + "task_account_account": { + "name": "task_account_account", + "type": "INT", + "null": false, + "foreignTable": "account", + "foreignKey": "account_id" + }, + "task_account_seen": { + "name": "task_account_seen", + "type": "TINYINT", + "default": 0, + "null": false + }, + "task_account_duty": { + "name": "task_account_duty", + "type": "TINYINT", + "null": false + } + } + }, + "task_group": { + "name": "task_group", + "fields": { + "task_group_id": { + "name": "task_group_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "task_group_task_element": { + "name": "task_group_task_element", + "type": "INT", + "default": null, + "null": true, + "foreignTable": "task_element", + "foreignKey": "task_element_id" + }, + "task_group_group": { + "name": "task_group_group", + "type": "INT", + "null": false, + "foreignTable": "account", + "foreignKey": "account_id" + }, + "task_group_duty": { + "name": "task_group_duty", + "type": "TINYINT", + "null": false + } + } + }, "task_element_media": { "name": "task_element_media", "fields": { diff --git a/Controller/ApiController.php b/Controller/ApiController.php index cf84c15..4230e1a 100644 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -29,7 +29,7 @@ use phpOMS\Model\Message\FormValidation; use phpOMS\Utils\Parser\Markdown\Markdown; /** - * Task class. + * Api controller for the tasks module. * * @package Modules\Tasks * @license OMS License 1.0 @@ -43,7 +43,7 @@ final class ApiController extends Controller * * @param RequestAbstract $request Request * - * @return array + * @return array Returns the validation array of the request * * @since 1.0.0 */ @@ -61,6 +61,8 @@ final class ApiController extends Controller } /** + * Api method to create a task + * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * @param mixed $data Generic data @@ -74,7 +76,7 @@ final class ApiController extends Controller public function apiTaskCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { if (!empty($val = $this->validateTaskCreate($request))) { - $response->set('task_create', new FormValidation($val)); + $response->set($request->getUri()->__toString(), new FormValidation($val)); return; } @@ -89,7 +91,7 @@ final class ApiController extends Controller * * @param RequestAbstract $request Request * - * @return Task + * @return Task Returns the created task from the request * * @since 1.0.0 */ @@ -106,7 +108,7 @@ final class ApiController extends Controller $task->setPriority((int) $request->getData('priority')); $element = new TaskElement(); - $element->setForwarded((int) ($request->getData('forward') ?? $request->getHeader()->getAccount())); + $element->addTo((int) ($request->getData('forward') ?? $request->getHeader()->getAccount())); $element->setCreatedBy($task->getCreatedBy()); $element->setDue($task->getDue()); $element->setPriority($task->getPriority()); @@ -162,7 +164,7 @@ final class ApiController extends Controller * * @param RequestAbstract $request Request * - * @return Task + * @return Task Returns the updated task from the request * * @since 1.0.0 */ @@ -185,7 +187,7 @@ final class ApiController extends Controller * * @param RequestAbstract $request Request * - * @return array + * @return array Returns the validation array of the request * * @since 1.0.0 */ @@ -193,9 +195,9 @@ final class ApiController extends Controller { $val = []; if (($val['status'] = !TaskStatus::isValidValue((int) $request->getData('status'))) - || ($val['due'] = !((bool) strtotime((string) $request->getData('due')))) - || ($val['task'] = !(is_numeric($request->getData('task')))) - || ($val['forward'] = !(is_numeric(empty($request->getData('forward')) ? $request->getHeader()->getAccount() : $request->getData('forward')))) + || ($val['due'] = !((bool) \strtotime((string) $request->getData('due')))) + || ($val['task'] = !(\is_numeric($request->getData('task')))) + || ($val['forward'] = !(\is_numeric(empty($request->getData('forward')) ? $request->getHeader()->getAccount() : $request->getData('forward')))) ) { // todo: validate correct task return $val; } @@ -204,6 +206,8 @@ final class ApiController extends Controller } /** + * Api method to create a task element + * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response * @param mixed $data Generic data @@ -237,14 +241,13 @@ final class ApiController extends Controller * * @param RequestAbstract $request Request * - * @return TaskElement + * @return TaskElement Returns the task created from the request * * @since 1.0.0 */ private function createTaskElementFromRequest(RequestAbstract $request) : TaskElement { $element = new TaskElement(); - $element->setForwarded((int) ($request->getData('forward') ?? $request->getHeader()->getAccount())); $element->setCreatedBy($request->getHeader()->getAccount()); $element->setDue(new \DateTime((string) ($request->getData('due') ?? 'now'))); $element->setPriority((int) $request->getData('priority')); @@ -253,6 +256,24 @@ final class ApiController extends Controller $element->setDescription(Markdown::parse((string) ($request->getData('plain') ?? ''))); $element->setDescriptionRaw((string) ($request->getData('plain') ?? '')); + $tos = $request->getData('to') ?? $request->getHeader()->getAccount(); + if (!\is_array($tos)) { + $tos = [$tos]; + } + + $ccs = $request->getData('cc') ?? []; + if (!\is_array($ccs)) { + $ccs = [$ccs]; + } + + foreach ($tos as $to) { + $element->addTo($to); + } + + foreach ($ccs as $cc) { + $element->addCC($cc); + } + return $element; } @@ -293,7 +314,7 @@ final class ApiController extends Controller $old = clone TaskElementMapper::get((int) $request->getData('id')); $new = $this->updateTaskElementFromRequest($request); $this->updateModel($request, $old, $new, TaskElementMapper::class, 'taskelement'); - // todo: update task if elment status change had effect on task status!!! + // todo: update task if element status change had effect on task status!!! //$this->updateModel($request, $task, $task, TaskMapper::class, 'task'); $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Task element', 'Task element successfully updated.', $new); } @@ -303,19 +324,36 @@ final class ApiController extends Controller * * @param RequestAbstract $request Request * - * @return TaskElement + * @return TaskElement Returns the updated task element from the request * * @since 1.0.0 */ private function updateTaskElementFromRequest(RequestAbstract $request) : TaskElement { $element = TaskElementMapper::get((int) ($request->getData('id'))); - $element->setForwarded((int) ($request->getData('forward') ?? !\is_int($forwarded = $element->getForwarded()) ? $forwarded->getId() : $forwarded)); $element->setDue(new \DateTime((string) ($request->getData('due') ?? $element->getDue()->format('Y-m-d H:i:s')))); $element->setStatus((int) ($request->getData('status') ?? $element->getStatus())); $element->setDescription(Markdown::parse((string) ($request->getData('description') ?? $element->getDescriptionRaw()))); $element->setDescriptionRaw((string) ($request->getData('description') ?? $element->getDescriptionRaw())); + $tos = $request->getData('to') ?? $request->getHeader()->getAccount(); + if (!\is_array($tos)) { + $tos = [$tos]; + } + + $ccs = $request->getData('cc') ?? []; + if (!\is_array($ccs)) { + $ccs = [$ccs]; + } + + foreach ($tos as $to) { + $element->addTo($to); + } + + foreach ($ccs as $cc) { + $element->addCC($cc); + } + return $element; } } diff --git a/Controller/BackendController.php b/Controller/BackendController.php index 9e9473c..9007a51 100644 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -28,7 +28,7 @@ use phpOMS\Message\ResponseAbstract; use phpOMS\Views\View; /** - * Task class. + * Backend controller for the tasks module. * * @package Modules\Tasks * @license OMS License 1.0 @@ -42,7 +42,7 @@ final class BackendController extends Controller * @param ResponseAbstract $response Response * @param mixed $data Generic data * - * @return RenderableInterface + * @return RenderableInterface Returns a renderable object * * @since 1.0.0 * @codeCoverageIgnore @@ -67,7 +67,7 @@ final class BackendController extends Controller * @param ResponseAbstract $response Response * @param mixed $data Generic data * - * @return RenderableInterface + * @return RenderableInterface Returns a renderable object * * @since 1.0.0 * @codeCoverageIgnore @@ -93,7 +93,7 @@ final class BackendController extends Controller * @param ResponseAbstract $response Response * @param mixed $data Generic data * - * @return RenderableInterface + * @return RenderableInterface Returns a renderable object * * @since 1.0.0 * @codeCoverageIgnore @@ -106,8 +106,8 @@ final class BackendController extends Controller $accountId = $request->getHeader()->getAccount(); if (!($task->getCreatedBy()->getId() === $accountId - || $task->isCc($accountId) - || $task->isForwarded($accountId)) + || $task->isCCAccount($accountId) + || $task->isToAccount($accountId)) && !$this->app->accountManager->get($accountId)->hasPermission( PermissionType::READ, $this->app->orgId, $this->app->appName, self::MODULE_NAME, PermissionState::TASK, $task->getId()) ) { @@ -134,7 +134,7 @@ final class BackendController extends Controller * @param ResponseAbstract $response Response * @param mixed $data Generic data * - * @return RenderableInterface + * @return RenderableInterface Returns a renderable object * * @since 1.0.0 * @codeCoverageIgnore @@ -160,7 +160,7 @@ final class BackendController extends Controller * @param ResponseAbstract $response Response * @param mixed $data Generic data * - * @return RenderableInterface + * @return RenderableInterface Returns a renderable object * * @since 1.0.0 * @codeCoverageIgnore @@ -179,7 +179,7 @@ final class BackendController extends Controller * * @param int $account Account id * - * @return int + * @return int Returns the amount of unread tasks * * @since 1.0.0 */ diff --git a/Models/AccountRelation.php b/Models/AccountRelation.php new file mode 100644 index 0000000..3ed178e --- /dev/null +++ b/Models/AccountRelation.php @@ -0,0 +1,82 @@ +relation = $account; + $this->duty = $duty; + } + + /** + * Get relation object. + * + * @return int|Account + * + * @since 1.0.0 + */ + public function getRelation() + { + return $this->relation; + } + + /** + * {@inheritdoc} + */ + public function toArray() : array + { + return [ + 'id' => $this->id, + 'duty' => $this->duty, + 'relation' => $this->relation, + ]; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() + { + return $this->toArray(); + } +} diff --git a/Models/AccountRelationMapper.php b/Models/AccountRelationMapper.php new file mode 100644 index 0000000..08dde74 --- /dev/null +++ b/Models/AccountRelationMapper.php @@ -0,0 +1,72 @@ +> + * @since 1.0.0 + */ + protected static $columns = [ + 'task_account_id' => ['name' => 'task_account_id', 'type' => 'int', 'internal' => 'id'], + 'task_account_duty' => ['name' => 'task_account_duty', 'type' => 'int', 'internal' => 'duty'], + 'task_account_account' => ['name' => 'task_account_account', 'type' => 'int', 'internal' => 'relation'], + 'task_account_task_element' => ['name' => 'task_account_task_element', 'type' => 'int', 'internal' => 'element'], + ]; + + /** + * Has one relation. + * + * @var array> + * @since 1.0.0 + */ + protected static $ownsOne = [ + 'relation' => [ + 'mapper' => AccountMapper::class, + 'src' => 'task_account_account', + ], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + protected static $table = 'task_account'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + protected static $primaryField = 'task_account_id'; +} diff --git a/Models/DutyType.php b/Models/DutyType.php new file mode 100644 index 0000000..d4962c6 --- /dev/null +++ b/Models/DutyType.php @@ -0,0 +1,31 @@ +relation = $group; + $this->duty = $duty; + } + + /** + * Get relation object. + * + * @return int|Group + * + * @since 1.0.0 + */ + public function getRelation() + { + return $this->relation; + } + + /** + * {@inheritdoc} + */ + public function toArray() : array + { + return [ + 'id' => $this->id, + 'duty' => $this->duty, + 'relation' => $this->relation, + ]; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() + { + return $this->toArray(); + } +} diff --git a/Models/GroupRelationMapper.php b/Models/GroupRelationMapper.php new file mode 100644 index 0000000..d087d33 --- /dev/null +++ b/Models/GroupRelationMapper.php @@ -0,0 +1,72 @@ +> + * @since 1.0.0 + */ + protected static $columns = [ + 'task_group_id' => ['name' => 'task_group_id', 'type' => 'int', 'internal' => 'id'], + 'task_group_duty' => ['name' => 'task_group_duty', 'type' => 'int', 'internal' => 'duty'], + 'task_group_group' => ['name' => 'task_group_group', 'type' => 'int', 'internal' => 'relation'], + 'task_group_task_element' => ['name' => 'task_group_task_element', 'type' => 'int', 'internal' => 'element'], + ]; + + /** + * Has one relation. + * + * @var array> + * @since 1.0.0 + */ + protected static $ownsOne = [ + 'relation' => [ + 'mapper' => GroupMapper::class, + 'src' => 'task_group_group', + ], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + protected static $table = 'task_group'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + protected static $primaryField = 'task_group_id'; +} diff --git a/Models/NullTask.php b/Models/NullTask.php index 598f0fd..9c71b5f 100644 --- a/Models/NullTask.php +++ b/Models/NullTask.php @@ -22,7 +22,7 @@ namespace Modules\Tasks\Models; * @link http://website.orange-management.de * @since 1.0.0 */ -class NullTask extends Task +final class NullTask extends Task { } diff --git a/Models/NullTaskElement.php b/Models/NullTaskElement.php index ee4f04a..eb8ecb0 100644 --- a/Models/NullTaskElement.php +++ b/Models/NullTaskElement.php @@ -22,7 +22,7 @@ namespace Modules\Tasks\Models; * @link http://website.orange-management.de * @since 1.0.0 */ -class NullTaskElement extends TaskElement +final class NullTaskElement extends TaskElement { } diff --git a/Models/RelationAbstract.php b/Models/RelationAbstract.php new file mode 100644 index 0000000..714529c --- /dev/null +++ b/Models/RelationAbstract.php @@ -0,0 +1,106 @@ +id; + } + + /** + * Set the duty (TO or CC) + * + * @param int $duty Is TO or CC + * + * @return void + * + * @since 1.0.0 + */ + public function setDuty(int $duty) : void + { + $this->duty = $duty; + } + + /** + * Get the duty (TO or CC) + * + * @return void Is TO or CC + * + * @since 1.0.0 + */ + public function getDuty() : int + { + return $this->duty; + } + + /** + * Get the relation object + * + * @return Account|Group + * + * @since 1.0.0 + */ + public abstract function getRelation(); + + /** + * {@inheritdoc} + */ + public abstract function jsonSerialize(); +} diff --git a/Models/Task.php b/Models/Task.php index 45cf4bf..4f2e78c 100644 --- a/Models/Task.php +++ b/Models/Task.php @@ -100,6 +100,14 @@ class Task implements \JsonSerializable */ protected $isClosable = true; + /** + * Task can be edited by user. + * + * @var bool + * @since 1.0.0 + */ + protected $isEditable = true; + /** * Start. * @@ -156,8 +164,6 @@ class Task implements \JsonSerializable */ protected $media = []; - protected $acc = []; - /** * Constructor. * @@ -166,10 +172,22 @@ class Task implements \JsonSerializable public function __construct() { $this->createdAt = new \DateTime('now'); + $this->schedule = new Schedule(); $this->start = new \DateTime('now'); $this->due = new \DateTime('now'); $this->due->modify('+1 day'); - $this->schedule = new Schedule(); + } + + /** + * Get id + * + * @return int + * + * @since 1.0.0 + */ + public function getId() : int + { + return $this->id; } /** @@ -200,6 +218,34 @@ class Task implements \JsonSerializable return $this->isClosable; } + /** + * Set editable + * + * Setting it to false will only allow other modules to close this task + * + * @param bool $editable Is editable + * + * @return void + * + * @since 1.0.0 + */ + public function setEditable(bool $editable) : void + { + $this->isEditable = $editable; + } + + /** + * Is editable + * + * @return bool + * + * @since 1.0.0 + */ + public function isEditable() : bool + { + return $this->isEditable; + } + /** * Adding new task element. * @@ -247,7 +293,7 @@ class Task implements \JsonSerializable } /** - * Check if user is cc + * Check if user is in to * * @param int $id User id * @@ -255,13 +301,39 @@ class Task implements \JsonSerializable * * @since 1.0.0 */ - public function isCc(int $id) : bool + public function isToAccount(int $id) : bool { + foreach ($this->taskElements as $element) { + if ($element->isToAccount($id)) { + return true; + } + } + return false; } /** - * check if user is forwarded + * Check if group is in to + * + * @param int $id Group id + * + * @return bool + * + * @since 1.0.0 + */ + public function isToGroup(int $id) : bool + { + foreach ($this->taskElements as $element) { + if ($element->isToGroup($id)) { + return true; + } + } + + return false; + } + + /** + * Check if user is in cc * * @param int $id User id * @@ -269,10 +341,30 @@ class Task implements \JsonSerializable * * @since 1.0.0 */ - public function isForwarded(int $id) : bool + public function isCCAccount(int $id) : bool { foreach ($this->taskElements as $element) { - if ($element->getForwarded()->getId() === $id) { + if ($element->isCCAccount($id)) { + return true; + } + } + + return false; + } + + /** + * Check if group is in cc + * + * @param int $id Group id + * + * @return bool + * + * @since 1.0.0 + */ + public function isCCGroup(int $id) : bool + { + foreach ($this->taskElements as $element) { + if ($element->isCCGroup($id)) { return true; } } @@ -445,18 +537,6 @@ class Task implements \JsonSerializable $this->due = $due; } - /** - * Get id - * - * @return int - * - * @since 1.0.0 - */ - public function getId() : int - { - return $this->id; - } - /** * Get status * @@ -637,16 +717,17 @@ class Task implements \JsonSerializable public function toArray() : array { return [ - 'id' => $this->id, - 'createdBy' => $this->createdBy, - 'createdAt' => $this->createdAt->format('Y-m-d H:i:s'), - 'title' => $this->title, + 'id' => $this->id, + 'createdBy' => $this->createdBy, + 'createdAt' => $this->createdAt->format('Y-m-d H:i:s'), + 'title' => $this->title, 'description' => $this->description, - 'status' => $this->status, - 'type' => $this->type, - 'priority' => $this->priority, - 'due' => $this->due->format('Y-m-d H:i:s'), - 'done' => (!isset($this->done) ? null : $this->done->format('Y-m-d H:i:s')), + 'status' => $this->status, + 'type' => $this->type, + 'priority' => $this->priority, + 'due' => $this->due->format('Y-m-d H:i:s'), + 'done' => (!isset($this->done) ? null : $this->done->format('Y-m-d H:i:s')), + 'elements' => $this->taskElements, ]; } diff --git a/Models/TaskElement.php b/Models/TaskElement.php index 849ddb5..09d99b8 100644 --- a/Models/TaskElement.php +++ b/Models/TaskElement.php @@ -16,6 +16,9 @@ namespace Modules\Tasks\Models; use phpOMS\Stdlib\Base\Exception\InvalidEnumValue; +use Modules\Admin\Models\Account; +use Modules\Admin\Models\Group; + /** * Task class. * @@ -99,14 +102,6 @@ class TaskElement implements \JsonSerializable */ protected $priority = TaskPriority::NONE; - /** - * Forwarded to. - * - * @var int - * @since 1.0.0 - */ - private $forwarded = 0; - /** * Media. * @@ -115,6 +110,22 @@ class TaskElement implements \JsonSerializable */ private $media = []; + /** + * Accounts who received this task element. + * + * @var array + * @since 1.0.0 + */ + protected $accRelation = []; + + /** + * Groups who received this task element. + * + * @var array + * @since 1.0.0 + */ + protected $grpRelation = []; + /** * Constructor. * @@ -127,6 +138,18 @@ class TaskElement implements \JsonSerializable $this->createdAt = new \DateTime('now'); } + /** + * Get id + * + * @return int + * + * @since 1.0.0 + */ + public function getId() : int + { + return $this->id; + } + /** * @return \DateTime * @@ -160,8 +183,8 @@ class TaskElement implements \JsonSerializable { $this->createdBy = $creator; - if ($this->forwarded === 0) { - $this->setForwarded($this->createdBy); + if (empty($this->acc)) { + $this->addTo($this->createdBy); } } @@ -301,41 +324,283 @@ class TaskElement implements \JsonSerializable } /** - * Get forwarded + * Get to * - * @return mixed + * @return array * * @since 1.0.0 */ - public function getForwarded() + public function getTo() : array { - return $this->forwarded; + $to = []; + + foreach ($this->accRelation as $acc) { + if ($acc->getDuty() === DutyType::TO) { + $to[] = $acc; + } + } + + foreach ($this->grpRelation as $grp) { + if ($grp->getDuty() === DutyType::TO) { + $to[] = $grp; + } + } + + return $to; } /** - * Set forwarded + * Check if user is in to * - * @param mixed $forwarded Forward to + * @param int $id User id + * + * @return bool + * + * @since 1.0.0 + */ + public function isToAccount(int $id) : bool + { + foreach ($this->accRelation as $acc) { + if (($acc->getDuty() === DutyType::TO + && ($acc->getRelation() instanceof AccountRelation) && $acc->getRelation()->getId() === $id) + || ($acc->getDuty() === DutyType::TO + && $acc->getRelation() === $id) + ) { + return true; + } + } + + return false; + } + + /** + * Check if group is in to + * + * @param int $id Group id + * + * @return bool + * + * @since 1.0.0 + */ + public function isToGroup(int $id) : bool + { + foreach ($this->grpRelation as $grp) { + if (($grp->getDuty() === DutyType::TO + && ($grp->getRelation() instanceof GroupRelation) && $grp->getRelation()->getId() === $id) + || ($grp->getDuty() === DutyType::TO + && $grp->getRelation() === $id) + ) { + return true; + } + } + + return false; + } + + /** + * Check if user is in cc + * + * @param int $id User id + * + * @return bool + * + * @since 1.0.0 + */ + public function isCCAccount(int $id) : bool + { + foreach ($this->accRelation as $acc) { + if (($acc->getDuty() === DutyType::CC + && ($acc->getRelation() instanceof AccountRelation) && $acc->getRelation()->getId() === $id) + || ($acc->getDuty() === DutyType::CC + && $acc->getRelation() === $id) + ) { + return true; + } + } + + return false; + } + + /** + * Check if group is in cc + * + * @param int $id Group id + * + * @return bool + * + * @since 1.0.0 + */ + public function isCCGroup(int $id) : bool + { + foreach ($this->grpRelation as $grp) { + if (($grp->getDuty() === DutyType::CC + && ($grp->getRelation() instanceof GroupRelation) && $grp->getRelation()->getId() === $id) + || ($grp->getDuty() === DutyType::CC + && $grp->getRelation() === $id) + ) { + return true; + } + } + + return false; + } + + /** + * Add to + * + * @param mixed $to To * * @return void * * @since 1.0.0 */ - public function setForwarded($forwarded) : void + public function addTo($to) : void { - $this->forwarded = $forwarded; + if ($to instanceof Group) { + $this->addGroupTo($to); + } elseif(($to instanceof Account) || \is_int($to)) { + $this->addAccountTo($to); + } } /** - * Get id + * Add group as to * - * @return int + * @param int|Group $group Group + * + * @return void * * @since 1.0.0 */ - public function getId() : int + public function addGroupTo($group) : void { - return $this->id; + $groupId = \is_int($group) ? $group : $group->getId(); + + foreach ($this->grpRelation as $grp) { + $grpId = !\is_int($grp->getRelation()) ? $grp->getRelation()->getId() : $grp->getRelation(); + + if ($grpId === $groupId && $grp->getDuty() === DutyType::TO) { + return; + } + } + + $this->grpRelation[] = new GroupRelation($group, DutyType::TO); + } + + /** + * Add account as to + * + * @param int|Account $account Account + * + * @return void + * + * @since 1.0.0 + */ + public function addAccountTo($account) : void + { + $accountId = \is_int($account) ? $account : $account->getId(); + + foreach ($this->accRelation as $acc) { + $accId = !\is_int($acc->getRelation()) ? $acc->getRelation()->getId() : $acc->getRelation(); + + if ($accId === $accountId && $acc->getDuty() === DutyType::TO) { + return; + } + } + + $this->accRelation[] = new AccountRelation($account, DutyType::TO); + } + + /** + * Get cc + * + * @return array + * + * @since 1.0.0 + */ + public function getCC() : array + { + $cc = []; + + foreach ($this->accRelation as $acc) { + if ($acc->getDuty() === DutyType::CC) { + $cc[] = $acc; + } + } + + foreach ($this->grpRelation as $grp) { + if ($grp->getDuty() === DutyType::CC) { + $cc[] = $grp; + } + } + + return $cc; + } + + /** + * Add cc + * + * @param mixed $cc CC + * + * @return void + * + * @since 1.0.0 + */ + public function addCC($cc) : void + { + if ($cc instanceof Group) { + $this->addGroupCC($cc); + } elseif(($cc instanceof Account) || \is_int($cc)) { + $this->addAccountCC($cc); + } + } + + /** + * Add group as cc + * + * @param int|Group $group Group + * + * @return void + * + * @since 1.0.0 + */ + public function addGroupCC($group) : void + { + $groupId = \is_int($group) ? $group : $group->getId(); + + foreach ($this->grpRelation as $grp) { + $grpId = !\is_int($grp->getRelation()) ? $grp->getRelation()->getId() : $grp->getRelation(); + + if ($grpId === $groupId && $grp->getDuty() === DutyType::CC) { + return; + } + } + + $this->grpRelation[] = new GroupRelation($group, DutyType::CC); + } + + /** + * Add account as cc + * + * @param int|Account $account Account + * + * @return void + * + * @since 1.0.0 + */ + public function addAccountCC($account) : void + { + $accountId = \is_int($account) ? $account : $account->getId(); + + foreach ($this->accRelation as $acc) { + $accId = !\is_int($acc->getRelation()) ? $acc->getRelation()->getId() : $acc->getRelation(); + + if ($accId === $accountId && $acc->getDuty() === DutyType::CC) { + return; + } + } + + $this->accRelation[] = new AccountRelation($account, DutyType::CC); } /** @@ -402,14 +667,15 @@ class TaskElement implements \JsonSerializable public function toArray() : array { return [ - 'id' => $this->id, - 'task' => $this->task, - 'createdBy' => $this->createdBy, - 'createdAt' => $this->createdAt, + 'id' => $this->id, + 'task' => $this->task, + 'createdBy' => $this->createdBy, + 'createdAt' => $this->createdAt, 'description' => $this->description, - 'status' => $this->status, - 'forward' => $this->forwarded, - 'due' => isset($this->due) ? $this->due->format('Y-m-d H:i:s') : null, + 'status' => $this->status, + 'to' => $this->getTo(), + 'cc' => $this->getCC(), + 'due' => isset($this->due) ? $this->due->format('Y-m-d H:i:s') : null, ]; } diff --git a/Models/TaskElementMapper.php b/Models/TaskElementMapper.php index 61325eb..ac85bcb 100644 --- a/Models/TaskElementMapper.php +++ b/Models/TaskElementMapper.php @@ -36,15 +36,14 @@ final class TaskElementMapper extends DataMapperAbstract * @since 1.0.0 */ protected static $columns = [ - 'task_element_id' => ['name' => 'task_element_id', 'type' => 'int', 'internal' => 'id'], - 'task_element_desc' => ['name' => 'task_element_desc', 'type' => 'string', 'internal' => 'description'], - 'task_element_desc_raw' => ['name' => 'task_element_desc_raw', 'type' => 'string', 'internal' => 'descriptionRaw'], - 'task_element_status' => ['name' => 'task_element_status', 'type' => 'int', 'internal' => 'status'], - 'task_element_priority' => ['name' => 'task_element_priority', 'type' => 'int', 'internal' => 'priority'], - 'task_element_due' => ['name' => 'task_element_due', 'type' => 'DateTime', 'internal' => 'due'], - 'task_element_forwarded' => ['name' => 'task_element_forwarded', 'type' => 'int', 'internal' => 'forwarded'], - 'task_element_task' => ['name' => 'task_element_task', 'type' => 'int', 'internal' => 'task'], - 'task_element_created_by' => ['name' => 'task_element_created_by', 'type' => 'int', 'internal' => 'createdBy'], + 'task_element_id' => ['name' => 'task_element_id', 'type' => 'int', 'internal' => 'id'], + 'task_element_desc' => ['name' => 'task_element_desc', 'type' => 'string', 'internal' => 'description'], + 'task_element_desc_raw' => ['name' => 'task_element_desc_raw', 'type' => 'string', 'internal' => 'descriptionRaw'], + 'task_element_status' => ['name' => 'task_element_status', 'type' => 'int', 'internal' => 'status'], + 'task_element_priority' => ['name' => 'task_element_priority', 'type' => 'int', 'internal' => 'priority'], + 'task_element_due' => ['name' => 'task_element_due', 'type' => 'DateTime', 'internal' => 'due'], + 'task_element_task' => ['name' => 'task_element_task', 'type' => 'int', 'internal' => 'task'], + 'task_element_created_by' => ['name' => 'task_element_created_by', 'type' => 'int', 'internal' => 'createdBy'], 'task_element_created_at' => ['name' => 'task_element_created_at', 'type' => 'DateTime', 'internal' => 'createdAt'], ]; @@ -61,6 +60,18 @@ final class TaskElementMapper extends DataMapperAbstract 'dst' => 'task_element_media_src', 'src' => 'task_element_media_dst', ], + 'accRelation' => [ + 'mapper' => AccountRelationMapper::class, + 'table' => 'task_account', + 'dst' => 'task_account_task_element', + 'src' => null, + ], + 'grpRelation' => [ + 'mapper' => GroupRelationMapper::class, + 'table' => 'task_group', + 'dst' => 'task_group_task_element', + 'src' => null, + ], ]; /** @@ -73,11 +84,7 @@ final class TaskElementMapper extends DataMapperAbstract 'createdBy' => [ 'mapper' => AccountMapper::class, 'src' => 'task_element_created_by', - ], - 'forwarded' => [ - 'mapper' => AccountMapper::class, - 'src' => 'task_element_forwarded', - ], + ] ]; /** diff --git a/Models/TaskMapper.php b/Models/TaskMapper.php index 5fbf692..26959b5 100644 --- a/Models/TaskMapper.php +++ b/Models/TaskMapper.php @@ -38,19 +38,20 @@ final class TaskMapper extends DataMapperAbstract * @since 1.0.0 */ protected static $columns = [ - 'task_id' => ['name' => 'task_id', 'type' => 'int', 'internal' => 'id'], - 'task_title' => ['name' => 'task_title', 'type' => 'string', 'internal' => 'title'], - 'task_desc' => ['name' => 'task_desc', 'type' => 'string', 'internal' => 'description'], - 'task_desc_raw' => ['name' => 'task_desc_raw', 'type' => 'string', 'internal' => 'descriptionRaw'], - 'task_type' => ['name' => 'task_type', 'type' => 'int', 'internal' => 'type'], - 'task_status' => ['name' => 'task_status', 'type' => 'int', 'internal' => 'status'], - 'task_closable' => ['name' => 'task_closable', 'type' => 'bool', 'internal' => 'isClosable'], - 'task_priority' => ['name' => 'task_priority', 'type' => 'int', 'internal' => 'priority'], - 'task_due' => ['name' => 'task_due', 'type' => 'DateTime', 'internal' => 'due'], - 'task_done' => ['name' => 'task_done', 'type' => 'DateTime', 'internal' => 'done'], - 'task_schedule' => ['name' => 'task_schedule', 'type' => 'int', 'internal' => 'schedule'], - 'task_start' => ['name' => 'task_start', 'type' => 'DateTime', 'internal' => 'start'], - 'task_created_by' => ['name' => 'task_created_by', 'type' => 'int', 'internal' => 'createdBy'], + 'task_id' => ['name' => 'task_id', 'type' => 'int', 'internal' => 'id'], + 'task_title' => ['name' => 'task_title', 'type' => 'string', 'internal' => 'title'], + 'task_desc' => ['name' => 'task_desc', 'type' => 'string', 'internal' => 'description'], + 'task_desc_raw' => ['name' => 'task_desc_raw', 'type' => 'string', 'internal' => 'descriptionRaw'], + 'task_type' => ['name' => 'task_type', 'type' => 'int', 'internal' => 'type'], + 'task_status' => ['name' => 'task_status', 'type' => 'int', 'internal' => 'status'], + 'task_closable' => ['name' => 'task_closable', 'type' => 'bool', 'internal' => 'isClosable'], + 'task_editable' => ['name' => 'task_editable', 'type' => 'bool', 'internal' => 'isEditable'], + 'task_priority' => ['name' => 'task_priority', 'type' => 'int', 'internal' => 'priority'], + 'task_due' => ['name' => 'task_due', 'type' => 'DateTime', 'internal' => 'due'], + 'task_done' => ['name' => 'task_done', 'type' => 'DateTime', 'internal' => 'done'], + 'task_schedule' => ['name' => 'task_schedule', 'type' => 'int', 'internal' => 'schedule'], + 'task_start' => ['name' => 'task_start', 'type' => 'DateTime', 'internal' => 'start'], + 'task_created_by' => ['name' => 'task_created_by', 'type' => 'int', 'internal' => 'createdBy'], 'task_created_at' => ['name' => 'task_created_at', 'type' => 'DateTime', 'internal' => 'createdAt'], ]; @@ -73,12 +74,6 @@ final class TaskMapper extends DataMapperAbstract 'dst' => 'task_media_src', 'src' => 'task_media_dst', ], - 'acc' => [ - 'mapper' => AccountMapper::class, - 'table' => 'task_account', - 'dst' => 'task_account_account', - 'src' => 'task_account_task', - ], ]; /** @@ -149,41 +144,6 @@ final class TaskMapper extends DataMapperAbstract return self::getAllByQuery($query); } - /** - * Get tasks related to user - * - * @param int $user User - * @param int $limit Result limit - * - * @return array - * - * @since 1.0.0 - */ - public static function getRelatedToAccount(int $user, int $limit = 25) : array - { - $query = self::getQuery(); - - $whereClause1 = new Builder(self::$db); - $whereClause1->prefix(self::$db->getPrefix()) - ->select(TaskElementMapper::getTable() . '.task_element_task') - ->distinct() - ->from(TaskElementMapper::getTable()) - ->where(TaskElementMapper::getTable() . '.task_element_created_by', '=', $user) - ->orWhere(TaskElementMapper::getTable() . '.task_element_forwarded', '=', $user); - - $whereClause2 = new Builder(self::$db); - $whereClause2->prefix(self::$db->getPrefix()) - ->select(self::$table . '.' . self::$primaryField) - ->from(self::$table) - ->where(self::$table . '.task_created_by', '=', $user); - - $query->where(self::$table . '.' . self::$primaryField, 'in', $whereClause1) - ->orWhere(self::$table. '.' . self::$primaryField, 'in', $whereClause2) - ->limit($limit); - - return self::getAllByQuery($query); - } - /** * Count unread task * @@ -202,7 +162,7 @@ final class TaskMapper extends DataMapperAbstract ->count() ->from(self::$table) ->where(self::$table . '.task_created_by', '=', $user) - ->where(self::$table . '.task_status', '=', TaskStatus::OPEN, 'and'); + ->andWhere(self::$table . '.task_status', '=', TaskStatus::OPEN); $sth = self::$db->con->prepare($query->toSql()); $sth->execute(); diff --git a/Theme/Backend/task-single.tpl.php b/Theme/Backend/task-single.tpl.php index 2b0b64b..db84993 100644 --- a/Theme/Backend/task-single.tpl.php +++ b/Theme/Backend/task-single.tpl.php @@ -13,6 +13,8 @@ use \Modules\Tasks\Models\TaskPriority; use \Modules\Tasks\Models\TaskStatus; +use \Modules\Admin\Models\Account; +use \Modules\Admin\Models\Group; /** * @var \phpOMS\Views\View $this @@ -22,7 +24,6 @@ $task = $this->getData('task'); $taskMedia = $task->getMedia(); $elements = $task->getTaskElements(); $cElements = \count($elements); -$forwarded = $task->getCreatedBy()->getId(); $color = $this->getStatus($task->getStatus()); echo $this->getData('nav')->render(); ?> @@ -86,13 +87,20 @@ echo $this->getData('nav')->render(); ?> $element) : $c++; $color = $this->getStatus($element->getStatus()); ?> - 1 && $element->getForwarded() !== 0 && $forwarded->getId() !== $element->getCreatedBy()->getId()) : ?> + getTo(); if ($c > 1 && \count($tos) > 1) : ?>
- Forwarded printHtml($element->getForwarded()->getName1()); ?> + Forwarded + + + printHtml($to->getRelation()->getName1()); ?> + + printHtml($to->getRelation()->getName()); ?> + +
- getForwarded(); ?> +
printHtml($element->getCreatedBy()->getName1()); ?> printHtml($element->getCreatedAt()->format('Y-m-d H:i')); ?>