Completed
Push — master ( c71ac0...51eb0e )
by smiley
04:36
created

BBCode::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 3
1
<?php
2
/**
3
 * Class BBCode
4
 *
5
 * @filesource   BBCode.php
6
 * @created      19.04.2018
7
 * @package      chillerlan\BBCode
8
 * @author       smiley <[email protected]>
9
 * @copyright    2018 smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\BBCode;
14
15
use chillerlan\BBCode\Output\BBCodeOutputInterface;
16
use chillerlan\Traits\{
17
	ClassLoader, ContainerInterface
18
};
19
use Psr\Log\{
20
	LoggerAwareInterface, LoggerAwareTrait, LoggerInterface, NullLogger
21
};
22
use Psr\SimpleCache\CacheInterface;
23
24
class BBCode implements LoggerAwareInterface{
25
	use ClassLoader, LoggerAwareTrait;
26
27
	/**
28
	 * @var \chillerlan\BBCode\BBCodeOptions|\chillerlan\Traits\ContainerInterface
29
	 */
30
	protected $options;
31
32
	/**
33
	 * @var \Psr\SimpleCache\CacheInterface
34
	 */
35
	protected $cache;
36
37
	/**
38
	 * @var \chillerlan\BBCode\SanitizerInterface
39
	 */
40
	protected $sanitizerInterface;
41
42
	/**
43
	 * @var \chillerlan\BBCode\Output\BBCodeOutputInterface
44
	 */
45
	protected $outputInterface;
46
47
	/**
48
	 * @var \chillerlan\BBCode\ParserMiddlewareInterface
49
	 */
50
	protected $parserMiddleware;
51
52
	/**
53
	 * @var array
54
	 */
55
	protected $tags = [];
56
57
	/**
58
	 * @var array
59
	 */
60
	protected $noparse = [];
61
62
	/**
63
	 * @var array
64
	 */
65
	protected $allowed = [];
66
67
	/**
68
	 * BBCode constructor.
69
	 *
70
	 * @param \chillerlan\Traits\ContainerInterface|null $options
71
	 * @param \Psr\SimpleCache\CacheInterface|null       $cache
72
	 * @param \Psr\Log\LoggerInterface|null              $logger
73
	 */
74
	public function __construct(ContainerInterface $options = null, CacheInterface $cache = null, LoggerInterface $logger = null){
75
		$this
76
			->setCache($cache ?? new BBCache)
77
			->setLogger($logger ?? new NullLogger);
78
79
		$this->setOptions($options ?? new BBCodeOptions);
80
	}
81
82
	/**
83
	 * @param array $allowedTags
84
	 *
85
	 * @return \chillerlan\BBCode\BBCode
86
	 */
87
	public function allowTags(array $allowedTags):BBCode{
88
		$this->allowed = [];
89
90
		foreach($allowedTags as $tag){
91
			$tag = strtolower($tag);
92
93
			if(in_array($tag, $this->tags, true)){
94
				$this->allowed[] = $tag;
95
			}
96
		}
97
98
		return $this;
99
	}
100
101
	/**
102
	 * @param \Psr\SimpleCache\CacheInterface $cache
103
	 *
104
	 * @return \chillerlan\BBCode\BBCode
105
	 */
106
	public function setCache(CacheInterface $cache):BBCode{
107
		$this->cache = $cache;
108
109
		return $this;
110
	}
111
112
	/**
113
	 * @todo
114
	 *
115
	 * @param \chillerlan\Traits\ContainerInterface $options
116
	 *
117
	 * @throws \chillerlan\BBCode\BBCodeException
118
	 * @return \chillerlan\BBCode\BBCode
119
	 */
