1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace luya; |
4
|
|
|
|
5
|
|
|
use Yii; |
6
|
|
|
use luya\tag\TagMarkdownParser; |
7
|
|
|
use yii\base\BaseObject; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* TagParser allows you to inject Tags and parse them. |
11
|
|
|
* |
12
|
|
|
* This is an additional concept to markdown, where you can inject your custom tags to parse. All tags must be an instance |
13
|
|
|
* of `luya\tag\BaseTag` and implement the `parse($value, $sub)` method in order to convert the input to your tag. |
14
|
|
|
* |
15
|
|
|
* Read more in the Guide [[concept-tags.md]]. |
16
|
|
|
* |
17
|
|
|
* The identifier of the tag is not related to your tag, so you can configure the same tag as different names with multiple |
18
|
|
|
* purposes. |
19
|
|
|
* |
20
|
|
|
* To inject a created tag just use: |
21
|
|
|
* |
22
|
|
|
* ```php |
23
|
|
|
* TagParser::inject('tagname', ['class' => 'path\to\TagClass']); |
24
|
|
|
* ``` |
25
|
|
|
* |
26
|
|
|
* To parse text with or without markdown use: |
27
|
|
|
* |
28
|
|
|
* ```php |
29
|
|
|
* TagParser::convert('Hello tagname[value](sub)'); |
30
|
|
|
* TagParser::convertWithMarkdown('**Hello** tagname[value](sub)'); |
31
|
|
|
* ``` |
32
|
|
|
* |
33
|
|
|
* @author Basil Suter <[email protected]> |
34
|
|
|
* @since 1.0.0 |
35
|
|
|
*/ |
36
|
|
|
class TagParser extends BaseObject |
37
|
|
|
{ |
38
|
|
|
/** |
39
|
|
|
* @var string Base regular expression to determine function, values and value-sub informations. |
40
|
|
|
* @see https://regex101.com/r/hP9nJ1/1 - Online Regex tester |
41
|
|
|
*/ |
42
|
|
|
const REGEX = '/(?<function>[a-z]+)\[(?<value>.*?)\]((?<!\\\\)\((?<sub>.*?)(?<!\\\\)\))?/mi'; |
43
|
|
|
|
44
|
|
|
private $tags = [ |
45
|
|
|
'mail' => ['class' => 'luya\tag\tags\MailTag'], |
46
|
|
|
'tel' => ['class' => 'luya\tag\tags\TelTag'], |
47
|
|
|
'link' => ['class' => 'luya\tag\tags\LinkTag'], |
48
|
|
|
]; |
49
|
|
|
|
50
|
|
|
private static $_instance; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Inject a new tag with a given name and a configurable array config. |
54
|
|
|
* |
55
|
|
|
* @param string $name The name of the tag on what the tag should be found. Must be [a-z] chars. |
56
|
|
|
* @param string|array $config The configurable object context can be either a string with a class or a configurable array base on {{yii\base\BaseObject}} concept. |
57
|
|
|
*/ |
58
|
|
|
public static function inject($name, $config) |
59
|
|
|
{ |
60
|
|
|
self::getInstance()->addTag($name, $config); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Convert the CMS-Tags into HTML-Tags. |
65
|
|
|
* |
66
|
|
|
* @param string $text The content where the CMS-Tags should be found and convert into Html-Tags. |
67
|
|
|
* @return string The converted output of $text. |
68
|
|
|
*/ |
69
|
|
|
public static function convert($text) |
70
|
|
|
{ |
71
|
|
|
return self::getInstance()->processText($text); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
/** |
75
|
|
|
* Convert the CMS-Tags into HTMl-Tags and additional convert GFM Markdown into Html as well. The main purpose |
76
|
|
|
* of this method to fix the conflict between markdown and tag parser when using urls. |
77
|
|
|
* |
78
|
|
|
* @param string $text The content where the CMS-Tags should be found and convert into Html-Tags and Markdown Tags. |
79
|
|
|
* @return string the Converted output of $text. |
80
|
|
|
*/ |
81
|
|
|
public static function convertWithMarkdown($text) |
82
|
|
|
{ |
83
|
|
|
return (new TagMarkdownParser())->parse(static::convert($text)); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Generate the instance for all registered tags. |
88
|
|
|
* |
89
|
|
|
* The main purpose of this method is to return all tag objects in admin context to provide help informations from the tags. |
90
|
|
|
* |
91
|
|
|
* @return \luya\tag\TagInterface |
92
|
|
|
*/ |
93
|
|
|
public static function getInstantiatedTagObjects() |
94
|
|
|
{ |
95
|
|
|
$context = self::getInstance(); |
96
|
|
|
foreach ($context->tags as $key => $config) { |
97
|
|
|
$context->instantiatTag($key); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
return $context->tags; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Get the TagParser object, create new if not exists |
105
|
|
|
* |
106
|
|
|
* @return static |
107
|
|
|
*/ |
108
|
|
|
private static function getInstance() |
109
|
|
|
{ |
110
|
|
|
if (self::$_instance === null) { |
111
|
|
|
self::$_instance = new self; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
return self::$_instance; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Internal method to add a tag into the tags array. |
119
|
|
|
*/ |
120
|
|
|
private function addTag($identifier, $tagObjectConfig) |
121
|
|
|
{ |
122
|
|
|
$this->tags[$identifier] = $tagObjectConfig; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Check if the given tag name exists. |
127
|
|
|
* |
128
|
|
|
* @return boolean |
129
|
|
|
*/ |
130
|
|
|
private function hasTag($tag) |
131
|
|
|
{ |
132
|
|
|
return isset($this->tags[$tag]); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Create the tag instance (object) for a given tag name. |
137
|
|
|
*/ |
138
|
|
|
private function instantiatTag($tag) |
139
|
|
|
{ |
140
|
|
|
if (!is_object($this->tags[$tag])) { |
141
|
|
|
$this->tags[$tag] = Yii::createObject($this->tags[$tag]); |
142
|
|
|
Yii::trace('tag parser object generated for:'. $tag, __CLASS__); |
|
|
|
|
143
|
|
|
} |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Parse the given tag with context informations. |
148
|
|
|
* |
149
|
|
|
* @return string Returns the parsed tag value. |
150
|
|
|
*/ |
151
|
|
|
private function parseTag($tag, $context) |
152
|
|
|
{ |
153
|
|
|
// ensure tag is an object |
154
|
|
|
$this->instantiatTag($tag); |
155
|
|
|
// extract context |
156
|
|
|
$value = isset($context['value']) ? $context['value'] : false; |
157
|
|
|
$sub = isset($context['sub']) ? $context['sub'] : false; |
158
|
|
|
// the sub value can contain escaped values, those values must be parsed back into the original state. |
159
|
|
|
if ($sub) { |
160
|
|
|
$sub = str_replace(['\)', '\('], [')', '('], $sub); |
161
|
|
|
} |
162
|
|
|
// run parse method inside the tag object. |
163
|
|
|
return $this->tags[$tag]->parse($value, $sub); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Process a given text. |
168
|
|
|
* |
169
|
|
|
* + This will find all tag based expressions inside the text |
170
|
|
|
* + instantiate the tag if the alias exists. |
171
|
|
|
* + parse the tag and modify the input $text |
172
|
|
|
* |
173
|
|
|
* @param string $text The input text |
174
|
|
|
* @return string The parsed text |
175
|
|
|
*/ |
176
|
|
|
private function processText($text) |
177
|
|
|
{ |
178
|
|
|
// verify if content is a string otherwhise just return the original provided content |
179
|
|
|
if (!is_string($text) || empty($text)) { |
180
|
|
|
return $text; |
181
|
|
|
} |
182
|
|
|
// find all tags based on the REGEX expression |
183
|
|
|
preg_match_all(static::REGEX, $text, $results, PREG_SET_ORDER); |
184
|
|
|
// foreach all the results matches the regex |
185
|
|
|
foreach ($results as $row) { |
186
|
|
|
// When value is empty (can be caused by using `link[]` we have to skip this item. |
187
|
|
|
if (empty($row['value'])) { |
188
|
|
|
continue; |
189
|
|
|
} |
190
|
|
|
// extract tag name from regex |
191
|
|
|
$tag = $row['function']; |
192
|
|
|
if ($this->hasTag($tag)) { |
193
|
|
|
$replace = $this->parseTag($tag, $row); |
194
|
|
|
$text = preg_replace('/'.preg_quote($row[0], '/').'/mi', $replace, $text, 1); |
195
|
|
|
} |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
return $text; |
199
|
|
|
} |
200
|
|
|
} |
201
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.