Completed
Push — master ( 15b4cf...ad9d4e )
by
unknown
08:03
created

EmbedShortcodeProvider::linkEmbed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 3
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
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) {
78
            $result = static::embedForTemplate($embed, $arguments);
79
            if ($result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type string|null is loosely compared to true; this is ambiguous if the string can be empty. 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 string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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 null|integer is loosely compared to true; this is ambiguous if the integer can be zero. 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) targeting SilverStripe\Core\Convert::raw2xml() can also be of type array; however, SilverStripe\View\HTML::createTag() does only seem to accept string|null, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

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