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
Push — master ( c87b3e...4d176b )
by Tomasz
02:18
created

Processor::processIteration()   C

Complexity

Conditions 8
Paths 25

Size

Total Lines 36
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 8

Importance

Changes 20
Bugs 4 Features 7
Metric Value
c 20
b 4
f 7
dl 0
loc 36
ccs 27
cts 27
cp 1
rs 5.3846
cc 8
eloc 26
nc 25
nop 3
crap 8
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
use Thunder\Shortcode\Shortcode\ShortcodeInterface;
14
15
/**
16
 * @author Tomasz Kowalczyk <[email protected]>
17
 */
18
final class Processor implements ProcessorInterface
19
{
20
    /** @var Handlers */
21
    private $handlers;
22
    /** @var ParserInterface */
23
    private $parser;
24
    /** @var EventContainerInterface */
25
    private $eventContainer;
26
27
    private $recursionDepth = null; // infinite recursion
28
    private $maxIterations = 1; // one iteration
29
    private $autoProcessContent = true; // automatically process shortcode content
30
31 62
    public function __construct(ParserInterface $parser, Handlers $handlers)
32
    {
33 62
        $this->parser = $parser;
34 62
        $this->handlers = $handlers;
35 62
    }
36
37
    /**
38
     * Entry point for shortcode processing. Implements iterative algorithm for
39
     * both limited and unlimited number of iterations.
40
     *
41
     * @param string $text Text to process
42
     *
43
     * @return string
44
     */
45 55
    public function process($text)
46
    {
47 55
        $iterations = $this->maxIterations === null ? 1 : $this->maxIterations;
48 55
        $context = new ProcessorContext();
49 55
        $context->processor = $this;
50
51 55
        while ($iterations--) {
52 55
            $context->iterationNumber++;
53 55
            $newText = $this->processIteration($text, $context, null);
54 55
            if ($newText === $text) {
55 8
                break;
56
            }
57 51
            $text = $newText;
58 51
            $iterations += $this->maxIterations === null ? 1 : 0;
59 51
        }
60
61 55
        return $text;
62
    }
63
64 55
    private function dispatchEvent($name, $event)
65
    {
66 55
        if(null === $this->eventContainer) {
67 50
            return $event;
68
        }
69
70 5
        $handlers = $this->eventContainer->getListeners($name);
71 5
        foreach($handlers as $handler) {
72 4
            call_user_func_array($handler, array($event));
73 5
        }
74
75 5
        return $event;
76
    }
77
78 55
    private function processIteration($text, ProcessorContext $context, ProcessedShortcode $parent = null)
79
    {
80 55
        if (null !== $this->recursionDepth && $context->recursionLevel > $this->recursionDepth) {
81 2
            return $text;
82
        }
83
84 55
        $context->parent = $parent;
85 55
        $context->text = $text;
86 55
        $filterEvent = new FilterShortcodesEvent($this->parser->parse($text), $parent);
87 55
        $this->dispatchEvent(Events::FILTER_SHORTCODES, $filterEvent);
88 55
        $shortcodes = $filterEvent->getShortcodes();
89 55
        $replaces = array();
90 55
        $baseOffset = $parent && $shortcodes ? mb_strpos($parent->getShortcodeText(), $shortcodes[0]->getText()) - $shortcodes[0]->getOffset() + $parent->getOffset() : 0;
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...
91 55
        foreach ($shortcodes as $shortcode) {
92 55
            $hasNamePosition = array_key_exists($shortcode->getName(), $context->namePosition);
93
94 55
            $context->baseOffset = $baseOffset + $shortcode->getOffset();
95 55
            $context->position++;
96 55
            $context->namePosition[$shortcode->getName()] = $hasNamePosition ? $context->namePosition[$shortcode->getName()] + 1 : 1;
97 55
            $context->shortcodeText = $shortcode->getText();
98 55
            $context->offset = $shortcode->getOffset();
99 55
            $context->shortcode = $shortcode;
100 55
            $context->textContent = $shortcode->getContent();
101
102 55
            $handler = $this->handlers->get($shortcode->getName());
103 55
            $replace = $this->processHandler($shortcode, $context, $handler);
104
105 55
            $replaces[] = new ReplacedShortcode($shortcode, $replace);
106 55
        }
107 55
        $replaces = array_filter($replaces);
108
109 55
        $applyEvent = new ReplaceShortcodesEvent($text, $replaces, $parent);
110 55
        $this->dispatchEvent(Events::REPLACE_SHORTCODES, $applyEvent);
111
112 55
        return $applyEvent->hasResult() ? $applyEvent->getResult() : $this->applyReplaces($text, $replaces);
113
    }
114
115
    private function applyReplaces($text, array $replaces)
116
    {
117 54 View Code Duplication
        return array_reduce(array_reverse($replaces), function($state, ReplacedShortcode $s) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
118 54
            $offset = $s->getOffset();
119 54
            $length = mb_strlen($s->getText());
120
121 54
            return mb_substr($state, 0, $offset).$s->getReplacement().mb_substr($state, $offset + $length);
122 54
        }, $text);
123
    }
