Test Setup Failed
Pull Request — latest (#3)
by Mark
34:22
created

ImageRenderer::setConfiguration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 1
c 1
b 0
f 1
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the league/commonmark package.
7
 *
8
 * (c) Colin O'Dell <[email protected]>
9
 *
10
 * Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
11
 *  - (c) John MacFarlane
12
 *
13
 * For the full copyright and license information, please view the LICENSE
14
 * file that was distributed with this source code.
15
 */
16
17
namespace UnicornFail\Emoji\Extension\Emoji\Renderer;
18
19
use League\Configuration\ConfigurationAwareInterface;
20
use League\Configuration\ConfigurationInterface;
21
use UnicornFail\Emoji\Node\Inline\Image;
22
use UnicornFail\Emoji\Node\Node;
23
use UnicornFail\Emoji\Renderer\ChildNodeRendererInterface;
24
use UnicornFail\Emoji\Renderer\NodeRendererInterface;
25
use UnicornFail\Emoji\Util\HtmlElement;
26
27
final class ImageRenderer implements NodeRendererInterface, ConfigurationAwareInterface
28
{
29
    public const REGEX_UNSAFE_PROTOCOL    = '/^javascript:|vbscript:|file:|data:/i';
30
    public const REGEX_SAFE_DATA_PROTOCOL = '/^data:image\/(?:png|gif|jpeg|webp)/i';
31
32
    /**
33
     * @var ConfigurationInterface
34
     *
35
     * @psalm-readonly-allow-private-mutation
36
     */
37
    private $config;
38
39
    /**
40
     * @param Node $node {@inheritdoc}
41
     *
42
     * @psalm-suppress MoreSpecificImplementedParamType
43
     */
44
    public function render(Node $node, ChildNodeRendererInterface $childRenderer)
45
    {
46
        if (! ($node instanceof Image)) {
47
            throw new \InvalidArgumentException('Incompatible node type: ' . \get_class($node));
48
        }
49
50
        /** @var array<string, mixed> $attrs */
51
        $attrs = $node->data->get('attributes');
52
53
        $forbidUnsafeLinks = ! $this->config->get('allow_unsafe_links');
54
        if ($forbidUnsafeLinks && self::isLinkPotentiallyUnsafe($node->getUrl())) {
0 ignored issues
show
Bug introduced by
The method getUrl() does not exist on UnicornFail\Emoji\Node\Inline\Image. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

54
        if ($forbidUnsafeLinks && self::isLinkPotentiallyUnsafe($node->/** @scrutinizer ignore-call */ getUrl())) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
55
            $attrs['src'] = '';
56
        } else {
57
            $attrs['src'] = $node->getUrl();
58
        }
59
60
        $alt          = $childRenderer->renderNodes($node->children());
61
        $alt          = \preg_replace('/\<[^>]*alt="([^"]*)"[^>]*\>/', '$1', $alt);
62
        $attrs['alt'] = \preg_replace('/\<[^>]*\>/', '', $alt ?? '');
63
64
        if ($node->data->has('title')) {
65
            $attrs['title'] = $node->data->get('title');
66
        }
67
68
        return new HtmlElement('img', $attrs, '', true);
69
    }
70
71
    public function setConfiguration(ConfigurationInterface $configuration): void
72
    {
73
        $this->config = $configuration;
74
    }
75
76
    /**
77
     * @psalm-pure
78
     */
79
    public static function isLinkPotentiallyUnsafe(string $url): bool
80
    {
81
        return \preg_match(self::REGEX_UNSAFE_PROTOCOL, $url) !== 0 && \preg_match(self::REGEX_SAFE_DATA_PROTOCOL, $url) === 0;
82
    }
83
}
84