Completed
Push — refactor-parsing ( adbb6b...fbe6de )
by Colin
08:21 queued 07:01
created

LinkParserHelper::parseLinkTitle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 4
cts 4
cp 1
rs 9.9666
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\Util;
16
17
use League\CommonMark\Parser\Cursor;
18
19
final class LinkParserHelper
20
{
21
    /**
22
     * Attempt to parse link destination
23
     *
24
     * @param Cursor $cursor
25
     *
26
     * @return null|string The string, or null if no match
27
     */
28 438
    public static function parseLinkDestination(Cursor $cursor): ?string
29
    {
30 438
        if ($res = $cursor->match(RegexHelper::REGEX_LINK_DESTINATION_BRACES)) {
31
            // Chop off surrounding <..>:
32 36
            return UrlEncoder::unescapeAndEncode(
33 36
                RegexHelper::unescape(\substr($res, 1, -1))
34
            );
35
        }
36
37 405
        if ($cursor->getCharacter() === '<') {
38 9
            return null;
39
        }
40
41 396
        $destination = self::manuallyParseLinkDestination($cursor);
42 396
        if ($destination === null) {
43
            return null;
44
        }
45
46 396
        return UrlEncoder::unescapeAndEncode(
47 396
            RegexHelper::unescape($destination)
48
        );
49
    }
50
51 297
    public static function parseLinkLabel(Cursor $cursor): int
52
    {
53 297
        $match = $cursor->match('/^\[(?:[^\\\\\[\]]|\\\\.){0,1000}\]/');
54 297
        if ($match === null) {
55 219
            return 0;
56
        }
57
58 90
        $length = \mb_strlen($match, 'utf-8');
59
60 90
        if ($length > 1001) {
61
            return 0;
62
        }
63
64 90
        return $length;
65
    }
66
67 432
    public static function parsePartialLinkLabel(Cursor $cursor): ?string
68
    {
69 432
        return $cursor->match('/^(?:[^\\\\\[\]]|\\\\.){0,1000}/');
70
    }
71
72
    /**
73
     * Attempt to parse link title (sans quotes)
74
     *
75
     * @param Cursor $cursor
76
     *
77
     * @return null|string The string, or null if no match
78
     */
79 54
    public static function parseLinkTitle(Cursor $cursor): ?string
80
    {
81 54
        if ($title = $cursor->match('/' . RegexHelper::PARTIAL_LINK_TITLE . '/')) {
82
            // Chop off quotes from title and unescape
83 30
            return RegexHelper::unescape(\substr($title, 1, -1));
84
        }
85
86 24
        return null;
87
    }
88
89 111
    public static function parsePartialLinkTitle(Cursor $cursor, string $endDelimiter): ?string
90
    {
91 111
        $endDelimiter = \preg_quote($endDelimiter, '/');
92 111
        $regex = \sprintf('/(%s|[^%s\x00])*(?:%s)?/', RegexHelper::PARTIAL_ESCAPED_CHAR, $endDelimiter, $endDelimiter);
93 111
        if (($partialTitle = $cursor->match($regex)) === null) {
94
            return null;
95
        }
96
97 111
        return RegexHelper::unescape($partialTitle);
98
    }
99
100 396
    private static function manuallyParseLinkDestination(Cursor $cursor): ?string
101
    {
102 396
        $oldPosition = $cursor->getPosition();
103 396
        $oldState = $cursor->saveState();
104
105 396
        $openParens = 0;
106 396
        while (($c = $cursor->getCharacter()) !== null) {
107 396
            if ($c === '\\' && $cursor->peek() !== null && RegexHelper::isEscapable($cursor->peek())) {
108 18
                $cursor->advanceBy(2);
109 396
            } elseif ($c === '(') {
110 15
                $cursor->advanceBy(1);
111 15
                $openParens++;
112 396
            } elseif ($c === ')') {
113 126
                if ($openParens < 1) {
114 123
                    break;
115
                }
116
117 15
                $cursor->advanceBy(1);
118 15
                $openParens--;
119 393
            } elseif (\preg_match(RegexHelper::REGEX_WHITESPACE_CHAR, $c)) {
120 156
                break;
121
            } else {
122 393
                $cursor->advanceBy(1);
123
            }
124
        }
125
126 396
        if ($openParens !== 0) {
127
            return null;
128
        }
129
130 396
        if ($cursor->getPosition() === $oldPosition && $c !== ')') {
131
            return null;
132
        }
133
134 396
        $newPos = $cursor->getPosition();
135 396
        $cursor->restoreState($oldState);
0 ignored issues
show
Unused Code introduced by
The call to the method League\CommonMark\Parser\Cursor::restoreState() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
136
137 396
        $cursor->advanceBy($newPos - $cursor->getPosition());
138
139 396
        return $cursor->getPreviousText();
140
    }
141
}
142