120
	public function setOptions(ContainerInterface $options):BBCode{
121
		$this->options = $options;
122
123
		mb_internal_encoding('UTF-8');
124
125
		if(
126
			ini_set('pcre.backtrack_limit', $this->options->pcre_backtrack_limit) === false
0 ignored issues
show
Bug introduced by
Accessing pcre_backtrack_limit on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
127
			|| ini_set('pcre.recursion_limit', $this->options->pcre_recursion_limit) === false
0 ignored issues
show
Bug introduced by
Accessing pcre_recursion_limit on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
128
			|| ini_set('pcre.jit', $this->options->pcre_jit) === false
0 ignored issues
show
Bug introduced by
Accessing pcre_jit on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
129
		){
130
			throw new BBCodeException('could not alter ini settings');
131
		}
132
133
		if(ini_get('pcre.backtrack_limit') !== (string)$this->options->pcre_backtrack_limit
0 ignored issues
show
Bug introduced by
Accessing pcre_backtrack_limit on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
134
			|| ini_get('pcre.recursion_limit') !== (string)$this->options->pcre_recursion_limit
0 ignored issues
show
Bug introduced by
Accessing pcre_recursion_limit on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
135
			|| ini_get('pcre.jit') !== (string)$this->options->pcre_jit
0 ignored issues
show
Bug introduced by
Accessing pcre_jit on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
136
		){
137
			throw new BBCodeException('ini settings differ from options');
138
		}
139
140
		if($this->options->sanitizeInput || $this->options->sanitizeOutput){
0 ignored issues
show
Bug introduced by
Accessing sanitizeInput on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing sanitizeOutput on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
141
			$this->sanitizerInterface  = $this->loadClass($this->options->sanitizerInterface, SanitizerInterface::class, $this->options);
0 ignored issues
show
Bug introduced by
Accessing sanitizerInterface on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
142
		}
143
144
145
146
		if($this->options->preParse || $this->options->postParse){
0 ignored issues
show
Bug introduced by
Accessing preParse on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
Bug introduced by
Accessing postParse on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
147
			$this->parserMiddleware = $this->loadClass($this->options->parserMiddlewareInterface, ParserMiddlewareInterface::class, $this->options, $this->cache, $this->logger);
0 ignored issues
show
Bug introduced by
Accessing parserMiddlewareInterface on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
148
		}
149
150
		$this->outputInterface = $this->loadClass($this->options->outputInterface, BBCodeOutputInterface::class, $this->options, $this->cache, $this->logger);
0 ignored issues
show
Bug introduced by
Accessing outputInterface on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
151
152
		$this->tags    = $this->outputInterface->getTags();
153
		$this->noparse = $this->outputInterface->getNoparse();
154
155
		if(is_array($this->options->allowedTags) && !empty($this->options->allowedTags)){
0 ignored issues
show
Bug introduced by
Accessing allowedTags on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
156
			$this->allowTags($this->options->allowedTags);
0 ignored issues
show
Bug introduced by
Accessing allowedTags on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
157
		}
158
		elseif($this->options->allowAvailableTags === true){
0 ignored issues
show
Bug introduced by
Accessing allowAvailableTags on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
159
			$this->allowed = $this->tags;
160
		}
161
162
		return $this;
163
	}
164
165
	/**
166
	 * Transforms a BBCode string to HTML (or whatevs)
167
	 *
168
	 * @param string $bbcode
169
	 *
170
	 * @return string
171
	 */
172
	public function parse(string $bbcode):string{
173
174
		// sanitize the input if needed
175
		if($this->options->sanitizeInput){
0 ignored issues
show
Bug introduced by
Accessing sanitizeInput on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
176
			$bbcode = $this->sanitizerInterface->sanitizeInput($bbcode);
177
		}
178
179
		// run the pre-parser
180
		if($this->options->preParse){
0 ignored issues
show
Bug introduced by
Accessing preParse on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
181
			$bbcode = $this->parserMiddleware->pre($bbcode);
182
		}
183
184
		// @todo: array < 2 elements causes a PREG_BACKTRACK_LIMIT_ERROR! (breaks match pattern)
185
		$singleTags = array_merge(['br', 'hr'], $this->outputInterface->getSingleTags());
186
187
		// close singletags: [br] -> [br][/br]
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
188
		$bbcode = preg_replace('#\[('.implode('|', $singleTags).')((?:\s|=)[^]]*)?]#is', '[$1$2][/$1]', $bbcode);
189
		// protect newlines
190
		$bbcode = str_replace(["\r", "\n"], ['', $this->options->placeholder_eol], $bbcode);
0 ignored issues
show
Bug introduced by
Accessing placeholder_eol on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
191
		// parse the bbcode
192
		$bbcode = $this->parseBBCode($bbcode);
193
194
		// run the post-parser
195
		if($this->options->postParse){
0 ignored issues
show
Bug introduced by
Accessing postParse on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
196
			$bbcode = $this->parserMiddleware->post($bbcode);
197
		}
198
199
		// replace the newline placeholders
200
		$bbcode = str_replace($this->options->placeholder_eol, PHP_EOL, $bbcode);
0 ignored issues
show
Bug introduced by
Accessing placeholder_eol on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
201
202
		// run the sanitizer/html purifier/whatever as a final step
203
		if($this->options->sanitizeOutput){
0 ignored issues
show
Bug introduced by
Accessing sanitizeOutput on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
204
			$bbcode = $this->sanitizerInterface->sanitizeOutput($bbcode);
205
		}
206
207
		return $bbcode;
208
	}
