Passed
Pull Request — 4 (#8843)
by Daniel
08:11
created

EmbedShortcodeProvider   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 151
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 57
dl 0
loc 151
rs 10
c 0
b 0
f 0
wmc 23

6 Methods

Rating   Name   Duplication   Size   Complexity  
A get_shortcodes() 0 3 1
B handle_shortcode() 0 43 9
A photoEmbed() 0 5 1
B embedForTemplate() 0 16 7
A linkEmbed() 0 9 2
A videoEmbed() 0 17 3
1
<?php
2
3
namespace SilverStripe\View\Shortcodes;
4
5
use SilverStripe\Core\Convert;
6
use SilverStripe\Core\Injector\Injector;
7
use SilverStripe\View\HTML;
8
use SilverStripe\View\Parsers\ShortcodeHandler;
9
use Embed\Adapters\Adapter;
10
use Embed\Embed;
11
use SilverStripe\View\Parsers\ShortcodeParser;
12
13
/**
14
 * Provider for the [embed] shortcode tag used by the embedding service
15
 * in the HTML Editor field.
16
 * Provides the html needed for the frontend and the editor field itself.
17
 */
18
class EmbedShortcodeProvider implements ShortcodeHandler
19
{
20
21
    /**
22
     * Gets the list of shortcodes provided by this handler
23
     *
24
     * @return mixed
25
     */
26
    public static function get_shortcodes()
27
    {
28
        return array('embed');
29
    }
30
31
    /**
32
     * Embed shortcode parser from Oembed. This is a temporary workaround.
33
     * Oembed class has been replaced with the Embed external service.
34
     *
35
     * @param array $arguments
36
     * @param string $content
37
     * @param ShortcodeParser $parser
38
     * @param string $shortcode
39
     * @param array $extra
40
     *
41
     * @return string
42
     */
43
    public static function handle_shortcode($arguments, $content, $parser, $shortcode, $extra = array())
44
    {
45
        // Get service URL
46
        if (!empty($content)) {
47
            $serviceURL = $content;
48
        } elseif (!empty($arguments['url'])) {
49
            $serviceURL = $arguments['url'];
50
        } else {
51
            return '';
52
        }
53
54
        // See https://github.com/oscarotero/Embed#example-with-all-options for service arguments
55
        $serviceArguments = [];
56
        if (!empty($arguments['width'])) {
57
            $serviceArguments['min_image_width'] = $arguments['width'];
58
        }
59
        if (!empty($arguments['height'])) {
60
            $serviceArguments['min_image_height'] = $arguments['height'];
61
        }
62
63
        // Allow resolver to be mocked
64
        $dispatcher = null;
65
        if (isset($extra['resolver'])) {
66
            $dispatcher = Injector::inst()->create(
67
                $extra['resolver']['class'],
68
                $serviceURL,
69
                $extra['resolver']['config']
70
            );
71
        }
72
73
        // Process embed
74
        $embed = Embed::create($serviceURL, $serviceArguments, $dispatcher);
75
76
        // Convert embed object into HTML
77
        if ($embed && $embed instanceof Adapter) {
0 ignored issues
show
introduced by
$embed is always a sub-type of Embed\Adapters\Adapter.
Loading history...
78
            $result = static::embedForTemplate($embed, $arguments);
79
            if ($result) {
80
                return $result;
81
            }
82
        }
83
84
        // Fallback to link to service
85
        return static::linkEmbed($arguments, $serviceURL, $serviceURL);
86
    }
87
88
    /**
89
     * @param Adapter $embed
90
     * @param array $arguments Additional shortcode params
91
     * @return string
92
     */
93
    public static function embedForTemplate($embed, $arguments)
94
    {
95
        switch ($embed->getType()) {
96
            case 'video':
97
            case 'rich':
98
                // Attempt to inherit width (but leave height auto)
99
                if (empty($arguments['width']) && $embed->getWidth()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $embed->getWidth() of type integer|null 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...
100
                    $arguments['width'] = $embed->getWidth();
101
                }
102
                return self::videoEmbed($arguments, $embed->getCode());
103
            case 'link':
104
                return self::linkEmbed($arguments, $embed->getUrl(), $embed->getTitle());
105
            case 'photo':
106
                return self::photoEmbed($arguments, $embed->getUrl());
107
            default:
108
                return null;
109
        }
110
    }
111
112
    /**
113
     * Build video embed tag
114
     *
115
     * @param array $arguments
116
     * @param string $content Raw HTML content
117
     * @return string
118
     */
119
    protected static function videoEmbed($arguments, $content)
120
    {
121
        // Ensure outer div has given width (but leave height auto)
122
        if (!empty($arguments['width'])) {
123
            $arguments['style'] = 'width: ' . intval($arguments['width']) . 'px;';
124
        }
125
126
        // Convert caption to <p>
127
        if (!empty($arguments['caption'])) {
128
            $xmlCaption = Convert::raw2xml($arguments['caption']);
129
            $content .= "\n<p class=\"caption\">{$xmlCaption}</p>";
130
        }
131
        unset($arguments['width']);
132
        unset($arguments['height']);
133
        unset($arguments['url']);
134
        unset($arguments['caption']);
135
        return HTML::createTag('div', $arguments, $content);
136
    }
137
138
    /**
139
     * Build <a> embed tag
140
     *
141
     * @param array $arguments
142
     * @param string $href
143
     * @param string $title Default title
144
     * @return string
145
     */
146
    protected static function linkEmbed($arguments, $href, $title)
147
    {
148
        $title = !empty($arguments['caption']) ? ($arguments['caption']) : $title;
149
        unset($arguments['caption']);
150
        unset($arguments['width']);
151
        unset($arguments['height']);
152
        unset($arguments['url']);
153
        $arguments['href'] = $href;
154
        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 and 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

154
        return HTML::createTag('a', $arguments, /** @scrutinizer ignore-type */ Convert::raw2xml($title));
Loading history...
155
    }
156
157
    /**
158
     * Build img embed tag
159
     *
160
     * @param array $arguments
161
     * @param string $src
162
     * @return string
163
     */
164
    protected static function photoEmbed($arguments, $src)
165
    {
166
        $arguments['src'] = $src;
167
        unset($arguments['url']);
168
        return HTML::createTag('img', $arguments);
169
    }
170
}
171