Passed
Push — 2.0 ( b7ed7b...934f6b )
by Colin
35:11 queued 31:18
created

HeadingPermalinkProcessor::setEnvironment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the league/commonmark package.
7
 *
8
 * (c) Colin O'Dell <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace League\CommonMark\Extension\HeadingPermalink;
15
16
use League\CommonMark\Environment\EnvironmentAwareInterface;
17
use League\CommonMark\Environment\EnvironmentInterface;
18
use League\CommonMark\Event\DocumentParsedEvent;
19
use League\CommonMark\Extension\CommonMark\Node\Block\Heading;
20
use League\CommonMark\Node\RawMarkupContainerInterface;
21
use League\CommonMark\Node\StringContainerHelper;
22
use League\CommonMark\Normalizer\TextNormalizerInterface;
23
use League\Config\ConfigurationInterface;
24
25
/**
26
 * Searches the Document for Heading elements and adds HeadingPermalinks to each one
27
 */
28
final class HeadingPermalinkProcessor implements EnvironmentAwareInterface
29
{
30
    public const INSERT_BEFORE = 'before';
31
    public const INSERT_AFTER  = 'after';
32
33
    /** @psalm-readonly-allow-private-mutation */
34
    private TextNormalizerInterface $slugNormalizer;
35
36
    /** @psalm-readonly-allow-private-mutation */
37
    private ConfigurationInterface $config;
38
39 135
    public function setEnvironment(EnvironmentInterface $environment): void
40
    {
41 135
        $this->config         = $environment->getConfiguration();
42 135
        $this->slugNormalizer = $environment->getSlugNormalizer();
43 132
    }
44
45 132
    public function __invoke(DocumentParsedEvent $e): void
46
    {
47 132
        $min = (int) $this->config->get('heading_permalink/min_heading_level');
48 132
        $max = (int) $this->config->get('heading_permalink/max_heading_level');
49
50 132
        $slugLength = (int) $this->config->get('slug_normalizer/max_length');
51
52 132
        $walker = $e->getDocument()->walker();
53
54 132
        while ($event = $walker->next()) {
55 132
            $node = $event->getNode();
56 132
            if ($node instanceof Heading && $event->isEntering() && $node->getLevel() >= $min && $node->getLevel() <= $max) {
57 126
                $this->addHeadingLink($node, $slugLength);
58
            }
59
        }
60 132
    }
61
62 126
    private function addHeadingLink(Heading $heading, int $slugLength): void
63
    {
64 126
        $text = StringContainerHelper::getChildText($heading, [RawMarkupContainerInterface::class]);
65 126
        $slug = $this->slugNormalizer->normalize($text, [
66 126
            'node' => $heading,
67 126
            'length' => $slugLength,
68
        ]);
69
70 126
        $headingLinkAnchor = new HeadingPermalink($slug);
71
72 126
        switch ($this->config->get('heading_permalink/insert')) {
73 126
            case self::INSERT_BEFORE:
74 117
                $heading->prependChild($headingLinkAnchor);
75
76 117
                return;
77 9
            case self::INSERT_AFTER:
78 9
                $heading->appendChild($headingLinkAnchor);
79
80 9
                return;
81
            default:
82
                throw new \RuntimeException("Invalid configuration value for heading_permalink/insert; expected 'before' or 'after'");
83
        }
84
    }
85
}
86