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.

Environment   C
last analyzed

↳ Parent: Project

Coupling/Cohesion

Components 1
Dependencies 7

Complexity

Total Complexity 58

Size/Duplication

Total Lines 518
Duplicated Lines 0 %

Test Coverage

Coverage 94.57%

Importance

Changes 0
Metric Value
wmc 58
lcom 1
cbo 7
dl 0
loc 518
ccs 174
cts 184
cp 0.9457
rs 6.3005
c 0
b 0
f 0

34 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A mergeConfig() 0 6 1
A setConfig() 0 6 1
A getConfig() 0 4 1
A getInlineParsers() 0 6 1
A getInlineParsersForCharacter() 0 10 2
A getInlineProcessors() 0 6 1
A getExtensions() 0 4 1
A getInlineParserCharacterRegex() 0 4 1
A addBlockParser() 0 8 1
A addInlineParser() 0 8 1
A addInlineProcessor() 0 8 1
A addDocumentProcessor() 0 8 1
A addBlockRenderer() 0 8 1
A addInlineRenderer() 0 8 1
A getBlockParsers() 0 6 1
A getInlineParser() 0 6 1
A getDocumentProcessors() 0 6 1
A getBlockRendererForClass() 0 10 2
A getInlineRendererForClass() 0 10 2
A createInlineParserEngine() 0 6 1
A addExtension() 0 8 1
A initializeExtensions() 0 18 3
A initializeExtension() 0 9 1
A initalizeBlockParsers() 0 14 4
B initializeInlineParsers() 0 18 5
A initializeInlineProcessors() 0 10 3
A initializeDocumentProcessors() 0 10 3
A initializeBlockRenderers() 0 10 3
A initializeInlineRenderers() 0 10 3
A createCommonMarkEnvironment() 0 17 1
A buildInlineParserCharacterRegex() 0 12 2
A assertUninitialized() 0 6 2
A getMiscExtension() 0 12 3

How to fix   Complexity   

Complex Class

Complex classes like Environment often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Environment, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the league/commonmark package.
5
 *
6
 * (c) Colin O'Dell <[email protected]>
7
 *
8
 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
