GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#48)
by Matthias
02:02
created

Processor::setAutoProcessContent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 1
crap 2
1
<?php
2
namespace Thunder\Shortcode\Processor;
3
4
use Thunder\Shortcode\Event\ReplaceShortcodesEvent;
5
use Thunder\Shortcode\Event\FilterShortcodesEvent;
6
use Thunder\Shortcode\EventContainer\EventContainerInterface;
7
use Thunder\Shortcode\Events;
8
use Thunder\Shortcode\HandlerContainer\HandlerContainerInterface as Handlers;
9
use Thunder\Shortcode\Parser\ParserInterface;
10
use Thunder\Shortcode\Shortcode\ReplacedShortcode;
11
use Thunder\Shortcode\Shortcode\ParsedShortcodeInterface;
12
use Thunder\Shortcode\Shortcode\ProcessedShortcode;
13
14
/**
15
 * @author Tomasz Kowalczyk <[email protected]>
16
 */
17
final class Processor implements ProcessorInterface
18
{
19
    /** @var Handlers */
20
    private $handlers;
21
    /** @var ParserInterface */
22
    private $parser;
23
    /** @var EventContainerInterface */
24
    private $eventContainer;
25
26
    private $recursionDepth = null; // infinite recursion
27
    private $maxIterations = 1; // one iteration
28
    private $autoProcessContent = true; // automatically process shortcode content
29
30 64
    public function __construct(ParserInterface $parser, Handlers $handlers)
31
    {
32 64
        $this->parser = $parser;
33 64
        $this->handlers = $handlers;
34 64
    }
35
36
    /**
37
     * Entry point for shortcode processing. Implements iterative algorithm for
38
     * both limited and unlimited number of iterations.
39
     *
40
     * @param string $text Text to process
41
     *
42
     * @return string
43
     */
44 57
    public function process($text)
45
    {
46 57
        $iterations = $this->maxIterations === null ? 1 : $this->maxIterations;
47 57
        $context = new ProcessorContext();
48 57
        $context->processor = $this;
49
50 57
        while ($iterations--) {
51 57
            $context->iterationNumber++;
52 57
            $newText = $this->processIteration($text, $context, null);
53 57
            if ($newText === $text) {
54 9
                break;
55
            }
56 52
            $text = $newText;
57 52
            $iterations += $this->maxIterations === null ? 1 : 0;
58 52
        }
59
60 57
        return $text;
61
    }
62
63 57
    private function dispatchEvent($name, $event)
64
    {
65 57
        if(null === $this->eventContainer) {
66 52
            return $event;
67
        }
68
69 5
        $handlers = $this->eventContainer->getListeners($name);
70 5
        foreach($handlers as $handler) {
71 4
            $handler($event);
72 5
        }
73
74 5
        return $event;
75
    }
76
77 57
    private function processIteration($text, ProcessorContext $context, ProcessedShortcode $parent = null)
78
    {
79 57
        if (null !== $this->recursionDepth && $context->recursionLevel > $this->recursionDepth) {
80 2
            return $text;
81
        }
82
83 57
        $context->parent = $parent;
84 57
        $context->text = $text;
85 57
        $filterEvent = new FilterShortcodesEvent($this->parser->parse($text), $parent);
86 57
        $this->dispatchEvent(Events::FILTER_SHORTCODES, $filterEvent);
87 57
        $shortcodes = $filterEvent->getShortcodes();
88 57
        $replaces = array();
89 57
        $baseOffset = $parent && $shortcodes
0 ignored issues
show
Bug Best Practice introduced by
The expression $shortcodes of type Thunder\Shortcode\Shortc...sedShortcodeInterface[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
90 57
            ? mb_strpos($parent->getShortcodeText(), $shortcodes[0]->getText(), null, 'utf-8') - $shortcodes[0]->getOffset() + $parent->getOffset()
91 57
            : 0;
92 57
        foreach ($shortcodes as $shortcode) {
93 57
            $name = $shortcode->getName();
94 57
            $hasNamePosition = array_key_exists($name, $context->namePosition);
95
96 57
            $context->baseOffset = $baseOffset + $shortcode->getOffset();
97 57
            $context->position++;
98 57
            $context->namePosition[$name] = $hasNamePosition ? $context->namePosition[$name] + 1 : 1;
99 57
            $context->shortcodeText = $shortcode->getText();
100 57
            $context->offset = $shortcode->getOffset();
101 57
            $context->shortcode = $shortcode;
102 57
            $context->textContent = $shortcode->getContent();
103
104 57
            $handler = $this->handlers->get($name);
105 57
            $replace = $this->processHandler($shortcode, $context, $handler);
106
107 57
            $replaces[] = new ReplacedShortcode($shortcode, $replace);
108 57
        }
109 57
        $replaces = array_filter($replaces);
110
111 57
        $applyEvent = new ReplaceShortcodesEvent($text, $replaces, $parent);
112 57
        $this->dispatchEvent(Events::REPLACE_SHORTCODES, $applyEvent);
113
114 57
        return $applyEvent->hasResult() ? $applyEvent->getResult() : $this->applyReplaces($text, $replaces);
115
    }
116
117
    private function applyReplaces($text, array $replaces)
118
    {
119 56
        return array_reduce(array_reverse($replaces), function($state, ReplacedShortcode $s) {
120 56
            $offset = $s->getOffset();
121 56
            $length = mb_strlen($s->getText(), 'utf-8');
122 56
            $textLength = mb_strlen($state, 'utf-8');
123
124 56
            return mb_substr($state, 0, $offset, 'utf-8').$s->getReplacement().mb_substr($state, $offset + $length, $textLength, 'utf-8');
125 56
        }, $text);
126
    }
127
128 57
    private function processHandler(ParsedShortcodeInterface $parsed, ProcessorContext $context, $handler)
129
    {
130 57
        $processed = ProcessedShortcode::createFromContext(clone $context);
131 57
        $content = $this->processRecursion($processed, $context);
132 57
        $processed = $processed->withContent($content);
133
134 57
        if($handler) {
135 53
            return $handler($processed);
136
        }
137
138 10
        $state = $parsed->getText();
139 10
        $length = mb_strlen($processed->getTextContent(), 'utf-8');
140 10
        $offset = mb_strrpos($state, $processed->getTextContent(), 'utf-8');
141
142 10
        return mb_substr($state, 0, $offset, 'utf-8').$processed->getContent().mb_substr($state, $offset + $length, mb_strlen($state, 'utf-8'), 'utf-8');
143
    }
144
145 57
    private function processRecursion(ParsedShortcodeInterface $shortcode, ProcessorContext $context)
146
    {
147 57
        if ($this->autoProcessContent && null !== $shortcode->getContent()) {
148 46
            $context->recursionLevel++;
149
            // this is safe from using max iterations value because it's manipulated in process() method
150 46
            $content = $this->processIteration($shortcode->getContent(), clone $context, $shortcode);
0 ignored issues
show
Documentation introduced by
$shortcode is of type object<Thunder\Shortcode...rsedShortcodeInterface>, but the function expects a null|object<Thunder\Shor...ode\ProcessedShortcode>.

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...
151 46
            $context->recursionLevel--;
152
153 46
            return $content;
154
        }
155
156 28
        return $shortcode->getContent();
157
    }
158
159
    /**
160
     * Set container for event handlers used in this processor.
161
     *
162
     * @param EventContainerInterface $eventContainer
163
     *
164
     * @return self
165
     */
166 8
    public function setEventContainer(EventContainerInterface $eventContainer)
167
    {
168 8
        $this->eventContainer = $eventContainer;
169
170 8
        return $this;
171
    }
172
173
    /**
174
     * Create a new Processor using a given event container
175
     *
176
     * @param EventContainerInterface $eventContainer
177
     *
178
     * @return self
179
     */
180 8
    public function withEventContainer(EventContainerInterface $eventContainer)
181
    {
182 8
        $self = clone $this;
183
184 8
        return $self->setEventContainer($eventContainer);
185
    }
186
187
    /**
188
     * Set recursion depth level
189
     *
190
     * Null means infinite, any integer greater than or
191
     * equal to zero sets value (number of recursion levels). Zero disables
192
     * recursion. Defaults to null.
193
     *
194
     * @param int|null $depth
195
     *
196
     * @return self
197
     */
198 3
    public function setRecursionDepth($depth)
199
    {
200 3
        if (null !== $depth && !(is_int($depth) && $depth >= 0)) {
201 1
            $msg = 'Recursion depth must be null (infinite) or integer >= 0!';
202 1
            throw new \InvalidArgumentException($msg);
203
        }
204
205 2
        $this->recursionDepth = $depth;
206
207 2
        return $this;
208
    }
209
210
    /**
211
     * Create a new Processor using a given resursion depth
212
     *
213
     * @param int|null $depth
214
     *
215
     * @return self
216
     */
217 3
    public function withRecursionDepth($depth)
218
    {
219 3
        $self = clone $this;
220
221 3
        return $self->setRecursionDepth($depth);
222
    }
223
224
    /**
225
     * Set maximum number of iterations
226
     *
227
     * Null means infinite, any integer greater
228
     * than zero sets value. Zero is invalid because there must be at least one
229
     * iteration. Defaults to 1. Loop breaks if result of two consequent
230
     * iterations shows no change in processed text.
231
     *
232
     * @param int|null $iterations
233
     *
234
     * @return self
235
     */
236 3
    public function setMaxIterations($iterations)
237
    {
238 3
        if (null !== $iterations && !(is_int($iterations) && $iterations > 0)) {
239 1
            $msg = 'Maximum number of iterations must be null (infinite) or integer > 0!';
240 1
            throw new \InvalidArgumentException($msg);
241
        }
242
243 2
        $this->maxIterations = $iterations;
244
245 2
        return $this;
246
    }
247
248
    /**
249
     * Create a new Processor using a given maximum number of iterations
250
     *
251
     * @param int|null $iterations
252
     *
253
     * @return self
254
     */
255 3
    public function withMaxIterations($iterations)
256
    {
257 3
        $self = clone $this;
258
259 3
        return $self->setMaxIterations($iterations);
260
    }
261
262
    /**
263
     * Sets whether shortcode content will be automatically processed and handler
264
     * already receives shortcode with processed content.
265
     *
266
     * If false, every shortcode handler needs to process content on its own.
267
     * Default true.
268
     *
269
     * @param bool $flag True if enabled (default), false otherwise
270
     *
271
     * @return self
272
     */
273 3
    public function setAutoProcessContent($flag)
274
    {
275 3
        if (!is_bool($flag)) {
276 1
            $msg = 'Auto processing flag must be a boolean value!';
277 1
            throw new \InvalidArgumentException($msg);
278
        }
279
280 2
        $this->autoProcessContent = (bool)$flag;
281
282 2
        return $this;
283
    }
284
285
    /**
286
     * Creates a new Processor with a given setting for automatic content processing
287
     *
288
     * @param bool $flag True if enabled (default), false otherwise
289
     *
290
     * @return self
291
     */
292 3
    public function withAutoProcessContent($flag)
293
    {
294 3
        $self = clone $this;
295
296 3
        return $self->setAutoProcessContent($flag);
297
    }
298
}
299