124
125 55
    private function processHandler(ParsedShortcodeInterface $parsed, ProcessorContext $context, $handler)
126
    {
127 55
        $processed = ProcessedShortcode::createFromContext(clone $context);
128 55
        $content = $this->processRecursion($processed, $context);
129 55
        $processed = $processed->withContent($content);
130
131
        return $handler
132 55
            ? call_user_func_array($handler, array($processed))
133 55
            : substr_replace($parsed->getText(), $processed->getContent(), strrpos($parsed->getText(), $parsed->getContent()), mb_strlen($parsed->getContent()));
134
    }
135
136 55
    private function processRecursion(ParsedShortcodeInterface $shortcode, ProcessorContext $context)
137
    {
138 55
        if ($this->autoProcessContent && null !== $shortcode->getContent()) {
139 45
            $context->recursionLevel++;
140
            // this is safe from using max iterations value because it's manipulated in process() method
141 45
            $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...
142 45
            $context->recursionLevel--;
143
144 45
            return $content;
145
        }
146
147 27
        return $shortcode->getContent();
148
    }
149
150
    /**
151
     * Container for event handlers used in this processor.
152
     *
153
     * @param EventContainerInterface $eventContainer
154
     *
155
     * @return self
156
     */
157 8
    public function withEventContainer(EventContainerInterface $eventContainer)
158
    {
159 8
        $self = clone $this;
160 8
        $self->eventContainer = $eventContainer;
161
162 8
        return $self;
163
    }
164
165
    /**
166
     * Recursion depth level, null means infinite, any integer greater than or
167
     * equal to zero sets value (number of recursion levels). Zero disables
168
     * recursion. Defaults to null.
169
     *
170
     * @param int|null $depth
171
     *
172
     * @return self
173
     */
174 3 View Code Duplication
    public function withRecursionDepth($depth)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
175
    {
176 3
        if (null !== $depth && !(is_int($depth) && $depth >= 0)) {
177 1
            $msg = 'Recursion depth must be null (infinite) or integer >= 0!';
178 1
            throw new \InvalidArgumentException($msg);
179
        }
180
181 2
        $self = clone $this;
182 2
        $self->recursionDepth = $depth;
183
184 2
        return $self;
185
    }
186
187
    /**
188
     * Maximum number of iterations, null means infinite, any integer greater
189
     * than zero sets value. Zero is invalid because there must be at least one
190
     * iteration. Defaults to 1. Loop breaks if result of two consequent
191
     * iterations shows no change in processed text.
192
     *
193
     * @param int|null $iterations
194
     *
195
     * @return self
196
     */
197 3 View Code Duplication
    public function withMaxIterations($iterations)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
198
    {
199 3
        if (null !== $iterations && !(is_int($iterations) && $iterations > 0)) {
200 1
            $msg = 'Maximum number of iterations must be null (infinite) or integer > 0!';
201 1
            throw new \InvalidArgumentException($msg);
202
        }
203
204 2
        $self = clone $this;
205 2
        $self->maxIterations = $iterations;
206
207 2
        return $self;
208
    }
209
210
    /**
211
     * Whether shortcode content will be automatically processed and handler
212
     * already receives shortcode with processed content. If false, every
213
     * shortcode handler needs to process content on its own. Default true.
214
     *
215
     * @param bool $flag True if enabled (default), false otherwise
216
     *
217
     * @return self
218
     */
219 3
    public function withAutoProcessContent($flag)
220
    {
221 3
        if (!is_bool($flag)) {
222 1
            $msg = 'Auto processing flag must be a boolean value!';
223 1
            throw new \InvalidArgumentException($msg);
224
        }
225
226 2
        $self = clone $this;
227 2
        $self->autoProcessContent = (bool)$flag;
228
229 2
        return $self;
230
    }
231
}
232