wse-1.0.x-dev/modules/wse_task_monitor/src/WorkspaceTask.php
modules/wse_task_monitor/src/WorkspaceTask.php
<?php
declare(strict_types=1);
namespace Drupal\wse_task_monitor;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/**
* Domain model for workspace tasks.
*/
class WorkspaceTask {
/**
* The task ID.
*/
protected string $id;
/**
* The workspace ID.
*/
protected string $workspaceId;
/**
* The handler class.
*/
protected string $handlerClass;
/**
* The task label.
*/
protected string $label;
/**
* The task status.
*/
protected TaskStatus $status;
/**
* The task progress (0-100).
*/
protected int $progress = 0;
/**
* The task message.
*/
protected string $message = '';
/**
* Task metadata.
*/
protected array $metadata = [];
/**
* Task creation timestamp.
*/
protected int $createdAt;
/**
* Task last update timestamp.
*/
protected int $updatedAt;
/**
* Task completion timestamp.
*/
protected ?int $completedAt = NULL;
/**
* Constructs a new WorkspaceTask.
*
* @param string $id
* The task ID.
* @param string $workspaceId
* The workspace ID.
* @param string $handlerClass
* The handler class.
* @param string $label
* The task label.
* @param array $metadata
* Optional metadata.
*/
public function __construct(
string $id,
string $workspaceId,
string $handlerClass,
string $label,
array $metadata = [],
) {
$this->id = $id;
$this->workspaceId = $workspaceId;
$this->handlerClass = $handlerClass;
$this->label = $label;
$this->metadata = $metadata;
$this->status = TaskStatus::Pending;
$this->message = 'Task created';
$this->createdAt = time();
$this->updatedAt = time();
}
/**
* Starts the task.
*
* @param string $message
* Optional start message.
*
* @return $this
*/
public function start(string $message = 'Starting task...'): static {
$this->status = TaskStatus::Running;
$this->message = $message;
$this->progress = 0;
$this->updatedAt = time();
return $this;
}
/**
* Updates task progress.
*
* @param int $progress
* Progress percentage (0-100).
* @param string|null $message
* Optional progress message.
*
* @return $this
*
* @throws \InvalidArgumentException
* If progress is invalid.
*/
public function updateProgress(int $progress, ?string $message = NULL): static {
// Only allow progress updates if task is not finished.
if ($this->status->isFinished()) {
// Silently ignore updates on finished tasks.
return $this;
}
if ($progress < 0 || $progress > 100) {
throw new \InvalidArgumentException('Progress must be between 0 and 100');
}
$this->progress = $progress;
if ($message !== NULL) {
$this->message = $message;
}
$this->updatedAt = time();
// Auto-complete task when progress reaches 100%.
if ($this->progress >= 100 && !$this->isFinished()) {
$this->complete($this->message ?: 'Task completed');
}
return $this;
}
/**
* Completes the task successfully.
*
* @param string|null $message
* Optional completion message.
*
* @return $this
*/
public function complete(?string $message = NULL): static {
$this->status = TaskStatus::Completed;
$this->progress = 100;
$this->message = $message ?? (string) new TranslatableMarkup('Task completed successfully.');
$this->completedAt = time();
$this->updatedAt = time();
return $this;
}
/**
* Fails the task.
*
* @param string $errorMessage
* The error message.
*
* @return $this
*/
public function fail(string $errorMessage): static {
$this->status = TaskStatus::Failed;
$this->message = $errorMessage;
$this->completedAt = time();
$this->updatedAt = time();
return $this;
}
/**
* Cancels the task.
*
* @param string|null $message
* Optional cancellation message.
*
* @return $this
*/
public function cancel(?string $message = NULL): static {
$this->status = TaskStatus::Cancelled;
$this->message = $message ?? 'Task cancelled by user.';
$this->completedAt = time();
$this->updatedAt = time();
return $this;
}
/**
* Checks if the task is finished.
*
* @return bool
* TRUE if the task is in a terminal state.
*/
public function isFinished(): bool {
return $this->status->isFinished();
}
/**
* Gets the task ID.
*/
public function getId(): string {
return $this->id;
}
/**
* Gets the workspace ID.
*
* @return string
* The workspace ID.
*/
public function getWorkspaceId(): string {
return $this->workspaceId;
}
/**
* Gets the handler class.
*
* @return string
* The handler class name.
*/
public function getHandlerClass(): string {
return $this->handlerClass;
}
/**
* Gets the handler instance for this task.
*
* @return \Drupal\wse_task_monitor\WorkspaceTaskMonitorInterface|null
* The handler instance, or NULL if not found.
*/
public function getHandler(): ?WorkspaceTaskMonitorInterface {
try {
// @phpstan-ignore-next-line
$handler = \Drupal::getContainer()->get($this->handlerClass);
return $handler instanceof WorkspaceTaskMonitorInterface ? $handler : NULL;
}
catch (\Exception) {
return NULL;
}
}
/**
* Refreshes progress from the handler.
*
* @return $this
*/
public function refreshProgress(): static {
$handler = $this->getHandler();
if ($handler && $this->getStatus() === TaskStatus::Running) {
$progress_info = $handler->getTaskProgress($this);
if ($progress_info !== NULL) {
// Update runtime progress.
$this->progress = max(0, min(100, $progress_info['progress']));
if (isset($progress_info['message'])) {
$this->message = $progress_info['message'];
}
// Auto-complete task when progress reaches 100%.
if ($this->progress >= 100 && !$this->isFinished()) {
$this->complete($this->message ?: 'Task completed');
}
}
}
return $this;
}
/**
* Gets the task label.
*
* @return string
* The task label.
*/
public function getLabel(): string {
return $this->label;
}
/**
* Gets the task status.
*
* @return \Drupal\wse_task_monitor\TaskStatus
* The task status.
*/
public function getStatus(): TaskStatus {
return $this->status;
}
/**
* Gets the task progress.
*
* @return int
* Progress percentage (0-100).
*/
public function getProgress(): int {
return $this->progress;
}
/**
* Gets the task message.
*
* @return string
* The task message.
*/
public function getMessage(): string {
return $this->message;
}
/**
* Gets the task metadata.
*
* @return array
* The task metadata array.
*/
public function getMetadata(): array {
return $this->metadata;
}
/**
* Gets a specific metadata value.
*
* @param string $key
* The metadata key.
* @param mixed $default
* Default value if key doesn't exist.
*
* @return mixed
* The metadata value.
*/
public function getMetadataValue(string $key, mixed $default = NULL): mixed {
return $this->metadata[$key] ?? $default;
}
/**
* Gets the creation timestamp.
*
* @return int
* The creation timestamp.
*/
public function getCreatedAt(): int {
return $this->createdAt;
}
}
