reviewer-1.2.x-dev/src/Reviewer/Checklist/ChecklistBase.php
src/Reviewer/Checklist/ChecklistBase.php
<?php
declare(strict_types=1);
namespace Drupal\reviewer\Reviewer\Checklist;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\reviewer\Attribute\Checklist as ChecklistAttribute;
use Drupal\reviewer\Exception\AttributeMissingException;
use Drupal\reviewer\Reviewer\Action;
use Drupal\reviewer\Reviewer\Result\CollectionResultInterface;
use Drupal\reviewer\Reviewer\Result\ResultFactoryInterface;
use Drupal\reviewer\Reviewer\Review\ReviewInterface;
use Drupal\reviewer\Reviewer\Status\Status;
use Drupal\reviewer\Reviewer\Task\TaskFactoryInterface;
/**
* Provides a base class for checklists that all checklists must extend.
*
* Checklists are logical collections of tasks which can be re-used across
* multiple reviews. A checklist must contain at least one task. For example, a
* checklist containing tasks that are related to form widget displays, such as
* ensuring the fields widgets used and their settings. You could re-use this
* checklist on multiple reviews targeting different entity types, like nodes,
* taxonomy terms, and paragraphs.
*
* Create checklists in the \Drupal\my_module\Plugin\reviewer\Checklist
* namespace. Checklist classes must have the
* \Drupal\reviewer\Attribute\Checklist attribute.
*
* Do not override this class's methods in children. Checklists are
* instantiated and run internally by reviewer.
*
* Here is an example of a checklist which contains multiple tasks:
*
* @code
* #[Checklist(
* id: 'example',
* tasks: [
* ExampleTaskOne::class,
* ExampleTaskTwo::class,
* ],
* )]
* final class Example extends ChecklistBase {}
* @endcode
*
* @see \Drupal\reviewer\Attribute\Checklist
* @see \Drupal\reviewer\Reviewer\Result\ResultInterface
* @see \Drupal\reviewer\Reviewer\Result\CollectionResultInterface
*/
abstract class ChecklistBase implements ChecklistInterface {
private readonly ChecklistAttribute $attribute;
private CollectionResultInterface $results;
private ReviewInterface $review;
/**
* Tasks.
*
* @var \Drupal\reviewer\Reviewer\Task\TaskInterface[]
*/
private array $tasks = [];
// phpcs:ignore Drupal.Commenting.FunctionComment.Missing
public function __construct(
private readonly ResultFactoryInterface $resultFactory,
private readonly TaskFactoryInterface $taskFactory,
) {
$reflection = new \ReflectionClass($this);
$attributes = $reflection->getAttributes(ChecklistAttribute::class);
$checklist_attribute = reset($attributes);
if (!$checklist_attribute) {
throw new AttributeMissingException(ChecklistAttribute::class, $this::class);
}
$this->attribute = $checklist_attribute->newInstance();
$this->results = $this->resultFactory->createCollection($this->attribute->getId());
}
/**
* {@inheritdoc}
*/
public function run(Action $action): ChecklistInterface {
foreach ($this->getTasks() as $task) {
$task->run($action);
$this->results->add($task->getResults());
}
return $this;
}
/**
* {@inheritdoc}
*/
public function getId(): string {
return $this->attribute->getId();
}
/**
* {@inheritdoc}
*/
public function resultId(): string {
return "{$this->review->resultId()}.{$this->getId()}";
}
/**
* {@inheritdoc}
*/
public function getConfigEntity(): ConfigEntityInterface|null {
return $this->review->getConfigEntity();
}
/**
* {@inheritdoc}
*/
public function setReview(ReviewInterface $review): ChecklistInterface {
$this->review = $review;
return $this;
}
/**
* {@inheritdoc}
*/
public function getTasks(): array {
if (!$this->tasks) {
$this->tasks = array_map(
fn(string $task) => $this->taskFactory->create($task),
$this->attribute->getTasks(),
);
foreach ($this->tasks as $task) {
$task->setChecklist($this);
}
}
return $this->tasks;
}
/**
* {@inheritdoc}
*/
public function getStatus(): Status {
return $this->getResults()->getStatus();
}
/**
* {@inheritdoc}
*/
public function getResults(): CollectionResultInterface {
return $this->results;
}
/**
* {@inheritdoc}
*/
public function getIgnored(): array {
return $this->review->getIgnored();
}
}
