Task.php

Code Hygiene Score: 60

Issues 1

Zeile Typ Beschreibung
- complexity Datei hat 304 Zeilen (max: 300)

Dependencies 4

Klassen 1

Funktionen 30

Verwendet von 6

Versionen 28

Code

<?php

declare(strict_types=1);

namespace Domain\Entity;

// @responsibility: Task-Entität - Rich Domain Model mit Business-Logik

use Domain\Traits\TimestampsTrait;
use Domain\ValueObject\TaskStatus;
use Domain\ValueObject\TaskType;

class Task
{
    use TimestampsTrait;
    private ?int $id = null;
    private string $uuid;
    private string $title;
    private ?string $description = null;
    private TaskType $type;
    private TaskStatus $status;
    private string $createdBy;
    private string $createdByType = 'human';
    private ?int $parentTaskId = null;
    private ?\DateTimeImmutable $dueDate = null;
    /** @var array<string, mixed> */
    private array $metadata = [];

    private function __construct()
    {
        $this->uuid = $this->generateUuid();
        $this->status = TaskStatus::PENDING;
        $this->type = TaskType::HUMAN_TASK;
        $this->createdAt = new \DateTimeImmutable();
        $this->updatedAt = new \DateTimeImmutable();
    }

    public static function create(
        string $title,
        string $createdBy,
        ?string $description = null,
        ?TaskType $type = null,
        ?int $parentTaskId = null,
        ?\DateTimeImmutable $dueDate = null
    ): self {
        $task = new self();
        $task->title = $title;
        $task->createdBy = $createdBy;
        $task->description = $description;

        if ($type !== null) {
            $task->type = $type;
        }

        if ($parentTaskId !== null) {
            $task->parentTaskId = $parentTaskId;
        }

        if ($dueDate !== null) {
            $task->dueDate = $dueDate;
        }

        return $task;
    }

    private function generateUuid(): string
    {
        return sprintf(
            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x0fff) | 0x4000,
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff)
        );
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getUuid(): string
    {
        return $this->uuid;
    }

    public function getTitle(): string
    {
        return $this->title;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function getType(): TaskType
    {
        return $this->type;
    }

    public function getStatus(): TaskStatus
    {
        return $this->status;
    }

    public function getCreatedBy(): string
    {
        return $this->createdBy;
    }

    public function getCreatedByType(): string
    {
        return $this->createdByType;
    }

    public function getParentTaskId(): ?int
    {
        return $this->parentTaskId;
    }

    public function getDueDate(): ?\DateTimeImmutable
    {
        return $this->dueDate;
    }

    /** @return array<string, mixed> */
    public function getMetadata(): array
    {
        return $this->metadata;
    }

    public function updateDetails(string $title, ?string $description = null): self
    {
        $this->title = $title;
        $this->description = $description;
        $this->touch();

        return $this;
    }

    public function changeType(TaskType $type): self
    {
        $this->type = $type;
        $this->touch();

        return $this;
    }

    public function assignParent(int $parentTaskId): self
    {
        $this->parentTaskId = $parentTaskId;
        $this->touch();

        return $this;
    }

    public function setDueDate(?\DateTimeImmutable $dueDate): self
    {
        $this->dueDate = $dueDate;
        $this->touch();

        return $this;
    }

    /** @param array<string, mixed> $metadata */
    public function updateMetadata(array $metadata): self
    {
        $this->metadata = $metadata;
        $this->touch();

        return $this;
    }

    public function isOverdue(): bool
    {
        return $this->dueDate !== null && !$this->status->isTerminal() && $this->dueDate < new \DateTimeImmutable();
    }

    public function start(): self
    {
        $this->transitionTo(TaskStatus::IN_PROGRESS);

        return $this;
    }

    public function complete(): self
    {
        $this->transitionTo(TaskStatus::COMPLETED);

        return $this;
    }

    public function fail(): self
    {
        $this->transitionTo(TaskStatus::FAILED);

        return $this;
    }

    public function cancel(): self
    {
        $this->transitionTo(TaskStatus::CANCELLED);

        return $this;
    }

    public function retry(): self
    {
        if ($this->status !== TaskStatus::FAILED) {
            throw new \DomainException('Can only retry failed tasks');
        }
        $this->transitionTo(TaskStatus::PENDING);
        $this->completedAt = null;

        return $this;
    }

    private function transitionTo(TaskStatus $newStatus): void
    {
        if (!$this->status->canTransitionTo($newStatus)) {
            throw new \DomainException(sprintf('Cannot transition from %s to %s', $this->status->value, $newStatus->value));
        }
        $this->status = $newStatus;
        $this->touch();
        if ($newStatus->isTerminal()) {
            $this->completedAt = new \DateTimeImmutable();
        }
    }

    public function setId(int $id): self
    {
        $this->id = $id;

        return $this;
    }

    /** @param array<string, mixed> $data */
    public function hydrate(array $data): self
    {
        $this->uuid = $data['uuid'] ?? $this->uuid;
        $this->title = $data['title'] ?? $this->title;
        $this->description = $data['description'] ?? null;
        $this->createdBy = $data['created_by'] ?? $this->createdBy;
        $this->createdByType = $data['created_by_type'] ?? 'human';
        $this->parentTaskId = isset($data['parent_task_id']) ? (int) $data['parent_task_id'] : null;

        if (isset($data['type'])) {
            $this->type = is_string($data['type']) ? TaskType::from($data['type']) : $data['type'];
        }
        if (isset($data['status'])) {
            $this->status = is_string($data['status']) ? TaskStatus::from($data['status']) : $data['status'];
        }
        if (isset($data['due_date'])) {
            $this->dueDate = $this->toDateTime($data['due_date']);
        }
        if (isset($data['created_at'])) {
            $this->createdAt = $this->toDateTime($data['created_at']);
        }
        if (isset($data['updated_at'])) {
            $this->updatedAt = $this->toDateTime($data['updated_at']);
        }
        if (isset($data['completed_at'])) {
            $this->completedAt = $this->toDateTime($data['completed_at']);
        }
        if (isset($data['metadata'])) {
            $this->metadata = is_string($data['metadata']) ? json_decode($data['metadata'], true) ?? [] : $data['metadata'];
        }

        return $this;
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            'id' => $this->id, 'uuid' => $this->uuid, 'title' => $this->title,
            'description' => $this->description, 'type' => $this->type->value,
            'status' => $this->status->value, 'created_by' => $this->createdBy,
            'created_by_type' => $this->createdByType, 'parent_task_id' => $this->parentTaskId,
            'due_date' => $this->dueDate?->format('Y-m-d H:i:s'),
            'created_at' => $this->createdAt->format('Y-m-d H:i:s.u'),
            'updated_at' => $this->updatedAt->format('Y-m-d H:i:s.u'),
            'completed_at' => $this->completedAt?->format('Y-m-d H:i:s.u'),
            'metadata' => $this->metadata,
        ];
    }

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        $task = new self();
        if (isset($data['id'])) {
            $task->setId((int) $data['id']);
        }

        return $task->hydrate($data);
    }
}
← Übersicht Graph