9
 *  - (c) John MacFarlane
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace League\CommonMark;
16
17
use League\CommonMark\Block\Parser\BlockParserInterface;
18
use League\CommonMark\Block\Renderer\BlockRendererInterface;
19
use League\CommonMark\Extension\CommonMarkCoreExtension;
20
use League\CommonMark\Extension\ExtensionInterface;
21
use League\CommonMark\Extension\MiscExtension;
22
use League\CommonMark\Inline\Parser\InlineParserInterface;
23
use League\CommonMark\Inline\Processor\InlineProcessorInterface;
24
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
25
use League\CommonMark\Util\Configuration;
26
use League\CommonMark\Util\ConfigurationAwareInterface;
27
28
class Environment
29
{
30
    const HTML_INPUT_STRIP = 'strip';
31
    const HTML_INPUT_ESCAPE = 'escape';
32
    const HTML_INPUT_ALLOW = 'allow';
33
34
    /**
35
     * @var ExtensionInterface[]
36
     */
37
    protected $extensions = [];
38
39
    /**
40
     * @var bool
41
     */
42
    protected $extensionsInitialized = false;
43
44
    /**
45
     * @var BlockParserInterface[]
46
     */
47
    protected $blockParsers = [];
48
49
    /**
50
     * @var InlineParserInterface[]
51
     */
52
    protected $inlineParsers = [];
53
54
    /**
55
     * @var array
56
     */
57
    protected $inlineParsersByCharacter = [];
58
59
    /**
60
     * @var DocumentProcessorInterface[]
61
     */
62
    protected $documentProcessors = [];
63
64
    /**
65
     * @var InlineProcessorInterface[]
66
     */
67
    protected $inlineProcessors = [];
68
69
    /**
70
     * @var BlockRendererInterface[]
71
     */
72
    protected $blockRenderersByClass = [];
73
74
    /**
75
     * @var InlineRendererInterface[]
76
     */
77
    protected $inlineRenderersByClass = [];
78
79
    /**
80
     * @var Configuration
81
     */
82
    protected $config;
83
84
    /**
85
     * @var string
86
     */
87
    protected $inlineParserCharacterRegex;
88
89 2019
    public function __construct(array $config = [])
90
    {
91 2019
        $this->config = new Configuration($config);
92 2019
    }
93
94
    /**
95
     * @param array $config
96
     */
97 1926
    public function mergeConfig(array $config = [])
98 3
    {
99 1926
        $this->assertUninitialized('Failed to modify configuration.');
100
101 1923
        $this->config->mergeConfig($config);
102 1923
    }
103
104
    /**
105
     * @param array $config
106
     */
107 6
    public function setConfig(array $config = [])
108
    {
109 6
        $this->assertUninitialized('Failed to modify configuration.');
110
111 3
        $this->config->setConfig($config);
112 3
    }
113
114
    /**
115
     * @param string|null $key
116
     * @param mixed       $default
117
     *
118
     * @return mixed
119
     */
120 1932
    public function getConfig($key = null, $default = null)
121
    {
122 1932
        return $this->config->getConfig($key, $default);
123
    }
124
125
    /**
126
     * @param BlockParserInterface $parser
127
     *
128
     * @return $this
129
     */
130 6
    public function addBlockParser(BlockParserInterface $parser)
131
    {
132 6
        $this->assertUninitialized('Failed to add block parser.');
133
134 3
        $this->getMiscExtension()->addBlockParser($parser);
135
136 3
        return $this;
137
    }
138
139
    /**
140
     * @param InlineParserInterface $parser
141
     *
142
     * @return $this
143
     */
144 18
    public function addInlineParser(InlineParserInterface $parser)
145
    {
146 18
        $this->assertUninitialized('Failed to add inline parser.');
147
148 15
        $this->getMiscExtension()->addInlineParser($parser);
149
150 15
        return $this;
151
    }
152
153
    /**
154
     * @param InlineProcessorInterface $processor
155
     *
156
     * @return $this
157
     */
158 6
    public function addInlineProcessor(InlineProcessorInterface $processor)
159
    {
160 6
        $this->assertUninitialized('Failed to add inline processor.');
161
162 3
        $this->getMiscExtension()->addInlineProcessor($processor);
163
164 3
        return $this;
165
    }
166
167
    /**
168
     * @param DocumentProcessorInterface $processor
169
     *
170
     * @return $this
171
     */
172 9
    public function addDocumentProcessor(DocumentProcessorInterface $processor)
173
    {
174 9
        $this->assertUninitialized('Failed to add document processor.');
175
176 6
        $this->getMiscExtension()->addDocumentProcessor($processor);
177
178 6
        return $this;
179
    }
180
181
    /**
182
     * @param string                 $blockClass
183
     * @param BlockRendererInterface $blockRenderer
184
     *
185
     * @return $this
186
     */
187 9
    public function addBlockRenderer($blockClass, BlockRendererInterface $blockRenderer)
188
    {
189 9
        $this->assertUninitialized('Failed to add block renderer.');
190
191 6
        $this->getMiscExtension()->addBlockRenderer($blockClass, $blockRenderer);
192
193 6
        return $this;
194
    }
195
196
    /**
197
     * @param string                  $inlineClass
198
     * @param InlineRendererInterface $renderer
199
     *
200
     * @return $this
201
     */
202 9
    public function addInlineRenderer($inlineClass, InlineRendererInterface $renderer)
203
    {
204 9
        $this->assertUninitialized('Failed to add inline renderer.');
205
206 6
        $this->getMiscExtension()->addInlineRenderer($inlineClass, $renderer);
207
208 6
        return $this;
209
    }
210
211
    /**
212
     * @return BlockParserInterface[]
213
     */
214 1923
    public function getBlockParsers()
215
    {
216 1923
        $this->initializeExtensions();
217
218 1923
        return $this->blockParsers;
219
    }
220
221
    /**
222
     * @param string $name
223
     *
224
     * @return InlineParserInterface
225
     */
226 3
    public function getInlineParser($name)
227
    {
228 3
        $this->initializeExtensions();
229
230 3
        return $this->inlineParsers[$name];
231
    }
232
233
    /**
234
     * @return InlineParserInterface[]
235
     */
236 9
    public function getInlineParsers()
237
    {
238 9
        $this->initializeExtensions();
239
240 9
        return $this->inlineParsers;
241
    }
242
243
    /**
244
     * @param string $character
245
     *
246
     * @return InlineParserInterface[]|null
247
     */
248 1641
    public function getInlineParsersForCharacter($character)
249
    {
250 1641
        $this->initializeExtensions();
251
252 1641
        if (!isset($this->inlineParsersByCharacter[$character])) {
253 1524
            return;
254
        }
255
256 1227
        return $this->inlineParsersByCharacter[$character];
257
    }
258
259
    /**
260
     * @return InlineProcessorInterface[]
261
     */
262 1644
    public function getInlineProcessors()
263
    {
264 1644
        $this->initializeExtensions();
265
266 1644
        return $this->inlineProcessors;
267
    }
268
269
    /**
270
     * @return DocumentProcessorInterface[]
271
     */
272 1920
    public function getDocumentProcessors()
273
    {
274 1920
        $this->initializeExtensions();
275
276 1920
        return $this->documentProcessors;
277
    }
278
279
    /**
280
     * @param string $blockClass
281
     *
282
     * @return BlockRendererInterface|null
283
     */
284 1926
    public function getBlockRendererForClass($blockClass)
285
    {
286 1926
        $this->initializeExtensions();
287
288 1926
        if (!isset($this->blockRenderersByClass[$blockClass])) {
289 6
            return;
290
        }
291
292 1920
        return $this->blockRenderersByClass[$blockClass];
293
    }
294
295
    /**
296
     * @param string $inlineClass
297
     *
298
     * @return InlineRendererInterface|null
299
     */
300 1650
    public function getInlineRendererForClass($inlineClass)
301
    {
302 1650
        $this->initializeExtensions();
303
304 1650
        if (!isset($this->inlineRenderersByClass[$inlineClass])) {
305 9
            return;
306
        }
307
308 1641
        return $this->inlineRenderersByClass[$inlineClass];
309
    }
310
311 6
    public function createInlineParserEngine()
312
    {
313 6
        $this->initializeExtensions();
314
315 6
        return new InlineParserEngine($this);
316
    }
317
318
    /**
319
     * Get all registered extensions
320
     *
321
     * @return ExtensionInterface[]
322
     */
323 15
    public function getExtensions()
324
    {
325 15
        return $this->extensions;
326
    }
327
328
    /**
329
     * Add a single extension
330
     *
331
     * @param ExtensionInterface $extension
332
     *
333
     * @return $this
334
     */
335 1965
    public function addExtension(ExtensionInterface $extension)
336
    {
337 1965
        $this->assertUninitialized('Failed to add extension.');
338
339 1962
        $this->extensions[] = $extension;
340
341 1962
        return $this;
342
    }
343
344 1989
    protected function initializeExtensions()
345
    {
346
        // Only initialize them once
347 1989
        if ($this->extensionsInitialized) {
348 1920
            return;
349
        }
350
351 1989
        $this->extensionsInitialized = true;
352
353
        // Initialize all the registered extensions
354 1989
        foreach ($this->extensions as $extension) {
355 1947
            $this->initializeExtension($extension);
356 1989
        }
357
358
        // Lastly, let's build a regex which matches non-inline characters
359
        // This will enable a huge performance boost with inline parsing
360 1989
        $this->buildInlineParserCharacterRegex();
361 1989
    }
362
363
    /**
364
     * @param ExtensionInterface $extension
365
     */
366 1947
    protected function initializeExtension(ExtensionInterface $extension)
367
    {
368 1947
        $this->initalizeBlockParsers($extension->getBlockParsers());
369 1947
        $this->initializeInlineParsers($extension->getInlineParsers());
370 1947
        $this->initializeInlineProcessors($extension->getInlineProcessors());
371 1947
        $this->initializeDocumentProcessors($extension->getDocumentProcessors());
372 1947
        $this->initializeBlockRenderers($extension->getBlockRenderers());
373 1947
        $this->initializeInlineRenderers($extension->getInlineRenderers());
374 1947
    }
375
376
    /**
377
     * @param BlockParserInterface[] $blockParsers
378
     */
379 1947
    private function initalizeBlockParsers($blockParsers)
380
    {
381 1947
        foreach ($blockParsers as $blockParser) {
382 1917
            if ($blockParser instanceof EnvironmentAwareInterface) {
383
                $blockParser->setEnvironment($this);
384
            }
385
386 1917
            if ($blockParser instanceof ConfigurationAwareInterface) {
387
                $blockParser->setConfiguration($this->config);
388
            }
389
390 1917
            $this->blockParsers[$blockParser->getName()] = $blockParser;
391 1947
        }
392 1947
    }
393
394
    /**
395
     * @param InlineParserInterface[] $inlineParsers
396
     */
397 1947
    private function initializeInlineParsers($inlineParsers)
398
    {
399 1947
        foreach ($inlineParsers as $inlineParser) {
400 1926
            if ($inlineParser instanceof EnvironmentAwareInterface) {
401 1914
                $inlineParser->setEnvironment($this);
402 1914
            }
403
404 1926
            if ($inlineParser instanceof ConfigurationAwareInterface) {
405
                $inlineParser->setConfiguration($this->config);
406
            }
407
408 1926
            $this->inlineParsers[$inlineParser->getName()] = $inlineParser;
409
410 1926
            foreach ($inlineParser->getCharacters() as $character) {
411 1926
                $this->inlineParsersByCharacter[$character][] = $inlineParser;
412 1926
            }
413 1947
        }
414 1947
    }
415
416
    /**
417
     * @param InlineProcessorInterface[] $inlineProcessors
418
     */
419 1947
    private function initializeInlineProcessors($inlineProcessors)
420
    {
421 1947
        foreach ($inlineProcessors as $inlineProcessor) {
422 1917
            $this->inlineProcessors[] = $inlineProcessor;
423
424 1917
            if ($inlineProcessor instanceof ConfigurationAwareInterface) {
425
                $inlineProcessor->setConfiguration($this->config);
426
            }
427 1947
        }
428 1947
    }
429
430
    /**
431
     * @param DocumentProcessorInterface[] $documentProcessors
432
     */
433 1947
    private function initializeDocumentProcessors($documentProcessors)
434
    {
435 1947
        foreach ($documentProcessors as $documentProcessor) {
436 3
            $this->documentProcessors[] = $documentProcessor;
437
438 3
            if ($documentProcessor instanceof ConfigurationAwareInterface) {
439
                $documentProcessor->setConfiguration($this->config);
440
            }
441 1947
        }
442 1947
    }
443
444
    /**
445
     * @param BlockRendererInterface[] $blockRenderers
446
     */
447 1947
    private function initializeBlockRenderers($blockRenderers)
448
    {
449 1947
        foreach ($blockRenderers as $class => $blockRenderer) {
450 1920
            $this->blockRenderersByClass[$class] = $blockRenderer;
451
452 1920
            if ($blockRenderer instanceof ConfigurationAwareInterface) {
453 1914
                $blockRenderer->setConfiguration($this->config);
454 1914
            }
455 1947
        }
456 1947
    }
457
458
    /**
459
     * @param InlineRendererInterface[] $inlineRenderers
460
     */
461 1947
    private function initializeInlineRenderers($inlineRenderers)
462
    {
463 1947
        foreach ($inlineRenderers as $class => $inlineRenderer) {
464 1920
            $this->inlineRenderersByClass[$class] = $inlineRenderer;
465
466 1920
            if ($inlineRenderer instanceof ConfigurationAwareInterface) {
467 1914
                $inlineRenderer->setConfiguration($this->config);
468 1914
            }
469 1947
        }
470 1947
    }
471
472
    /**
473
     * @return Environment
474
     */
475 1920
    public static function createCommonMarkEnvironment()
476
    {
477 1920
        $environment = new static();
478 1920
        $environment->addExtension(new CommonMarkCoreExtension());
479 1920
        $environment->mergeConfig([
480
            'renderer' => [
481 1920
                'block_separator' => "\n",
482 1920
                'inner_separator' => "\n",
483 1920
                'soft_break'      => "\n",
484 1920
            ],
485 1920
            'safe'               => false, // deprecated option
486 1920
            'html_input'         => self::HTML_INPUT_ALLOW,
487 1920
            'allow_unsafe_links' => true,
488 1920
        ]);
489
490 1920
        return $environment;
491
    }
492
493
    /**
494
     * Regex which matches any character which doesn't indicate an inline element
495
     *
496
     * This allows us to parse multiple non-special characters at once
497
     *
498
     * @return string
499
     */
500 1527
    public function getInlineParserCharacterRegex()
501
    {
502 1527
        return $this->inlineParserCharacterRegex;
503
    }
504
505 1989
    private function buildInlineParserCharacterRegex()
506
    {
507 1989
        $chars = array_keys($this->inlineParsersByCharacter);
508
509 1989
        if (empty($chars)) {
510
            // If no special inline characters exist then parse the whole line
511 63
            $this->inlineParserCharacterRegex = '/^.+$/u';
512 63
        } else {
513
            // Match any character which inline parsers are not interested in
514 1926
            $this->inlineParserCharacterRegex = '/^[^' . preg_quote(implode('', $chars), '/') . ']+/u';
515
        }
516 1989
    }
517
518
    /**
519
     * @param string $message
520
     *
521
     * @throws \RuntimeException
522
     */
523 1995
    private function assertUninitialized($message)
524
    {
525 1995
        if ($this->extensionsInitialized) {
526 27
            throw new \RuntimeException($message . ' Extensions have already been initialized.');
527
        }
528 1968
    }
529
530
    /**
531
     * @return MiscExtension
532
     */
533 36
    private function getMiscExtension()
534
    {
535 36
        $lastExtension = end($this->extensions);
536 36
        if ($lastExtension !== false && $lastExtension instanceof MiscExtension) {
537 6
            return $lastExtension;
538
        }
539
540 36
        $miscExtension = new MiscExtension();
541 36
        $this->addExtension($miscExtension);
542
543 36
        return $miscExtension;
544
    }
545
}
546