Completed
Branch wip/litedown (e234a3)
by Josh
31:46 queued 18:30
created

Links   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 4
dl 0
loc 119
ccs 64
cts 64
cp 1
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A parse() 0 11 3
A addLinkTag() 0 14 2
A getLabels() 0 16 2
A parseInlineLinks() 0 18 2
B parseReferenceLinks() 0 24 5
1
<?php
2
3
/**
4
* @package   s9e\TextFormatter
5
* @copyright Copyright (c) 2010-2017 The s9e Authors
6
* @license   http://www.opensource.org/licenses/mit-license.php The MIT License
7
*/
8
namespace s9e\TextFormatter\Plugins\Litedown\Parser\Passes;
9
10
use s9e\TextFormatter\Plugins\Litedown\Parser\LinkAttributesSetter;
11
12
class Links extends AbstractPass
13
{
14
	use LinkAttributesSetter;
15
16
	/**
17
	* {@inheritdoc}
18
	*/
19 263
	public function parse()
20
	{
21 263
		if ($this->text->indexOf('](') !== false)
22 263
		{
23 32
			$this->parseInlineLinks();
24 32
		}
25 263
		if ($this->text->hasReferences)
26 263
		{
27 26
			$this->parseReferenceLinks();
28 26
		}
29 263
	}
30
31
	/**
32
	* Add an image tag for given text span
33
	*
34
	* @param  integer $startPos Start tag position
35
	* @param  integer $endPos   End tag position
36
	* @param  integer $endLen   End tag length
37
	* @param  string  $linkInfo    URL optionally followed by space and a title
38
	* @return void
39
	*/
40 57
	protected function addLinkTag($startPos, $endPos, $endLen, $linkInfo)
41
	{
42
		// Give the link a slightly worse priority if this is a implicit reference and a slightly
43
		// better priority if it's an explicit reference or an inline link or to give it precedence
44
		// over possible BBCodes such as [b](https://en.wikipedia.org/wiki/B)
45 57
		$priority = ($endLen === 1) ? 1 : -1;
46
47 57
		$tag = $this->parser->addTagPair('URL', $startPos, 1, $endPos, $endLen, $priority);
48 57
		$this->setLinkAttributes($tag, $linkInfo, 'url');
49
50
		// Overwrite the markup without touching the link's text
51 57
		$this->text->overwrite($startPos, 1);
52 57
		$this->text->overwrite($endPos,   $endLen);
53 57
	}
54
55
	/**
56
	* Capture and return labels used in current text
57
	*
58
	* @return array Labels' text position as keys, lowercased text content as values
59
	*/
60 26
	protected function getLabels()
61
	{
62 26
		preg_match_all(
63 26
			'/\\[((?:[^\\x17[\\]]|\\[[^\\x17[\\]]*\\])*)\\]/',
64 26
			$this->text,
65 26
			$matches,
66
			PREG_OFFSET_CAPTURE
67 26
		);
68 26
		$labels = [];
69 26
		foreach ($matches[1] as $m)
70
		{
71 26
			$labels[$m[1] - 1] = strtolower($m[0]);
72 26
		}
73
74 26
		return $labels;
75
	}
76
77
	/**
78
	* Parse inline links markup
79
	*
80
	* @return void
81
	*/
82 32
	protected function parseInlineLinks()
83
	{
84 32
		preg_match_all(
85 32
			'/\\[(?:[^\\x17[\\]]|\\[[^\\x17[\\]]*\\])*\\]\\(( *(?:[^\\x17\\s()]|\\([^\\x17\\s()]*\\))*(?=[ )]) *(?:"[^\\x17]*?"|\'[^\\x17]*?\'|\\([^\\x17)]*\\))? *)\\)/',
86 32
			$this->text,
87 32
			$matches,
88 32
			PREG_OFFSET_CAPTURE | PREG_SET_ORDER
89 32
		);
90 32
		foreach ($matches as $m)
91
		{
92 32
			$linkInfo = $m[1][0];
93 32
			$startPos = $m[0][1];
94 32
			$endLen   = 3 + strlen($linkInfo);
95 32
			$endPos   = $startPos + strlen($m[0][0]) - $endLen;
96
97 32
			$this->addLinkTag($startPos, $endPos, $endLen, $linkInfo);
98 32
		}
99 32
	}
100
101
	/**
102
	* Parse reference links markup
103
	*
104
	* @return void
105
	*/
106 26
	protected function parseReferenceLinks()
107
	{
108 26
		$labels = $this->getLabels();
109 26
		foreach ($labels as $startPos => $id)
110
		{
111 26
			$labelPos = $startPos + 2 + strlen($id);
112 26
			$endPos   = $labelPos - 1;
113 26
			$endLen   = 1;
114
115 26
			if ($this->text->charAt($labelPos) === ' ')
116 26
			{
117 8
				++$labelPos;
118 8
			}
119 26
			if (isset($labels[$labelPos], $this->text->linkReferences[$labels[$labelPos]]))
120 26
			{
121 10
				$id     = $labels[$labelPos];
122 10
				$endLen = $labelPos + 2 + strlen($id) - $endPos;
123 10
			}
124 26
			if (isset($this->text->linkReferences[$id]))
125 26
			{
126 26
				$this->addLinkTag($startPos, $endPos, $endLen, $this->text->linkReferences[$id]);
127 26
			}
128 26
		}
129
	}
130
}