209
210
	/**
211
	 * @param $bbcode
212
	 *
213
	 * @return string
214
	 */
215
	protected function parseBBCode($bbcode):string{
216
		static $callback_count = 0;
217
218
		$callback = false;
219
220
		if(is_array($bbcode) && count($bbcode) === 4){
221
			[$match, $tag, $attributes, $content] = $bbcode;
0 ignored issues
show
Bug introduced by
The variable $match seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $tag seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $attributes seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $content seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
222
223
			$tag        = strtolower($tag);
0 ignored issues
show
Bug introduced by
The variable $tag seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
224
			$attributes = $this->parseAttributes($attributes);
0 ignored issues
show
Bug introduced by
The variable $attributes seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
225
			$callback   = true;
226
227
			$callback_count++;
228
		}
229
		else if(is_string($bbcode) && !empty($bbcode)){
230
			$match      = null;
231
			$tag        = null;
232
			$attributes = [];
233
			$content    = $bbcode;
234
		}
235
		else{
236
			return '';
237
		}
238
239
		if($callback_count < (int)$this->options->nestingLimit && !in_array($tag, $this->noparse , true)){
0 ignored issues
show
Bug introduced by
Accessing nestingLimit on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
240
			$content = preg_replace_callback('#\[(\w+)((?:\s|=)[^]]*)?]((?:[^[]|\[(?!/?\1((?:\s|=)[^]]*)?])|(?R))*)\[/\1]#', __METHOD__, $content);
0 ignored issues
show
Bug introduced by
The variable $content does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
241
			$e = preg_last_error();
242
243
			/**
244
			 * 1 - PREG_INTERNAL_ERROR
245
			 * 2 - PREG_BACKTRACK_LIMIT_ERROR
246
			 * 3 - PREG_RECURSION_LIMIT_ERROR
247
			 * 4 - PREG_BAD_UTF8_ERROR
248
			 * 5 - PREG_BAD_UTF8_OFFSET_ERROR
249
			 * 6 - PREG_JIT_STACKLIMIT_ERROR
250
			 */
251
			if($e !== PREG_NO_ERROR){
252
				$this->logger->debug('preg_error', ['errno' => $e, '$content' => $content]);
253
254
				$content = $match ?? '';//$content ?? $bbcode ??
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
255
			}
256
		}
257
258
		if($callback === true && in_array($tag, $this->allowed, true)){
259
			$content = $this->outputInterface->transform($tag, $attributes, $content, $match, $callback_count);
0 ignored issues
show
Bug introduced by
The variable $match does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
260
			$callback_count = 0;
261
		}
262
263
		return $content;
264
	}
265
266
	/**
267
	 * @param string $attributes
268
	 *
269
	 * @return array
270
	 */
271
	protected function parseAttributes(string $attributes):array{
272
		$attr = [];
273
274
		// @todo: fix attributes pattern: accept single and double quotes around the value
275
		if(preg_match_all('#(?<name>^|\w+)\=(\'?)(?<value>[^\']*?)\2(?: |$)#', $attributes, $matches, PREG_SET_ORDER) > 0){
276
277
			foreach($matches as $attribute){
278
				$name = empty($attribute['name']) ? $this->options->placeholder_bbtag : strtolower(trim($attribute['name']));
0 ignored issues
show
Bug introduced by
Accessing placeholder_bbtag on the interface chillerlan\Traits\ContainerInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
279
280
				$attr[$name] = trim($attribute['value'], '"\' ');
281
			}
282
		}
283
284
		$e = preg_last_error();
285
286
		if($e !== PREG_NO_ERROR){
287
			$this->logger->debug('preg_error', ['errno' => $e, '$attributes' => $attributes]);
288
		}
289
290
		return $attr;
291
	}
292
293
}
294