• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

FluidTYPO3 / vhs / 13566190336

27 Feb 2025 12:18PM UTC coverage: 72.127% (-0.6%) from 72.746%
13566190336

push

github

NamelessCoder
[TER] 7.1.0

5649 of 7832 relevant lines covered (72.13%)

20.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.6
/Classes/ViewHelpers/Media/YoutubeViewHelper.php
1
<?php
2
namespace FluidTYPO3\Vhs\ViewHelpers\Media;
3

4
/*
5
 * This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.md file that was distributed with this source code.
9
 */
10

11
use FluidTYPO3\Vhs\Traits\TagViewHelperCompatibility;
12
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;
13

14
/**
15
 * Renders HTML code to embed a video from YouTube.
16
 */
17
class YoutubeViewHelper extends AbstractTagBasedViewHelper
18
{
19
    use TagViewHelperCompatibility;
20

21
    /**
22
     * Base url
23
     *
24
     * @var string
25
     */
26
    const YOUTUBE_BASEURL = '//www.youtube.com';
27

28
    /**
29
     * Base url for extended privacy
30
     *
31
     * @var string
32
     */
33
    const YOUTUBE_PRIVACY_BASEURL = '//www.youtube-nocookie.com';
34

35
    /**
36
     * @var string
37
     */
38
    protected $tagName = 'iframe';
39

40
    public function initializeArguments(): void
41
    {
42
        parent::initializeArguments();
7✔
43
        $this->registerUniversalTagAttributes();
7✔
44
        $this->registerArgument('videoId', 'string', 'YouTube id of the video to embed.', true);
7✔
45
        $this->registerArgument(
7✔
46
            'width',
7✔
47
            'integer',
7✔
48
            'Width of the video in pixels. Defaults to 640 for 16:9 content.',
7✔
49
            false,
7✔
50
            640
7✔
51
        );
7✔
52
        $this->registerArgument(
7✔
53
            'height',
7✔
54
            'integer',
7✔
55
            'Height of the video in pixels. Defaults to 385 for 16:9 content.',
7✔
56
            false,
7✔
57
            385
7✔
58
        );
7✔
59
        $this->registerArgument(
7✔
60
            'autoplay',
7✔
61
            'boolean',
7✔
62
            'Play the video automatically on load. Defaults to FALSE.',
7✔
63
            false,
7✔
64
            false
7✔
65
        );
7✔
66
        $this->registerArgument('legacyCode', 'boolean', 'Whether to use the legacy flash video code.', false, false);
7✔
67
        $this->registerArgument(
7✔
68
            'showRelated',
7✔
69
            'boolean',
7✔
70
            'Whether to show related videos after playing.',
7✔
71
            false,
7✔
72
            false
7✔
73
        );
7✔
74
        $this->registerArgument('extendedPrivacy', 'boolean', 'Whether to use cookie-less video player.', false, true);
7✔
75
        $this->registerArgument('hideControl', 'boolean', 'Hide video player\'s control bar.', false, false);
7✔
76
        $this->registerArgument('hideInfo', 'boolean', 'Hide video player\'s info bar.', false, false);
7✔
77
        $this->registerArgument('enableJsApi', 'boolean', 'Enable YouTube JavaScript API', false, false);
7✔
78
        $this->registerArgument('playlist', 'string', 'Comma seperated list of video IDs to be played.');
7✔
79
        $this->registerArgument('loop', 'boolean', 'Play the video in a loop.', false, false);
7✔
80
        $this->registerArgument('start', 'integer', 'Start playing after seconds.');
7✔
81
        $this->registerArgument('end', 'integer', 'Stop playing after seconds.');
7✔
82
        $this->registerArgument('lightTheme', 'boolean', 'Use the YouTube player\'s light theme.', false, false);
7✔
83
        $this->registerArgument(
7✔
84
            'videoQuality',
7✔
85
            'string',
7✔
86
            'Set the YouTube player\'s video quality (hd1080,hd720,highres,large,medium,small).'
7✔
87
        );
7✔
88
        $this->registerArgument(
7✔
89
            'windowMode',
7✔
90
            'string',
7✔
91
            'Set the Window-Mode of the YouTube player (transparent,opaque). This is necessary for ' .
7✔
92
            'z-index handling in IE10/11.'
7✔
93
        );
7✔
94
    }
95

96
    /**
97
     * Render method
98
     *
99
     * @return string
100
     */
101
    public function render()
102
    {
103
        /** @var string $videoId */
104
        $videoId = $this->arguments['videoId'];
7✔
105
        /** @var int $width */
106
        $width = $this->arguments['width'];
7✔
107
        /** @var int height */
108
        $height = $this->arguments['height'];
7✔
109

110
        $this->tag->addAttribute('width', (string) $width);
7✔
111
        $this->tag->addAttribute('height', (string) $height);
7✔
112

113
        $src = $this->getSourceUrl($videoId);
7✔
114

115
        if (!$this->arguments['legacyCode']) {
7✔
116
            $this->tag->addAttribute('src', $src);
7✔
117
            $this->tag->addAttribute('frameborder', '0');
7✔
118
            $this->tag->addAttribute('allowFullScreen', 'allowFullScreen');
7✔
119
            $this->tag->forceClosingTag(true);
7✔
120
        } else {
121
            $this->tag->setTagName('object');
×
122

123
            $tagContent = '';
×
124

125
            $paramAttributes = [
×
126
                'movie' => $src,
×
127
                'allowFullScreen' => 'true',
×
128
                'scriptAccess' => 'always',
×
129
            ];
×
130
            foreach ($paramAttributes as $name => $value) {
×
131
                $tagContent .= $this->renderChildTag('param', [$name => $value], true);
×
132
            }
133

134
            $embedAttributes = [
×
135
                'src' => $src,
×
136
                'type' => 'application/x-shockwave-flash',
×
137
                'width' => $width,
×
138
                'height' => $height,
×
139
                'allowFullScreen' => 'true',
×
140
                'scriptAccess' => 'always',
×
141
            ];
×
142
            $tagContent .= $this->renderChildTag('embed', $embedAttributes, true);
×
143

144
            $this->tag->setContent($tagContent);
×
145
        }
146

147
        return $this->tag->render();
7✔
148
    }
149

150
    /**
151
     * Returns video source url according to provided arguments.
152
     */
153
    private function getSourceUrl(string $videoId): string
154
    {
155
        $src = $this->arguments['extendedPrivacy'] ? static::YOUTUBE_PRIVACY_BASEURL : static::YOUTUBE_BASEURL;
7✔
156

157
        $params = [];
7✔
158

159
        if (!$this->arguments['showRelated']) {
7✔
160
            $params[] = 'rel=0';
7✔
161
        }
162
        if ($this->arguments['autoplay']) {
7✔
163
            $params[] = 'autoplay=1';
×
164
        }
165
        if ($this->arguments['hideControl']) {
7✔
166
            $params[] = 'controls=0';
×
167
        }
168
        if ($this->arguments['hideInfo']) {
7✔
169
            $params[] = 'showinfo=0';
7✔
170
        }
171
        if ($this->arguments['enableJsApi']) {
7✔
172
            $params[] = 'enablejsapi=1';
×
173
        }
174
        if (!empty($this->arguments['playlist'])) {
7✔
175
            $params[] = 'playlist=' . $this->arguments['playlist'];
×
176
        }
177
        if ($this->arguments['loop']) {
7✔
178
            $params[] = 'loop=1';
×
179
        }
180
        if (!empty($this->arguments['start'])) {
7✔
181
            $params[] = 'start=' . $this->arguments['start'];
7✔
182
        }
183
        if (!empty($this->arguments['end'])) {
7✔
184
            $params[] = 'end=' . $this->arguments['end'];
×
185
        }
186
        if ($this->arguments['lightTheme']) {
7✔
187
            $params[] = 'theme=light';
×
188
        }
189
        if (!empty($this->arguments['videoQuality'])) {
7✔
190
            $params[] = 'vq=' . $this->arguments['videoQuality'];
×
191
        }
192
        if (!empty($this->arguments['windowMode'])) {
7✔
193
            $params[] = 'wmode=' . $this->arguments['windowMode'];
×
194
        }
195

196
        if (!$this->arguments['legacyCode']) {
7✔
197
            $src .= '/embed/'. $videoId;
7✔
198
            $seperator = '?';
7✔
199
        } else {
200
            $src .= '/v/' . $videoId . '?version=3';
×
201
            $seperator = '&';
×
202
        }
203

204
        if (!empty($params)) {
7✔
205
            $src .= $seperator . implode('&', $params);
7✔
206
        }
207

208
        return $src;
7✔
209
    }
210

211
    private function renderChildTag(string $tagName, array $attributes = [], bool $forceClosingTag = false): string
212
    {
213
        $tagBuilder = clone $this->tag;
×
214
        $tagBuilder->reset();
×
215
        $tagBuilder->setTagName($tagName);
×
216
        $tagBuilder->addAttributes($attributes);
×
217
        $tagBuilder->forceClosingTag($forceClosingTag);
×
218
        $childTag = $tagBuilder->render();
×
219
        unset($tagBuilder);
×
220

221
        return $childTag;
×
222
    }
223
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc