├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── composer.json
└── embedder
├── Embedder.php
├── fields
└── EmbedderFieldType.php
├── icon.svg
├── migrations
└── m180412_205549_update_embedder_fields.php
├── services
└── EmbedderService.php
├── templates
└── _fields
│ └── input.twig
└── variables
└── EmbedderVariable.php
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS Files
2 | .DS_Store
3 | Thumbs.db
4 |
5 | # Dependencies
6 | /vendor
7 | *composer.lock
8 |
9 | # Log Files
10 | *.log
11 |
12 | # Editors
13 | /.idea
14 | /.vscode
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Embedder Changelog
2 |
3 | ## 4.0.0 - 2024-08-18
4 | ### Added
5 | - Add support for Craft 5
6 | - Drop support for Craft 4
7 |
8 | ## 3.0.0 - 2022-05-23
9 |
10 | ### Added
11 |
12 | - Add support for Craft 4
13 | - Drop support for Craft 3
14 |
15 | ## 2.0.3 - 2022-1-25
16 |
17 | ### Added
18 |
19 | - Add support for YouTube privacy-enhanced mode via `youtube_privacyEnhanced` parameter
20 |
21 | ## 2.0.2 - 2021-8-19
22 |
23 | ### Fixed
24 |
25 | - Fix code that handles graceful failure when a video is not found
26 |
27 | ### Changed
28 |
29 | - Add type hinting to EmbedderService
30 |
31 | ## 2.0.1 - 2020-12-15
32 |
33 | ### Fixed
34 |
35 | - Removed force_https setting as YouTube only accepts https now
36 | - Removed bug fix for YouTube videos over 612px as it doesn't work with the new API
37 |
38 | ## 2.0.0 - 2019-01-16
39 |
40 | ### Added
41 |
42 | - Added support for Craft 3
43 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 Jonathan Sarmiento
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Embedder
2 |
3 | Embedder is a plugin for Craft CMS based on [Antenna](https://github.com/vector/Antenna) by Vector Media Group that will generate embed code for YouTube, Vimeo, Wistia, or Viddler. It also gives you access to the video’s title, its author, the author’s YouTube/Vimeo URL, and a thumbnail. All you have to do is pass it a single URL.
4 |
5 | You can also output various pieces of metadata about the video.
6 |
7 | ## Requirements
8 |
9 | This plugin requires Craft 5 or later.
10 |
11 | > For the Craft 2 version, see the [v1 branch](https://github.com/jdsdev/Embedder/tree/v1)
12 |
13 | ## Installation
14 |
15 | To install the plugin, follow these instructions.
16 |
17 | 1. Open your terminal and go to your Craft project:
18 |
19 | cd /path/to/project
20 |
21 | 2. Then tell Composer to load the plugin:
22 |
23 | composer require jdsdev/craft-embedder
24 |
25 | 3. In the Control Panel, go to Settings → Plugins and click the “Install” button for Embedder.
26 |
27 | ---
28 |
29 | ## Simple Usage
30 |
31 | If used as a single tag (embedder.embed), it returns the HTML embed/object code for the video.
32 |
33 | ```twig
34 | {{ craft.embedder.embed (entry.embedderVideo, {max_width:500, max_height:800}) }}
35 | ```
36 |
37 | ## Full Usage and Variables
38 |
39 | If used by setting the video URL, you get access to several variables.
40 |
41 | ```twig
42 | {% set video = craft.embedder.url(entry.embedderVideo, {max_width:500, max_height:800}) %}
43 |
44 | {{ video.embed_code }}
45 |
46 |
title : {{ video.video_title }}
47 |
description : {{ video.video_description }}
48 |
thumbnail :
49 |
50 | ```
51 |
52 | There are three image sizes available for videos: `video_thumbnail`, `video_mediumres`, and `video_highres`. They are not consistent across services but they should fall into rough size brackets. `video_thumbnail` is going to be between 100-200px wide; `video_mediumres` will be around 400-500px wide; and `video_highres` will be at least the full size of your uploaded video and could be as wide as 1280px.
53 |
54 | ## Parameters
55 |
56 | ### Dimensions
57 |
58 | Set the `max_width` and/or `max_height` for whatever size your website requires. The video will be resized to be within those dimensions, and will stay at the correct proportions.
59 |
60 | - `max_width: 500` - Can be any number. Left unspecified by default.
61 | - `max_height: 800` - Can be any number. Left unspecified by default.
62 |
63 | ### YouTube
64 |
65 | If you're using YouTube, you can use any of the [supported embed parameters](https://developers.google.com/youtube/player_parameters#Parameters). Simply prefix the parameters with `youtube_`. Here are some common parameters:
66 |
67 | - `youtube_rel: 0` - Show related videos at the end of the video. Can be `0` or `1` (default).
68 | - `youtube_showinfo: 0` - Show the video title overlay. Can be `0` or `1` (default).
69 | - `youtube_controls: 0` - Show the video player controls. Can be `0` or `1` (default).
70 | - `youtube_autoplay: 1` - Automatically start playback of the video. Can be `0` (default) or `1`.
71 | - `youtube_enablejsapi: 1` - Enable the YouTube IFrame or JavaScript APIs. Can be `0` (default) or `1`.
72 |
73 | Additionally the following non-standard parameter is available when using YouTube:
74 |
75 | - `youtube_privacyEnhanced: 1` - Use [YouTube's privacy-enhanced mode](https://support.google.com/youtube/answer/171780#zippy=%2Cturn-on-privacy-enhanced-mode). Can be `0` (default) or `1`.
76 |
77 | ### Vimeo
78 |
79 | If you're using Vimeo, you can use any of the [supported embed parameters](https://github.com/vimeo/player.js#embed-options). Simply prefix the parameters with `vimeo_`. Here are some of the common parameters:
80 |
81 | - `vimeo_byline: 0` - Shows the byline on the video. Can be `0` or `1` (default).
82 | - `vimeo_title: 0` - Shows the title on the video. Can be `0` or `1` (default).
83 | - `vimeo_portrait: 0` - Shows the user's avatar on the video. Can be `0` or `1` (default).
84 | - `vimeo_loop: 1` - Loops the video playback. Can be `0` (default) or `1`.
85 | - `vimeo_autoplay: 1` - Automatically start playback of the video. Can be `0` (default) or `1`.
86 | - `vimeo_color: 'ff0000'` - Sets the theme color for the Vimeo player. Can be any hexidecimal color value (without the hash). Defaults to `'00adef'`.
87 |
88 | You can also use the following Vimeo parameter:
89 |
90 | - `vimeo_player_id: 'myVideoPlayer'` - Sets an ID on the player, which is useful if you want to control multiple videos on the same page in a different way.
91 |
92 | The following extra variable is available when using Vimeo:
93 |
94 | - `{{ video_description }}` - The description of the video, as set in Vimeo
95 |
96 | ### Viddler
97 |
98 | If you're using Viddler, you get access to two more parameters:
99 |
100 | - `viddler_type: 'simple'` - Specifies the player type. Can be `'simple'` or `'player'` (default).
101 | - `viddler_ratio: 'widescreen'` - Aspect ratio. Can be `'widescreen'`, `'fullscreen'`, or left unspecified for automatically determined aspect ratio.
102 |
103 | ### Wistia
104 |
105 | If you're using Wistia, you get access to two more parameters:
106 |
107 | - `wistia_type` - Sets the supported embed type.
108 | - `wistia_foam: true` - Makes the embedded video responsive using Wistia's Video Foam feature.
109 |
110 | ### HTML Output Control
111 |
112 | You can also control your output with the following parameters:
113 |
114 | - `id: 'myId'` - Gives the iFrame an `id=` attribute with the specified value.
115 | - `class: 'video player'` - Gives the iFrame a `class=` attribute with the specified value.
116 | - `attributes: 'data-video data-player'` - Gives the iFrame the specified HTML attribute(s).
117 |
118 | ### wmode (deprecated with most providers)
119 |
120 | The optional `wmode` parameter can be used if you're experiencing issues positioning HTML content in front of the embedded media. It accepts values of `transparent`, `opaque` and `window`.
121 |
122 | ---
123 |
124 | ## Contributions
125 |
126 | - [Adam Powell](https://github.com/A-P) - Original plugin author.
127 |
128 | - [Aaron Waldon](https://github.com/aaronwaldon) / @aaronwaldon - Reworked the logic to allow any provider parameters to be used. Added HTML output control parameters and updated the documentation.
129 |
130 | - [Jonathan Sarmiento](https://github.com/jdsdev) - Updated the plugin for Craft 3 and Craft 4.
131 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jdsdev/craft-embedder",
3 | "description": "Generate video embed code.",
4 | "version": "4.0.0",
5 | "type": "craft-plugin",
6 | "license": "MIT",
7 | "keywords": [
8 | "craft",
9 | "cms",
10 | "craftcms",
11 | "craft-plugin",
12 | "embedder"
13 | ],
14 | "authors": [
15 | {
16 | "name": "jonathan@jdsdev.com",
17 | "homepage": "https://jdsdev.com/"
18 | }
19 | ],
20 | "require": {
21 | "craftcms/cms": "^5.0.0-beta.1",
22 | "php": "^8.2"
23 | },
24 | "autoload": {
25 | "psr-4": {
26 | "jdsdev\\embedder\\": "embedder/"
27 | }
28 | },
29 | "extra": {
30 | "name": "Embedder",
31 | "handle": "embedder",
32 | "changelogUrl": "https://raw.githubusercontent.com/jdsdev/Embedder/master/CHANGELOG.md",
33 | "components": {
34 | "embedder": "jdsdev\\embedder\\services\\EmbedderService"
35 | },
36 | "class": "jdsdev\\embedder\\Embedder"
37 | },
38 | "config": {
39 | "allow-plugins": {
40 | "yiisoft/yii2-composer": true,
41 | "craftcms/plugin-installer": true
42 | }
43 | },
44 | "minimum-stability": "dev",
45 | "prefer-stable": true,
46 | "require-dev": {
47 | "craftcms/rector": "dev-main"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/embedder/Embedder.php:
--------------------------------------------------------------------------------
1 | types[] = EmbedderFieldType::class;
52 | }
53 | );
54 |
55 | // Register variables
56 | Event::on(
57 | CraftVariable::class,
58 | CraftVariable::EVENT_INIT,
59 | function (Event $event) {
60 | $variable = $event->sender;
61 | $variable->set('embedder', EmbedderVariable::class);
62 | }
63 | );
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/embedder/fields/EmbedderFieldType.php:
--------------------------------------------------------------------------------
1 | $this->handle,
35 | 'value' => $value,
36 | 'field' => $this,
37 | ];
38 |
39 | return Craft::$app->getView()->renderTemplate(
40 | 'embedder/_fields/input',
41 | $variables
42 | );
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/embedder/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/embedder/migrations/m180412_205549_update_embedder_fields.php:
--------------------------------------------------------------------------------
1 | update('{{%fields}}', [
20 | 'type' => EmbedderFieldType::class
21 | ], [
22 | 'type' => 'Embedder'
23 | ], [], false);
24 | }
25 |
26 | /**
27 | * @inheritdoc
28 | */
29 | public function safeDown()
30 | {
31 | echo "m180412_205549_update_embedder_fields cannot be reverted.\n";
32 | return false;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/embedder/services/EmbedderService.php:
--------------------------------------------------------------------------------
1 | 'video_title',
33 | 'html' => 'embed_code',
34 | 'author_name' => 'video_author',
35 | 'author_url' => 'video_author_url',
36 | 'thumbnail_url' => 'video_thumbnail',
37 | 'medres_url' => 'video_mediumres',
38 | 'highres_url' => 'video_highres',
39 | 'description' => 'video_description',
40 | ];
41 |
42 | $video_data = [];
43 |
44 | foreach ($plugin_vars as $var)
45 | {
46 | $video_data[$var] = false;
47 | }
48 |
49 | // if it's not YouTube, Vimeo, Wistia, or Viddler bail
50 | if ($isYouTube)
51 | {
52 | $url = 'https://www.youtube.com/oembed?format=xml&iframe=1&url=';
53 | }
54 | elseif ($isVimeo)
55 | {
56 | $url = 'https://vimeo.com/api/oembed.xml?url=';
57 | }
58 | elseif ($isWistia)
59 | {
60 | $url = 'http://app.wistia.com/embed/oembed.xml?url=';
61 | }
62 | elseif ($isViddler)
63 | {
64 | $url = 'http://www.viddler.com/oembed/?format=xml&url=';
65 | }
66 | else
67 | {
68 | return $output === 'simple' ? '' : $video_data;
69 | }
70 | $url .= urlencode($video_url);
71 |
72 | // set the semi-ubiquitous parameters
73 | $max_width = isset($params['max_width']) ? '&maxwidth=' . $params['max_width'] : '';
74 | $max_height = isset($params['max_height']) ? '&maxheight=' . $params['max_height'] : '';
75 | $wmode_param = isset($params['wmode']) ? '&wmode=' . $params['wmode'] : '';
76 | $url .= $max_width . $max_height . $wmode_param;
77 |
78 | // cache can be disabled by setting 0 as the cache_minutes param
79 | if (isset($params['cache_minutes']) && $params['cache_minutes'] !== false && is_numeric($params['cache_minutes']))
80 | {
81 | $cache_refresh_minutes = $params['cache_minutes'];
82 | }
83 |
84 | // optional provider prefixed parameters
85 | $providerExtraParams = [];
86 | if ($isVimeo)
87 | {
88 | $providerExtraParams = $this->getPrefixedParams($params, 'vimeo_');
89 | }
90 | elseif ($isWistia)
91 | {
92 | $providerExtraParams = $this->getPrefixedParams($params, 'wistia_');
93 |
94 | // handle legacy shortcuts
95 | if (isset($providerExtraParams['type']))
96 | {
97 | $providerExtraParams['embedType'] = $providerExtraParams['type'];
98 | unset($providerExtraParams['type']);
99 | }
100 | if (isset($providerExtraParams['foam']))
101 | {
102 | $providerExtraParams['videoFoam'] = $providerExtraParams['foam'];
103 | unset($providerExtraParams['foam']);
104 | }
105 | }
106 | elseif ($isViddler)
107 | {
108 | $providerExtraParams = $this->getPrefixedParams($params, 'viddler_');
109 | }
110 | if (!empty($providerExtraParams))
111 | {
112 | $url .= '&' . $this->makeUrlKeyValuePairsString($providerExtraParams);
113 | }
114 |
115 | // checking if url has been cached
116 | $cached_url = Craft::$app->cache->get($url);
117 |
118 | if (!$cache_refresh_minutes || $is_cache_expired || !$cached_url)
119 | {
120 | // create the info and header variables
121 | list($video_info, $video_header) = $this->getVideoInfo($url);
122 |
123 | // write the data to cache if caching hasn't been disabled
124 | if ($cache_refresh_minutes)
125 | {
126 | Craft::$app->cache->set($url, $video_info, $cache_refresh_minutes);
127 | }
128 | }
129 | else
130 | {
131 | $video_info = $cached_url;
132 | }
133 |
134 | // decode the cURL data
135 | libxml_use_internal_errors(true);
136 |
137 | $video_info = simplexml_load_string($video_info);
138 |
139 | // gracefully fail if the video is not found
140 | if ($video_info === false)
141 | {
142 | return $output === 'simple' ? 'Video not found' : $video_data;
143 | }
144 |
145 | // inject wmode transparent if required
146 | $wmode = $params['wmode'] ?? '';
147 | if ($wmode === 'transparent' || $wmode === 'opaque' || $wmode === 'window')
148 | {
149 | $param_str = '';
150 | $embed_str = ' wmode="' . $wmode . '" ';
151 |
152 | // determine whether we are dealing with iframe or embed and handle accordingly
153 | if (strpos($video_info->html, '