Passed
Push — 4.2 ( cfc3b8...7d90a1 )
by
unknown
26:25 queued 19:09
created

EmbedShortcodeProvider   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 158
rs 10
c 0
b 0
f 0
wmc 24

6 Methods

Rating   Name   Duplication   Size   Complexity  
A photoEmbed() 0 5 1
B embedForTemplate() 0 16 7
A get_shortcodes() 0 3 1
A linkEmbed() 0 9 2
A videoEmbed() 0 17 3
C handle_shortcode() 0 50 10
1
<?php
2
3
namespace SilverStripe\View\Shortcodes;
4
5
use SilverStripe\Core\Convert;
6
use SilverStripe\Core\Injector\Injector;
7
use SilverStripe\View\Embed\Embeddable;
8
use SilverStripe\View\Embed\EmbedResource;
9
use SilverStripe\View\HTML;
10
use SilverStripe\View\Parsers\ShortcodeHandler;
11
use Embed\Adapters\Adapter;
12
use Embed\Embed;
13
use SilverStripe\View\Parsers\ShortcodeParser;
14
15
/**
16
 * Provider for the [embed] shortcode tag used by the embedding service
17
 * in the HTML Editor field.
18
 * Provides the html needed for the frontend and the editor field itself.
19
 */
20
class EmbedShortcodeProvider implements ShortcodeHandler
21
{
22
23
    /**
24
     * Gets the list of shortcodes provided by this handler
25
     *
26
     * @return mixed
27
     */
28
    public static function get_shortcodes()
29
    {
30
        return array('embed');
31
    }
32
33
    /**
34
     * Embed shortcode parser from Oembed. This is a temporary workaround.
35
     * Oembed class has been replaced with the Embed external service.
36
     *
37
     * @param array $arguments
38
     * @param string $content
39
     * @param ShortcodeParser $parser
40
     * @param string $shortcode
41
     * @param array $extra
42
     *
43
     * @return string
44
     */
45
    public static function handle_shortcode($arguments, $content, $parser, $shortcode, $extra = array())
46
    {
47
        // Get service URL
48
        if (!empty($content)) {
49
            $serviceURL = $content;
50
        } elseif (!empty($arguments['url'])) {
51
            $serviceURL = $arguments['url'];
52
        } else {
53
            return '';
54
        }
55
56
        // See https://github.com/oscarotero/Embed#example-with-all-options for service arguments
57
        $serviceArguments = [];
58
        if (!empty($arguments['width'])) {
59
            $serviceArguments['min_image_width'] = $arguments['width'];
60
        }
61
        if (!empty($arguments['height'])) {
62
            $serviceArguments['min_image_height'] = $arguments['height'];
63
        }
64
65
        /** @var EmbedResource $embed */
66
        $embed = Injector::inst()->create(Embeddable::class, $serviceURL);
67
        if (!empty($serviceArguments)) {
68
            $embed->setOptions(array_merge($serviceArguments, (array) $embed->getOptions()));
69
        }
70
71
        // Allow resolver to be mocked
72
        $dispatcher = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $dispatcher is dead and can be removed.
Loading history...
73
        if (isset($extra['resolver'])) {
74
            $dispatcher = Injector::inst()->create(
75
                $extra['resolver']['class'],
76
                $serviceURL,
77
                $extra['resolver']['config']
78
            );
79
            $embed->setDispatcher($dispatcher);
80
        }
81
82
        // Process embed
83
        $embed = $embed->getEmbed();
84
85
        // Convert embed object into HTML
86
        if ($embed && $embed instanceof Adapter) {
0 ignored issues
show
introduced by
$embed is always a sub-type of Embed\Adapters\Adapter. If $embed can have other possible types, add them to src/View/Shortcodes/EmbedShortcodeProvider.php:65.
Loading history...
87
            $result = static::embedForTemplate($embed, $arguments);
88
            if ($result) {
89
                return $result;
90
            }
91
        }
92
93
        // Fallback to link to service
94
        return static::linkEmbed($arguments, $serviceURL, $serviceURL);
95
    }
96
97
    /**
98
     * @param Adapter $embed
99
     * @param array $arguments Additional shortcode params
100
     * @return string
101
     */
102
    public static function embedForTemplate($embed, $arguments)
103
    {
104
        switch ($embed->getType()) {
105
            case 'video':
106
            case 'rich':
107
                // Attempt to inherit width (but leave height auto)
108
                if (empty($arguments['width']) && $embed->getWidth()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $embed->getWidth() of type null|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
109
                    $arguments['width'] = $embed->getWidth();
110
                }
111
                return self::videoEmbed($arguments, $embed->getCode());
112
            case 'link':
113
                return self::linkEmbed($arguments, $embed->getUrl(), $embed->getTitle());
114
            case 'photo':
115
                return self::photoEmbed($arguments, $embed->getUrl());
116
            default:
117
                return null;
118
        }
119
    }
120
121
    /**
122
     * Build video embed tag
123
     *
124
     * @param array $arguments
125
     * @param string $content Raw HTML content
126
     * @return string
127
     */
128
    protected static function videoEmbed($arguments, $content)
129
    {
130
        // Ensure outer div has given width (but leave height auto)
131
        if (!empty($arguments['width'])) {
132
            $arguments['style'] = 'width: ' . intval($arguments['width']) . 'px;';
133
        }
134
135
        // Convert caption to <p>
136
        if (!empty($arguments['caption'])) {
137
            $xmlCaption = Convert::raw2xml($arguments['caption']);
138
            $content .= "\n<p class=\"caption\">{$xmlCaption}</p>";
139
        }
140
        unset($arguments['width']);
141
        unset($arguments['height']);
142
        unset($arguments['url']);
143
        unset($arguments['caption']);
144
        return HTML::createTag('div', $arguments, $content);
145
    }
146
147
    /**
148
     * Build <a> embed tag
149
     *
150
     * @param array $arguments
151
     * @param string $href
152
     * @param string $title Default title
153
     * @return string
154
     */
155
    protected static function linkEmbed($arguments, $href, $title)
156
    {
157
        $title = !empty($arguments['caption']) ? ($arguments['caption']) : $title;
158
        unset($arguments['caption']);
159
        unset($arguments['width']);
160
        unset($arguments['height']);
161
        unset($arguments['url']);
162
        $arguments['href'] = $href;
163
        return HTML::createTag('a', $arguments, Convert::raw2xml($title));
0 ignored issues
show
Bug introduced by
It seems like SilverStripe\Core\Convert::raw2xml($title) can also be of type array; however, parameter $content of SilverStripe\View\HTML::createTag() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

163
        return HTML::createTag('a', $arguments, /** @scrutinizer ignore-type */ Convert::raw2xml($title));
Loading history...
164
    }
165
166
    /**
167
     * Build img embed tag
168
     *
169
     * @param array $arguments
170
     * @param string $src
171
     * @return string
172
     */
173
    protected static function photoEmbed($arguments, $src)
174
    {
175
        $arguments['src'] = $src;
176
        unset($arguments['url']);
177
        return HTML::createTag('img', $arguments);
178
    }
179
}
180