Passed
Push — latest ( 212a66...171a44 )
by Colin
01:50
created

FixOrphanedFootnotesAndRefsListener::exists()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 19
ccs 11
cts 11
cp 1
rs 9.2222
cc 6
nc 5
nop 3
crap 6
1
<?php
2
3
/*
4
 * This file is part of the league/commonmark package.
5
 *
6
 * (c) Colin O'Dell <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace League\CommonMark\Extension\Footnote\Event;
15
16
use League\CommonMark\Event\DocumentParsedEvent;
17
use League\CommonMark\Extension\Footnote\Node\Footnote;
18
use League\CommonMark\Extension\Footnote\Node\FootnoteRef;
19
use League\CommonMark\Node\Block\Document;
20
use League\CommonMark\Node\Inline\Text;
21
use League\CommonMark\Reference\ReferenceableInterface;
22
23
final class FixOrphanedFootnotesAndRefsListener
24
{
25 90
    public function onDocumentParsed(DocumentParsedEvent $event): void
26
    {
27 90
        $document = $event->getDocument();
28 90
        $walker   = $document->walker();
29
30 90
        while ($event = $walker->next()) {
31 90
            if (! $event->isEntering()) {
32 90
                continue;
33
            }
34
35 90
            $node = $event->getNode();
36 90
            if ($node instanceof FootnoteRef && ! $this->exists($document, Footnote::class, $node->getReference()->getLabel())) {
37
                // Found an orphaned FootnoteRef without a corresponding Footnote
38
                // Restore the original footnote ref text
39 9
                $node->replaceWith(new Text(\sprintf('[^%s]', $node->getReference()->getLabel())));
40
            }
41
42
            // phpcs:disable SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed
43 90
            if ($node instanceof Footnote && ! $this->exists($document, FootnoteRef::class, $node->getReference()->getLabel())) {
44
                // Found an orphaned Footnote without a corresponding FootnoteRef
45
                // Remove the footnote
46 9
                $walker->resumeAt($node->next() ?? $node->parent());
47 9
                $node->detach();
48
            }
49
        }
50 90
    }
51
52 81
    private function exists(Document $document, string $type, string $label): bool
53
    {
54 81
        $walker = $document->walker();
55 81
        while ($event = $walker->next()) {
56 81
            if (! $event->isEntering()) {
57 81
                continue;
58
            }
59
60 81
            $node = $event->getNode();
61 81
            if (! ($node instanceof ReferenceableInterface && \get_class($node) === $type)) {
62 81
                continue;
63
            }
64
65 81
            if ($node->getReference()->getLabel() === $label) {
66 81
                return true;
67
            }
68
        }
69
70 18
        return false;
71
    }
72
}
73