Completed
Push — master ( fb47ed...8a4ab4 )
by Colin
01:43
created

MentionParser::createWithStringTemplate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
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\Mention;
15
16
use League\CommonMark\Extension\Mention\LinkGenerator\CallbackLinkGenerator;
17
use League\CommonMark\Extension\Mention\LinkGenerator\MentionLinkGeneratorInterface;
18
use League\CommonMark\Extension\Mention\LinkGenerator\StringTemplateLinkGenerator;
19
use League\CommonMark\Parser\Inline\InlineParserInterface;
20
use League\CommonMark\Parser\InlineParserContext;
21
22
final class MentionParser implements InlineParserInterface
23
{
24
    /**
25
     * @var string
26
     *
27
     * @psalm-readonly
28
     */
29
    private $symbol;
30
31
    /**
32
     * @var string
33
     *
34
     * @psalm-readonly
35
     */
36
    private $mentionRegex;
37
38
    /**
39
     * @var MentionLinkGeneratorInterface
40
     *
41
     * @psalm-readonly
42
     */
43
    private $linkGenerator;
44
45 27
    public function __construct(string $symbol, string $mentionRegex, MentionLinkGeneratorInterface $linkGenerator)
46
    {
47 27
        $this->symbol        = $symbol;
48 27
        $this->mentionRegex  = $mentionRegex;
49 27
        $this->linkGenerator = $linkGenerator;
50 27
    }
51
52
    /**
53
     * {@inheritDoc}
54
     */
55 27
    public function getCharacters(): array
56
    {
57 27
        return [$this->symbol];
58
    }
59
60 24
    public function parse(InlineParserContext $inlineContext): bool
61
    {
62 24
        $cursor = $inlineContext->getCursor();
63
64
        // The symbol must not have any other characters immediately prior
65 24
        $previousChar = $cursor->peek(-1);
66 24
        if ($previousChar !== null && $previousChar !== ' ') {
67
            // peek() doesn't modify the cursor, so no need to restore state first
68 6
            return false;
69
        }
70
71
        // Save the cursor state in case we need to rewind and bail
72 21
        $previousState = $cursor->saveState();
73
74
        // Advance past the symbol to keep parsing simpler
75 21
        $cursor->advance();
76
77
        // Parse the handle
78 21
        $handle = $cursor->match($this->mentionRegex);
79 21
        if (empty($handle)) {
80
            // Regex failed to match; this isn't a valid mention
81 6
            $cursor->restoreState($previousState);
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...
82
83 6
            return false;
84
        }
85
86 18
        $link = $this->linkGenerator->generateLink($this->symbol, $handle);
87
88 18
        if ($link === null) {
89 3
            $cursor->restoreState($previousState);
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...
90
91 3
            return false;
92
        }
93
94 15
        $inlineContext->getContainer()->appendChild($link);
95
96 15
        return true;
97
    }
98
99 9
    public static function createWithStringTemplate(string $symbol, string $mentionRegex, string $urlTemplate): MentionParser
100
    {
101 9
        return new self($symbol, $mentionRegex, new StringTemplateLinkGenerator($urlTemplate));
102
    }
103
104 3
    public static function createWithCallback(string $symbol, string $mentionRegex, callable $callback): MentionParser
105
    {
106 3
        return new self($symbol, $mentionRegex, new CallbackLinkGenerator($callback));
107
    }
108
109 3
    public static function createTwitterHandleParser(): MentionParser
110
    {
111 3
        return self::createWithStringTemplate('@', '/^[A-Za-z0-9_]{1,15}(?!\w)/', 'https://twitter.com/%s');
112
    }
113
114 3
    public static function createGitHubHandleParser(): MentionParser
115
    {
116
        // RegEx adapted from https://github.com/shinnn/github-username-regex/blob/master/index.js
117 3
        return self::createWithStringTemplate('@', '/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}(?!\w)/', 'https://github.com/%s');
118
    }
119
120 3
    public static function createGitHubIssueParser(string $project): MentionParser
121
    {
122 3
        return self::createWithStringTemplate('#', '/^\d+/', \sprintf('https://github.com/%s/issues/%%d', $project));
123
    }
124
}
125