Completed
Pull Request — development (#2316)
by Joshua
09:55
created

ParserWrapper::parse()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 28
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5.7629

Importance

Changes 3
Bugs 0 Features 1
Metric Value
dl 0
loc 28
ccs 11
cts 16
cp 0.6875
rs 8.439
c 3
b 0
f 1
cc 5
eloc 14
nc 3
nop 2
crap 5.7629
1
<?php
2
3
/**
4
 *
5
 * @name      ElkArte Forum
6
 * @copyright ElkArte Forum contributors
7
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
8
 *
9
 */
10
11
namespace BBC;
12
13
/**
14
 * Class ParserWrapper
15
 *
16
 * Wrap around the BBC parsers before we implement a DIC.
17
 * Deprecate in future versions in favor of a DIC
18
 */
19
class ParserWrapper
20
{
21
	/** @var array Disabled tags */
22
	protected $disabled = array();
23
	/** @var \BBC\Codes */
24
	protected $codes;
25
	/** @var  \BBC\BBCParser */
26
	protected $bbc_parser;
27
	/** @var  \BBC\SmileyParser */
28
	protected $smiley_parser;
29
	/** @var  \BBC\HtmlParser */
30
	protected $html_parser;
31
	/** @var  \BBC\Autolink */
32
	protected $autolink_parser;
33
34
	protected $smileys_enabled = true;
35
36
	public static $instance;
37
38
	/**
39
	 * @return ParserWrapper
40
	 */
41 1
	public static function getInstance()
42
	{
43 1
		if (self::$instance === null)
44 1
		{
45
			self::$instance = new ParserWrapper;
46
		}
47
48 1
		return self::$instance;
49
	}
50
51
	private function __construct()
52
	{
53
54
	}
55
56
	/**
57
	 * Check if the server load is too high to execute BBC parsing
58
	 *
59
	 * @return bool If the parser can execute
60
	 */
61 1
	protected function checkLoad()
62
	{
63 1
		global $modSettings, $context;
64
65 1
		if (!empty($modSettings['bbc']) && $modSettings['current_load'] >= $modSettings['bbc'])
66 1
		{
67
			$context['disabled_parse_bbc'] = true;
68
			return false;
69
		}
70
71 1
		return true;
72
	}
73
74
	/**
75
	 * Is BBC parsing enabled
76
	 *
77
	 * @return bool
78
	 */
79 1
	protected function isEnabled()
80
	{
81 1
		global $modSettings;
82
83 1
		return !empty($modSettings['enableBBC']);
84
	}
85
86
	/**
87
	 * @param bool $toggle
88
	 * @return $this
89
	 */
90 1
	public function enableSmileys($toggle)
91
	{
92 1
		$this->smileys_enabled = (bool) $toggle;
93 1
		return $this;
94
	}
95
96
	/**
97
	 * Get parsers based on where it will be used
98
	 *
99
	 * @param string $area Where it is being called from
100
	 * @return array
101
	 */
102 1
	protected function getParsersByArea($area)
103
	{
104
		$parsers = array(
105 1
			'autolink' => false,
106 1
			'html' => false,
107 1
			'bbc' => false,
108 1
			'smiley' => false,
109 1
		);
110
111
		// First see if any hooks set a parser.
112 1
		foreach ($parsers as $parser_type => &$parser)
113
		{
114 1
			call_integration_hook('integrate_' . $area . '_' . $parser_type . '_parser', array(&$parser, $this));
115
116
			// If not, use the default one
117 1
			if ($parser === false)
118 1
			{
119 1
				$parser = call_user_func(array($this, 'get' . ucfirst($parser_type) . 'Parser'), $area);
120 1
			}
121 1
		}
122
123 1
		return $parsers;
124
	}
125
126
	/**
127
	 * @return array
128
	 */
129
	public function getMessageParsers()
130
	{
131
		return $this->getParsersByArea('message');
132
	}
133
134
	/**
135
	 * @return array
136
	 */
137
	public function getSignatureParser()
138
	{
139
		return $this->getParsersByArea('signature');
140
	}
141
142
	/**
143
	 * @return array
144
	 */
145
	public function getNewsParser()
146
	{
147
		return $this->getParsersByArea('news');
148
	}
149
150
	/**
151
	 * Parse a string based on where it's being called from
152
	 *
153
	 * @param string $area Where this is being called from
154
	 * @param string $message The message to be parsed
155
	 * @return string The Parsed message
156
	 */
157 1
	protected function parse($area, $message)
0 ignored issues
show
Coding Style introduced by
parse uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
158
	{
159
		// If the load average is too high, don't parse the BBC.
160 1
		if (!$this->checkLoad())
161 1
		{
162
			return $message;
163
		}
164
165 1
		$parsers = $this->getParsersByArea($area);
166
167 1
		if (!$this->isEnabled())
168 1
		{
169
			// You need to run the smiley parser to get rid of the markers
170
			$parsers['smiley']
0 ignored issues
show
Bug introduced by
The method setEnabled cannot be called on $parsers['smiley'] (of type false).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
171
				->setEnabled($this->smileys_enabled && $GLOBALS['user_info']['smiley_set'] !== 'none')
172
				->parse($message);
173
174
			return $message;
175
		}
176
177 1
		$message = $parsers['bbc']->parse($message);
0 ignored issues
show
Bug introduced by
The method parse cannot be called on $parsers['bbc'] (of type false).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
178
179 1
		$parsers['smiley']
0 ignored issues
show
Bug introduced by
The method setEnabled cannot be called on $parsers['smiley'] (of type false).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
180 1
			->setEnabled($this->smileys_enabled && $GLOBALS['user_info']['smiley_set'] !== 'none')
181 1
			->parse($message);
182
183 1
		return $message;
184
	}
185
186
	/**
187
	 * Parse the BBC and smileys in messages
188
	 *
189
	 * @param string $message
190
	 * @param bool   $smileys_enabled
191
	 * @return string
192
	 */
193 1
	public function parseMessage($message, $smileys_enabled)
194
	{
195 1
		return $this->enableSmileys($smileys_enabled)->parse('message', $message);
196
	}
197
198
	/**
199
	 * Parse the BBC and smileys in signatures
200
	 *
201
	 * @param string $signature
202
	 * @param string $smileys_enabled
203
	 * @return string
204
	 */
205
	public function parseSignature($signature, $smileys_enabled)
206
	{
207
		return $this->enableSmileys($smileys_enabled)->parse('signature', $signature);
0 ignored issues
show
Documentation introduced by
$smileys_enabled is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
208
	}
209
210
	/**
211
	 * Parse the BBC and smileys in news items
212
	 *
213
	 * @param string $news
214
	 * @return string
215
	 */
216
	public function parseNews($news)
217
	{
218
		return $this->enableSmileys(true)->parse('news', $news);
219
	}
220
221
	/**
222
	 * Parse the BBC and smileys in emails
223
	 *
224
	 * @param string $message
225
	 * @return string
226
	 */
227
	public function parseEmail($message)
228
	{
229
		return $this->enableSmileys(false)->parse('email', $message);
230
	}
231
232
	/**
233
	 * Parse the BBC and smileys in custom profile fields
234
	 * @param string $field
235
	 * @return string
236
	 */
237
	public function parseCustomFields($field)
238
	{
239
		// @todo this should account for which field is being parsed and hook on that
240
241
		return $this->enableSmileys(true)->parse('customfields', $field);
242
	}
243
244
	/**
245
	 * Parse the BBC and smileys in poll questions/answers
246
	 *
247
	 * @param string $field
248
	 * @return string
249
	 */
250
	public function parsePoll($field)
251
	{
252
		return $this->enableSmileys(true)->parse('poll', $field);
253
	}
254
255
	/**
256
	 * Parse the BBC and smileys in the registration agreement
257
	 *
258
	 * @param string $agreement
259
	 * @return string
260
	 */
261
	public function parseAgreement($agreement)
262
	{
263
		return $this->enableSmileys(true)->parse('agreement', $agreement);
264
	}
265
266
	/**
267
	 * Parse the BBC and smileys in personal messages
268
	 *
269
	 * @param string $message
270
	 * @return string
271
	 */
272
	public function parsePM($message)
273
	{
274
		return $this->enableSmileys(true)->parse('pm', $message);
275
	}
276
277
	/**
278
	 * Parse the BBC and smileys in user submitted reports
279
	 *
280
	 * @param string $report
281
	 * @return string
282
	 */
283
	public function parseReport($report)
284
	{
285
		return $this->enableSmileys(true)->parse('report', $report);
286
	}
287
288
	/**
289
	 * Parse the BBC and smileys in package descriptions
290
	 *
291
	 * @param string $report
0 ignored issues
show
Bug introduced by
There is no parameter named $report. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
292
	 * @return string
293
	 */
294
	public function parsePackage($string)
295
	{
296
		return $this->enableSmileys(true)->parse('package', $string);
297
	}
298
299
	/**
300
	 * Parse the BBC and smileys in user verification controls
301
	 *
302
	 * @param string $question
303
	 * @return string
304
	 */
305
	public function parseVerificationControls($question)
306
	{
307
		return $this->enableSmileys(true)->parse('package', $question);
308
	}
309
310
	/**
311
	 * Parse the BBC and smileys in moderator notices to users
312
	 *
313
	 * @param string $notice
314
	 * @return string
315
	 */
316
	public function parseNotice($notice)
317
	{
318
		return $this->enableSmileys(true)->parse('notice', $notice);
319
	}
320
321
	/**
322
	 * Parse the BBC and smileys in board descriptions
323
	 *
324
	 * @param string $board
325
	 * @return string
326
	 */
327
	public function parseBoard($board)
328
	{
329
		return $this->enableSmileys(true)->parse('board', $board);
330
	}
331
332
	/**
333
	 * Set the disabled tags
334
	 * (usually from $modSettings['disabledBBC'])
335
	 * @param array $disabled
336
	 * @return $this
337
	 */
338
	public function setDisabled(array $disabled)
339
	{
340
		foreach ($disabled as $tag)
341
		{
342
			$this->disabled[trim($tag)] = true;
343
		}
344
345
		return $this;
346
	}
347
348
	/**
349
	 * @return Codes
350
	 */
351 1
	public function getCodes()
352
	{
353 1
		if ($this->codes === null)
354 1
		{
355 1
			$additional_bbc = array();
356 1
			call_integration_hook('integrate_additional_bbc', array(&$additional_bbc));
357 1
			$this->codes = new \BBC\Codes($additional_bbc, $this->disabled);
358 1
		}
359
360 1
		return $this->codes;
361
	}
362
363
	/**
364
	 * @return BBCParser
365
	 */
366 1
	public function getBBCParser()
367
	{
368 1
		if ($this->bbc_parser === null)
369 1
		{
370 1
			$this->bbc_parser = new \BBC\BBCParser($this->getCodes(), $this->getAutolinkParser());
371 1
		}
372
373 1
		return $this->bbc_parser;
374
	}
375
376
	/**
377
	 * @return Autolink
378
	 */
379 1
	public function getAutolinkParser()
380
	{
381 1
		if ($this->autolink_parser === null)
382 1
		{
383 1
			$this->autolink_parser = new \BBC\Autolink($this->getCodes());
384 1
		}
385
386 1
		return $this->autolink_parser;
387
	}
388
389
	/**
390
	 * @return SmileyParser
391
	 */
392 1
	public function getSmileyParser()
0 ignored issues
show
Coding Style introduced by
getSmileyParser uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
393
	{
394 1
		global $modSettings, $user_info;
395
396 1
		if ($this->smiley_parser === null)
397 1
		{
398 1
			$path = $modSettings['smileys_url'] . '/' . $user_info['smiley_set'] . '/';
399 1
			$this->smiley_parser = new \BBC\SmileyParser($path);
400 1
			$this->smiley_parser->setEnabled($GLOBALS['user_info']['smiley_set'] !== 'none');
401 1
		}
402
403 1
		return $this->smiley_parser;
404
	}
405
406
	/**
407
	 * @return HtmlParser
408
	 */
409 1
	public function getHtmlParser()
410
	{
411 1
		if ($this->html_parser === null)
412 1
		{
413 1
			$this->html_parser = new \BBC\HtmlParser;
414 1
		}
415
416 1
		return $this->html_parser;
417
	}
418
}