• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FluidTYPO3 / vhs / 30001290505

23 Jul 2026 10:57AM UTC coverage: 70.309% (-1.7%) from 72.022%
30001290505

push

github

NamelessCoder
[TER] 8.0.0

4819 of 6854 relevant lines covered (70.31%)

6.54 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
    private const string YOUTUBE_BASEURL = '//www.youtube.com';
27

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

96
    public function render(): string
97
    {
98
        /** @var string $videoId */
99
        $videoId = $this->arguments['videoId'];
3✔
100
        /** @var int $width */
101
        $width = $this->arguments['width'];
3✔
102
        /** @var int height */
103
        $height = $this->arguments['height'];
3✔
104

105
        $this->tag->addAttribute('width', (string) $width);
3✔
106
        $this->tag->addAttribute('height', (string) $height);
3✔
107

108
        $src = $this->getSourceUrl($videoId);
3✔
109

110
        if (!$this->arguments['legacyCode']) {
3✔
111
            $this->tag->addAttribute('src', $src);
3✔
112
            $this->tag->addAttribute('frameborder', '0');
3✔
113
            $this->tag->addAttribute('allowFullScreen', 'allowFullScreen');
3✔
114
            $this->tag->forceClosingTag(true);
3✔
115
        } else {
116
            $this->tag->setTagName('object');
×
117

118
            $tagContent = '';
×
119

120
            $paramAttributes = [
×
121
                'movie' => $src,
×
122
                'allowFullScreen' => 'true',
×
123
                'scriptAccess' => 'always',
×
124
            ];
×
125
            foreach ($paramAttributes as $name => $value) {
×
126
                $tagContent .= $this->renderChildTag('param', [$name => $value], true);
×
127
            }
128

129
            $embedAttributes = [
×
130
                'src' => $src,
×
131
                'type' => 'application/x-shockwave-flash',
×
132
                'width' => $width,
×
133
                'height' => $height,
×
134
                'allowFullScreen' => 'true',
×
135
                'scriptAccess' => 'always',
×
136
            ];
×
137
            $tagContent .= $this->renderChildTag('embed', $embedAttributes, true);
×
138

139
            $this->tag->setContent($tagContent);
×
140
        }
141

142
        return $this->tag->render();
3✔
143
    }
144

145
    /**
146
     * Returns video source url according to provided arguments.
147
     */
148
    private function getSourceUrl(string $videoId): string
149
    {
150
        $src = $this->arguments['extendedPrivacy'] ? self::YOUTUBE_PRIVACY_BASEURL : self::YOUTUBE_BASEURL;
3✔
151

152
        $params = [];
3✔
153

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

191
        if (!$this->arguments['legacyCode']) {
3✔
192
            $src .= '/embed/'. $videoId;
3✔
193
            $seperator = '?';
3✔
194
        } else {
195
            $src .= '/v/' . $videoId . '?version=3';
×
196
            $seperator = '&';
×
197
        }
198

199
        if (!empty($params)) {
3✔
200
            $src .= $seperator . implode('&', $params);
3✔
201
        }
202

203
        return $src;
3✔
204
    }
205

206
    private function renderChildTag(string $tagName, array $attributes = [], bool $forceClosingTag = false): string
207
    {
208
        $tagBuilder = clone $this->tag;
×
209
        $tagBuilder->reset();
×
210
        $tagBuilder->setTagName($tagName);
×
211
        $tagBuilder->addAttributes($attributes);
×
212
        $tagBuilder->forceClosingTag($forceClosingTag);
×
213
        $childTag = $tagBuilder->render();
×
214
        unset($tagBuilder);
×
215

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

© 2026 Coveralls, Inc