Completed
Push — master ( a9232e...f0b987 )
by smiley
02:39
created

BaseModuleAbstract::getInfo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 9
rs 9.6666
cc 2
eloc 5
nc 2
nop 0
1
<?php
2
/**
3
 * Class BaseModuleAbstract
4
 *
5
 * @filesource   BaseModuleAbstract.php
6
 * @created      12.10.2015
7
 * @package      chillerlan\bbcode\Modules
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2015 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\bbcode\Modules;
14
15
use chillerlan\bbcode\{BBCodeException, BBTemp};
16
17
/**
18
 * The base module implements the basic functionality for each module
19
 */
20
abstract class BaseModuleAbstract implements BaseModuleInterface{
21
22
	/**
23
	 * The current bbcode tag
24
	 *
25
	 * @var string
26
	 * @see \chillerlan\bbcode\BBTemp::$tag
27
	 */
28
	protected $tag;
29
30
	/**
31
	 * An array of the bbcode's attributes
32
	 *
33
	 * @var array
34
	 * @see \chillerlan\bbcode\BBTemp::$attributes
35
	 */
36
	protected $attributes;
37
38
	/**
39
	 * The content between the current bbcode tags
40
	 *
41
	 * @var string
42
	 * @see \chillerlan\bbcode\BBTemp::$content
43
	 */
44
	protected $content;
45
46
	/**
47
	 * The current callback depth
48
	 *
49
	 * @var int
50
	 * @see \chillerlan\bbcode\BBTemp::$depth
51
	 */
52
	protected $depth;
53
54
	/**
55
	 * Holds the current base module's EOL token which will replace any newlines
56
	 *
57
	 * @var string
58
	 * @see \chillerlan\bbcode\Modules\ModuleInfo::$eol_token
59
	 */
60
	protected $eol_token = PHP_EOL;
61
62
	/**
63
	 * Holds an array of FQN strings to the current base module's children
64
	 *
65
	 * @var array
66
	 * @see \chillerlan\bbcode\Modules\ModuleInfo::$modules
67
	 */
68
	protected $modules = [];
69
70
	/**
71
	 * An array of tags the module is able to process
72
	 *
73
	 * @var array
74
	 * @see \chillerlan\bbcode\Modules\Tagmap::$tags
75
	 */
76
	protected $tags = [];
77
78
	/**
79
	 * An optional array of tags contained in self::$tags which are marked as "noparse"
80
	 *
81
	 * @var array
82
	 * @see \chillerlan\bbcode\Modules\Tagmap::$noparse_tags
83
	 */
84
	protected $noparse_tags = [];
85
86
	/**
87
	 * An optional array of tags contained in self::$tags which are marked as "single tag"
88
	 *
89
	 * @var array
90
	 * @see \chillerlan\bbcode\Modules\Tagmap::$singletags
91
	 */
92
	protected $singletags = [];
93
94
	/**
95
	 * The parser options
96
	 *
97
	 * @var \chillerlan\bbcode\ParserOptions
98
	 * @see \chillerlan\bbcode\parserOptions::$options
99
	 */
100
	protected $parserOptions;
101
102
	/**
103
	 * Holds the translation class for the current language
104
	 *
105
	 * @var \chillerlan\bbcode\Language\LanguageInterface
106
	 */
107
	protected $languageInterface;
108
109
	/**
110
	 * Sets self::$tag, self::$attributes, self::$content and self::$options
111
	 *
112
	 * @param \chillerlan\bbcode\BBTemp $bbtemp
113
	 *
114
	 * @return $this
115
	 */
116
	public function setBBTemp(BBTemp $bbtemp){
117
		foreach(['tag', 'attributes', 'content', 'parserOptions', 'languageInterface', 'depth'] as $var){
118
			$this->{$var} = $bbtemp->{$var};
119
		}
120
121
		return $this;
122
	}
123
124
	/**
125
	 * Returns a list of the BaseModuleAbstract's modules
126
	 *
127
	 * @return \chillerlan\bbcode\Modules\BaseModuleInfo
128
	 */
129
	public function getInfo():BaseModuleInfo{
130
		$info = new BaseModuleInfo;
131
132
		foreach(['modules', 'eol_token'] as $option){
133
			$info->{$option} = $this->{$option};
134
		}
135
136
		return $info;
137
	}
138
139
	/**
140
	 * Returns an array of tags which the module is able to process
141
	 *
142
	 * @return \chillerlan\bbcode\Modules\Tagmap
143
	 * @see \chillerlan\bbcode\Modules\ModuleInterface
144
	 */
145
	public function getTags():Tagmap{
146
		$tags = new Tagmap;
147
		$tags->tags = $this->tags;
148
		$tags->noparse_tags = $this->noparse_tags;
149
		$tags->singletags = $this->singletags;
150
151
		return $tags;
152
	}
153
154
	/**
155
	 * Checks if the module supports the current tag
156
	 *
157
	 * @return $this
158
	 * @throws \chillerlan\bbcode\BBCodeException
159
	 */
160
	public function checkTag(){
161
		if(!$this->tag || !in_array($this->tag, $this->tags)){
162
			throw new BBCodeException('tag ['.$this->tag.'] not supported.');
163
		}
164
165
		return $this;
166
	}
167
168
	/**
169
	 * Replaces the EOL placeholder in the given string with a custom token
170
	 *
171
	 * @param string $str   haystack
172
	 * @param string $eol   [optional] custom EOL token, default: ''
173
	 * @param int    $count [optional] replace first $count occurences
0 ignored issues
show
Documentation introduced by
Should the type for parameter $count not be null|integer?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
174
	 *
175
	 * @return string
176
	 */
177
	public function eol(string $str, string $eol = '', int $count = null):string{
178
		return str_replace($this->parserOptions->eol_placeholder, $eol, $str, $count);
179
	}
180
181
	/**
182
	 * Clears all EOL placeholders from self::$content with the base modules EOL token
183
	 *
184
	 * @param string $eol [optional] custom EOL token
0 ignored issues
show
Documentation introduced by
Should the type for parameter $eol not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
185
	 *
186
	 * @return $this
187
	 */
188
	public function clearEOL(string $eol = null){
189
		$eol = $eol ?: $this->eol_token;
190
		$this->content = str_replace($this->parserOptions->eol_placeholder, $eol, $this->content);
191
192
		return $this;
193
	}
194
195
	/**
196
	 * Clears all pseudo closing single tag bbcodes like [/br]
197
	 *
198
	 * @return $this
199
	 */
200
	public function clearPseudoClosingTags(){
201
		$this->content = preg_replace('#\[/('.$this->parserOptions->singletags.')]#is', '', $this->content);
202
203
		return $this;
204
	}
205
206
	/**
207
	 * Retrieves an attribute's value by it's name
208
	 *
209
	 * @param string $name     the desired attributes name
210
	 * @param mixed  $default  [optional] a default value in case the attribute isn't set, defaults to false
211
	 *
212
	 * @return mixed the attribute's value in case it exists, otherwise $default
213
	 */
214
	public function getAttribute(string $name, $default = false){
215
		return isset($this->attributes[$name]) && !empty($this->attributes[$name]) ? $this->attributes[$name] : $default;
216
	}
217
218
	/**
219
	 * Retrieves an attribute's value by it's name and checks if it's whitelisted
220
	 *
221
	 * @param string $name      the desired attributes name
222
	 * @param array  $whitelist an array with whitelisted values
223
	 * @param mixed  $default   [optional] a default value in case the attribute isn't set, defaults to false
224
	 *
225
	 * @return mixed boolean if no $default is set, otherwise the attribute's value in case it exists and is whitelisted or $default
226
	 */
227
	public function attributeIn(string $name, array $whitelist, $default = false){
228
		return isset($this->attributes[$name]) && in_array($this->attributes[$name], $whitelist)
229
			? $default !== false ? $this->attributes[$name] : true
230
			: $default;
231
	}
232
233
	/**
234
	 * Checks if an attribute exists and if it exists as key in a whitelist
235
236
	 * @param string $name      the desired attributes name
237
	 * @param array  $whitelist an array with whitelisted key -> value pairs
238
	 * @param mixed  $default   [optional] a default value in case the attribute isn't set, defaults to false
239
	 *
240
	 * @return mixed boolean if no $default is set, otherwise the whitelist value to the given key in case it exists or $default
241
	 */
242
	public function attributeKeyIn(string $name, array $whitelist, $default = false){
243
		return isset($this->attributes[$name]) && array_key_exists($this->attributes[$name], $whitelist)
244
				? $default !== false ? $whitelist[$this->attributes[$name]] : true
245
				: $default;
246
	}
247
248
	/**
249
	 * Checks if the current tag is whitelisted
250
	 *
251
	 * @param array $whitelist an array with whitelisted tag names
252
	 * @param mixed $default   [optional] a default value in case the tag isn't whitelisted
253
	 *
254
	 * @return mixed boolean if no $default is set, otherwise the whitelisted tag or $default
255
	 */
256
	public function tagIn(array $whitelist, $default = false){
257
		return in_array($this->tag, $whitelist)
258
			? $default !== false ? $this->tag : true
259
			: $default;
260
	}
261
262
	/**
263
	 * Sanitizes the content to prevent vulnerabilities or compatibility problems
264
	 *
265
	 * @param $content string to sanitize
266
	 *
267
	 * @return string
268
	 * @codeCoverageIgnore
269
	 */
270
271
	/**
272
	 * Checks the tag and returns the processed bbcode, called from the parser within a module
273
	 *
274
	 * @see \chillerlan\bbcode\Modules\ModuleInterface::transform()
275
	 */
276
	public function transform():string{
277
		$this->checkTag();
278
279
		/** @var $this \chillerlan\bbcode\Modules\ModuleInterface */
280
		return $this->__transform();
0 ignored issues
show
Bug introduced by
The method __transform() does not exist on chillerlan\bbcode\Modules\BaseModuleAbstract. Did you maybe mean transform()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
281
	}
282
283
	/**
284
	 * shorthand for self::getAttribute('__BBTAG__')
285
	 *
286
	 * @param mixed $default
287
	 *
288
	 * @return mixed $this->attributes['__BBTAG__']
289
	 */
290
	protected function bbtag($default = false){
291
		return $this->getAttribute($this->parserOptions->bbtag_placeholder, $default);
292
	}
293
294
	/**
295
	 * shorthand for self::attributeIn('__BBTAG__', $array)
296
	 *
297
	 * @param array $array
298
	 * @param mixed $default
299
	 *
300
	 * @return mixed
301
	 */
302
	protected function bbtagIn(array $array, $default = false){
303
		return $this->attributeIn($this->parserOptions->bbtag_placeholder, $array, $default);
304
	}
305
306
	/**
307
	 * Checks if an URL is valid using filter_var()
308
	 *
309
	 * @todo check against whitelist?
310
	 *
311
	 * @param string $url the URL to check
312
	 *
313
	 * @return bool|string the url if valid, otherwise false
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use false|string.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
314
	 */
315
	public function checkUrl(string $url){
316
		if(filter_var($url, FILTER_VALIDATE_URL) === false){
317
			return false;
318
		}
319
320
		return $url;
321
	}
322
323
	/**
324
	 * Wraps the given content between the wrapper. Obvious, eh?
325
	 *
326
	 * @param string $content
327
	 * @param string $wrapper
328
	 *
329
	 * @return string
330
	 */
331
	public function wrap(string $content, string $wrapper):string{
332
		return $wrapper.$content.$wrapper;
333
	}
334
335
}
336