packages/requirements/src/Config/Markdown/QuotationBlocks.php
1<?php
2
3declare(strict_types=1);
4
5namespace Requirements\Config\Markdown;
6
7use League\CommonMark\Extension\CommonMark\Node\Block\BlockQuote;
8use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
9use League\CommonMark\Node\Block\Paragraph;
10use League\CommonMark\Node\Node;
11use Requirements\Input\InvalidInputException;
12use stdClass;
13
14/**
15 * Reads the evidence quotations that follow a card's statement.
16 *
17 * Each block quotation may be followed by a paragraph holding only its source link.
18 */
19final class QuotationBlocks
20{
21 /**
22 * @param Presentation $presentation Receives the citation link of each quotation
23 * @param Citation|null $source Resolves citations against the definition's source
24 */
25 public function __construct(private readonly Presentation $presentation, private readonly ?Citation $source)
26 {
27 }
28
29 /**
30 * Reads the leading quotations of the remaining card blocks.
31 *
32 * @param list<Node> $blocks The blocks after the statement
33 * @param string $file The definition file
34 * @param string $id The item ID
35 *
36 * @return array{list<stdClass>, list<Node>} The evidence entries and the blocks after them
37 *
38 * @throws InvalidInputException When a quotation lacks a source, a selector or text, or its citation disagrees
39 */
40 public function read(array $blocks, string $file, string $id): array
41 {
42 $evidence = [];
43 while (isset($blocks[0]) && $blocks[0] instanceof BlockQuote) {
44 $quote = $blocks[0];
45 array_shift($blocks);
46 $attribution = null;
47 if (isset($blocks[0]) && $blocks[0] instanceof Paragraph && $blocks[0]->firstChild() instanceof Link && $blocks[0]->firstChild()->next() === null) {
48 $attribution = Nodes::link($blocks[0]);
49 array_shift($blocks);
50 }
51 $reader = new Quotation();
52 try {
53 $evidence[] = $reader->read($quote, $this->source, $attribution);
54 } catch (InvalidInputException $error) {
55 throw new InvalidInputException("$file: $id: " . $error->getMessage(), 0, $error);
56 }
57 $this->presentation->citations[$id][] = $reader->link;
58 }
59 return [$evidence, $blocks];
60 }
61}
62