Completed
Push — master ( 7cfa55...f98783 )
by Colin
10:32 queued 09:06
created

InlineParserEngine::processInlines()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
/*
4
 * This file is part of the league/commonmark package.
5
 *
6
 * (c) Colin O'Dell <[email protected]>
7
 *
8
 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
9
 *  - (c) John MacFarlane
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace League\CommonMark;
16
17
use League\CommonMark\Inline\Element\Text;
18
use League\CommonMark\Node\Node;
19
use League\CommonMark\Reference\ReferenceMap;
20
21
class InlineParserEngine
22
{
23
    protected $environment;
24
25 1950
    public function __construct(EnvironmentInterface $environment)
26
    {
27 1950
        $this->environment = $environment;
28 1950
    }
29
30
    /**
31
     * @param Node         $container
32
     * @param ReferenceMap $referenceMap
33
     */
34 1662
    public function parse(Node $container, ReferenceMap $referenceMap)
35
    {
36 1662
        $inlineParserContext = new InlineParserContext($container, $referenceMap);
0 ignored issues
show
Compatibility introduced by
$container of type object<League\CommonMark\Node\Node> is not a sub-type of object<League\CommonMark...\Element\AbstractBlock>. It seems like you assume a child class of the class League\CommonMark\Node\Node to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
37 1662
        while (($character = $inlineParserContext->getCursor()->getCharacter()) !== null) {
38 1659
            if (!$this->parseCharacter($character, $inlineParserContext)) {
39 1542
                $this->addPlainText($character, $container, $inlineParserContext);
40
            }
41
        }
42
43 1662
        $this->processInlines($inlineParserContext);
44
45 1662
        $this->collapseAdjoiningTextElements($inlineParserContext);
46 1662
    }
47
48
    /**
49
     * @param string              $character
50
     * @param InlineParserContext $inlineParserContext
51
     *
52
     * @return bool Whether we successfully parsed a character at that position
53
     */
54 1659
    protected function parseCharacter(string $character, InlineParserContext $inlineParserContext): bool
55
    {
56 1659
        foreach ($this->environment->getInlineParsersForCharacter($character) as $parser) {
57 1239
            if ($parser->parse($inlineParserContext)) {
58 1217
                return true;
59
            }
60
        }
61
62 1542
        return false;
63
    }
64
65
    /**
66
     * @param InlineParserContext $inlineParserContext
67
     */
68 1662
    protected function processInlines(InlineParserContext $inlineParserContext)
69
    {
70 1662
        $delimiterStack = $inlineParserContext->getDelimiterStack();
71
72 1662
        foreach ($this->environment->getInlineProcessors() as $inlineProcessor) {
73 1662
            $inlineProcessor->processInlines($delimiterStack);
74
        }
75
76
        // Remove all delimiters
77 1662
        $delimiterStack->removeAll();
78 1662
    }
79
80
    /**
81
     * @param string              $character
82
     * @param Node                $container
83
     * @param InlineParserContext $inlineParserContext
84
     */
85 1542
    private function addPlainText(string $character, Node $container, InlineParserContext $inlineParserContext)
86
    {
87
        // We reach here if none of the parsers can handle the input
88
        // Attempt to match multiple non-special characters at once
89 1542
        $text = $inlineParserContext->getCursor()->match($this->environment->getInlineParserCharacterRegex());
90
        // This might fail if we're currently at a special character which wasn't parsed; if so, just add that character
91 1542
        if ($text === null) {
92 177
            $inlineParserContext->getCursor()->advance();
93 177
            $text = $character;
94
        }
95
96 1542
        $lastInline = $container->lastChild();
97 1542
        if ($lastInline instanceof Text && !isset($lastInline->data['delim'])) {
98 210
            $lastInline->append($text);
99
        } else {
100 1509
            $container->appendChild(new Text($text));
101
        }
102 1542
    }
103
104 1662
    private function collapseAdjoiningTextElements(InlineParserContext $context)
105
    {
106 1662
        $walker = $context->getContainer()->walker();
107
108 1662
        while (($event = $walker->next()) !== null) {
109 1662
            if ($event->isEntering()) {
110 1662
                $node = $event->getNode();
111 1662
                if ($node instanceof Text) {
112 1599
                    while (($next = $node->next()) && $next instanceof Text) {
113 387
                        $node->append($next->getContent());
114 387
                        $next->detach();
115
                    }
116
                }
117
            }
118
        }
119 1662
    }
120
}
121