Completed
Push — simplify ( c10a7e )
by Colin
03:25
created

EmphasisParser::determineCanOpenOrClose()   F

Complexity

Conditions 14
Paths 490

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 14

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 27
ccs 20
cts 20
cp 1
rs 3.2003
cc 14
eloc 20
nc 490
nop 4
crap 14

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 (http://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\Inline\Parser;
16
17
use League\CommonMark\Delimiter\Delimiter;
18
use League\CommonMark\Environment;
19
use League\CommonMark\EnvironmentAwareInterface;
20
use League\CommonMark\Inline\Element\Text;
21
use League\CommonMark\InlineParserContext;
22
use League\CommonMark\Util\Configuration;
23
use League\CommonMark\Util\RegexHelper;
24
25
class EmphasisParser extends AbstractInlineParser implements EnvironmentAwareInterface
26
{
27
    protected $config;
28
29 1854
    public function __construct(array $newConfig = [])
30
    {
31 1854
        $this->config = new Configuration([
32 1854
            'use_asterisk'    => true,
33 1854
            'use_underscore'  => true,
34 1854
            'enable_em'       => true,
35 1854
            'enable_strong'   => true,
36 1854
        ]);
37 1854
        $this->config->mergeConfig($newConfig);
38 1854
    }
39
40 1854
    public function setEnvironment(Environment $environment)
41
    {
42 1854
        $this->config->mergeConfig($environment->getConfig());
43 1854
    }
44
45
    /**
46
     * @return string[]
47
     */
48 1854
    public function getCharacters()
49
    {
50 1854
        if (!$this->config->getConfig('enable_em') && !$this->config->getConfig('enable_strong')) {
51
            return [];
52
        }
53
54 1854
        $chars = [];
55 1854
        if ($this->config->getConfig('use_asterisk')) {
56 1854
            $chars[] = '*';
57 1854
        }
58 1854
        if ($this->config->getConfig('use_underscore')) {
59 1854
            $chars[] = '_';
60 1854
        }
61
62 1854
        return $chars;
63
    }
64
65
    /**
66
     * @param InlineParserContext $inlineContext
67
     *
68
     * @return bool
69
     */
70 507
    public function parse(InlineParserContext $inlineContext)
71
    {
72 507
        $character = $inlineContext->getCursor()->getCharacter();
73 507
        if (!in_array($character, $this->getCharacters())) {
74
            return false;
75
        }
76
77 507
        $numDelims = 0;
78
79 507
        $cursor = $inlineContext->getCursor();
80 507
        $charBefore = $cursor->peek(-1);
81 507
        if ($charBefore === null) {
82 345
            $charBefore = "\n";
83 345
        }
84
85 507
        while ($cursor->peek($numDelims) === $character) {
86 507
            ++$numDelims;
87 507
        }
88
89
        // Skip single delims if emphasis is disabled
90 507
        if ($numDelims === 1 && !$this->config->getConfig('enable_em')) {
91
            return false;
92
        }
93
94 507
        $cursor->advanceBy($numDelims);
95
96 507
        $charAfter = $cursor->getCharacter();
97 507
        if ($charAfter === null) {
98 342
            $charAfter = "\n";
99 342
        }
100
101 507
        list($canOpen, $canClose) = $this->determineCanOpenOrClose($charBefore, $charAfter, $character, $numDelims);
102
103 507
        $node = new Text($cursor->getPreviousText(), [
104 507
            'delim'           => true,
105 507
            'emphasis_config' => $this->config,
106 507
        ]);
107 507
        $inlineContext->getContainer()->appendChild($node);
108
109
        // Add entry to stack to this opener
110 507
        $delimiter = new Delimiter($character, $numDelims, $node, $canOpen, $canClose);
111 507
        $inlineContext->getDelimiterStack()->push($delimiter);
112
113 507
        return true;
114
    }
115
116
    /**
117
     * @param string $charBefore
118
     * @param string $charAfter
119
     * @param string $character
120
     * @param int    $numDelims
121
     *
122
     * @return bool[]
123
     */
124 507
    private function determineCanOpenOrClose($charBefore, $charAfter, $character, $numDelims)
125
    {
126 507
        $afterIsWhitespace = preg_match('/\pZ|\s/u', $charAfter);
127 507
        $afterIsPunctuation = preg_match(RegexHelper::REGEX_PUNCTUATION, $charAfter);
128 507
        $beforeIsWhitespace = preg_match('/\pZ|\s/u', $charBefore);
129 507
        $beforeIsPunctuation = preg_match(RegexHelper::REGEX_PUNCTUATION, $charBefore);
130
131 507
        $leftFlanking = $numDelims > 0 && !$afterIsWhitespace &&
132 453
            !($afterIsPunctuation &&
133 453
                !$beforeIsWhitespace &&
134 507
                !$beforeIsPunctuation);
135
136 507
        $rightFlanking = $numDelims > 0 && !$beforeIsWhitespace &&
137 432
            !($beforeIsPunctuation &&
138 432
                !$afterIsWhitespace &&
139 507
                !$afterIsPunctuation);
140
141 507
        if ($character === '_') {
142 204
            $canOpen = $leftFlanking && (!$rightFlanking || $beforeIsPunctuation);
143 204
            $canClose = $rightFlanking && (!$leftFlanking || $afterIsPunctuation);
144 204
        } else {
145 333
            $canOpen = $leftFlanking;
146 333
            $canClose = $rightFlanking;
147
        }
148
149 507
        return [$canOpen, $canClose];
150
    }
151
}
152