Add unit tests and fix templates

This commit is contained in:
Dennis Eichhorn 2019-04-14 19:47:06 +02:00
parent 9805852139
commit 4919a52846
16 changed files with 1037 additions and 201 deletions

View File

@ -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": {

View File

@ -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<string, bool>
* @return array<string, bool> 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<string, bool>
* @return array<string, bool> 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;
}
}

View File

@ -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
*/

View File

@ -0,0 +1,82 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package Modules\Tasks
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace Modules\Tasks\Models;
use Modules\Admin\Models\Account;
/**
* Task relation to account
*
* @package Modules\Tasks
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
class AccountRelation extends RelationAbstract
{
/**
* Relation object
*
* @var int|Account
* @since 1.0.0
*/
private $relation = null;
/**
* Constructor.
*
* @param int|Account $account Account
* @param int $duty Duty type
*
* @since 1.0.0
*/
public function __construct($account = 0, int $duty = DutyType::TO)
{
$this->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();
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package Modules\Tasks
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace Modules\Tasks\Models;
use Modules\Admin\Models\AccountMapper;
use phpOMS\DataStorage\Database\DataMapperAbstract;
/**
* Mapper class.
*
* @package Modules\Tasks
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
final class AccountRelationMapper extends DataMapperAbstract
{
/**
* Columns.
*
* @var array<string, array<string, bool|string>>
* @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<string, array<string, string>>
* @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';
}

31
Models/DutyType.php Normal file
View File

@ -0,0 +1,31 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package Modules\Tasks
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace Modules\Tasks\Models;
use phpOMS\Stdlib\Base\Enum;
/**
* Task forward type enum.
*
* @package Modules\Tasks
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
abstract class DutyType extends Enum
{
public const TO = 1;
public const CC = 2;
}

82
Models/GroupRelation.php Normal file
View File

@ -0,0 +1,82 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package Modules\Tasks
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace Modules\Tasks\Models;
use Modules\Admin\Models\Group;
/**
* Task relation to group
*
* @package Modules\Tasks
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
class GroupRelation extends RelationAbstract
{
/**
* Relation object
*
* @var int|Group
* @since 1.0.0
*/
private $relation = null;
/**
* Constructor.
*
* @param int|Group $group Group
* @param int $duty Duty type
*
* @since 1.0.0
*/
public function __construct($group = 0, int $duty = DutyType::TO)
{
$this->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();
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package Modules\Tasks
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace Modules\Tasks\Models;
use Modules\Admin\Models\GroupMapper;
use phpOMS\DataStorage\Database\DataMapperAbstract;
/**
* Mapper class.
*
* @package Modules\Tasks
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
final class GroupRelationMapper extends DataMapperAbstract
{
/**
* Columns.
*
* @var array<string, array<string, bool|string>>
* @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<string, array<string, string>>
* @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';
}

View File

@ -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
{
}

View File

@ -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
{
}

106
Models/RelationAbstract.php Normal file
View File

@ -0,0 +1,106 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package Modules\Tasks
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace Modules\Tasks\Models;
use Modules\Admin\Models\Account;
use Modules\Admin\Models\Group;
/**
* Task relation to accounts or groups
*
* @package Modules\Tasks
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
abstract class RelationAbstract implements \JsonSerializable
{
/**
* ID.
*
* @var int
* @since 1.0.0
*/
protected $id = 0;
/**
* Duty.
*
* @var int
* @since 1.0.0
*/
protected $duty = DutyType::TO;
/**
* Element id.
*
* @var int
* @since 1.0.0
*/
protected $element = 0;
/**
* Get id.
*
* @return int
*
* @since 1.0.0
*/
public function getId() : int
{
return $this->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();
}

View File

@ -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,
];
}

View File

@ -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<RelationAbstract>
*
* @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<RelationAbstract>
*
* @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,
];
}

View File

@ -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',
],
]
];
/**

View File

@ -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();

View File

@ -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(); ?>
<?php $c = 0;
foreach ($elements as $key => $element) : $c++;
$color = $this->getStatus($element->getStatus()); ?>
<?php if ($c > 1 && $element->getForwarded() !== 0 && $forwarded->getId() !== $element->getCreatedBy()->getId()) : ?>
<?php $tos = $element->getTo(); if ($c > 1 && \count($tos) > 1) : ?>
<section class="box wf-100">
<div class="inner">
Forwarded <?= $this->printHtml($element->getForwarded()->getName1()); ?>
Forwarded
<?php foreach ($toes as $to) : ?>
<?php if ($to instanceof Account) : ?>
<?= $this->printHtml($to->getRelation()->getName1()); ?>
<?php elseif ($to instanceof Group) : ?>
<?= $this->printHtml($to->getRelation()->getName()); ?>
<?php endif; ?>
<?php endforeach; ?>
</div>
</section>
<?php endif; $forwarded = $element->getForwarded(); ?>
<?php endif; ?>
<section class="box wf-100">
<div class="inner pAlignTable">
<div class="vCenterTable wf-100"><?= $this->printHtml($element->getCreatedBy()->getName1()); ?> <?= $this->printHtml($element->getCreatedAt()->format('Y-m-d H:i')); ?></div>