YouTube Channel - Version 3.0.7

Version Description

(2015-05-17) = * Fix: Uncaught TypeError: e(...).fitVids is not a function * Change: Remove plugin default Channel ID, Vanity custom name, Legacy username and Playlist ID; leave them empty by default and allow them to be empty parameters; throw error if required value not provided. All this to prevent questions like Why I see your videos on my website or Why my website link to your channel * Cleanup: Deprecated widget toggler for Playlist Only depending on selected Resource * Cleanup: Deprecated 16:10 styles * Optimize: Minimize admin style for widget layout

Download this release

Release Info

Developer urkekg
Plugin Icon YouTube Channel
Version 3.0.7
Comparing to
See all releases

Code changes from version 3.0.6.2 to 3.0.7

assets/css/admin.min.css ADDED
@@ -0,0 +1 @@
 
1
+ div[id*='_youtube-channel-'] .widget-content p{width:100%;clear:both}div[id*='_youtube-channel-'] .widget-content p.half{width:49%}div[id*='_youtube-channel-'] .widget-content p.glue-top{margin-top:0}div[id*='_youtube-channel-'] .widget-content p.half.left{float:left;clear:left}div[id*='_youtube-channel-'] .widget-content p.half.right{float:right;clear:right}div[id*='_youtube-channel-'] .widget-content p.hidden{display:none}div[id*='_youtube-channel-'] .widget-content p.visible{display:block}@media screen and (max-width:782px){div[id*='_youtube-channel-'] .widget-content p.half.left,div[id*='_youtube-channel-'] .widget-content p.half.right{width:100%;float:none;clear:none}}
assets/css/youtube-channel.css CHANGED
@@ -71,11 +71,6 @@
71
  .ytc_thumb.ar16_9>span:before {
72
  padding-bottom: 56.26%;
73
  }
74
- .ytc_thumb.ar16_10,
75
- .ytc_thumb.ar16_10>span,
76
- .ytc_thumb.ar16_10>span:before {
77
- padding-bottom: 62.5%;
78
- }
79
  .ytc_thumb.ar4_3,
80
  .ytc_thumb.ar4_3>span,
81
  .ytc_thumb.ar4_3>span:before {
@@ -91,11 +86,6 @@ padding-bottom: 75%;
91
  padding-bottom: 56.25%; /* 16:9 */
92
  height: 0;
93
  }
94
- .youtube_channel.responsive .ytc_video_container.ar16_10 .fluid-width-video-wrapper {
95
- position: relative;
96
- padding-bottom: 62.5%; /* 16:10 */
97
- height: 0;
98
- }
99
  .youtube_channel.responsive .ytc_video_container.ar4_3 .fluid-width-video-wrapper {
100
  position: relative;
101
  padding-bottom: 75%; /* 4:3; */
71
  .ytc_thumb.ar16_9>span:before {
72
  padding-bottom: 56.26%;
73
  }
 
 
 
 
 
74
  .ytc_thumb.ar4_3,
75
  .ytc_thumb.ar4_3>span,
76
  .ytc_thumb.ar4_3>span:before {
86
  padding-bottom: 56.25%; /* 16:9 */
87
  height: 0;
88
  }
 
 
 
 
 
89
  .youtube_channel.responsive .ytc_video_container.ar4_3 .fluid-width-video-wrapper {
90
  position: relative;
91
  padding-bottom: 75%; /* 4:3; */
assets/css/youtube-channel.min.css CHANGED
@@ -1 +1 @@
1
- .ytc_thumb>span,.ytc_thumb>span:before{background-position:center center;background-repeat:no-repeat}.clearfix{clear:both}.youtube_channel{float:left;clear:both;position:relative;box-sizing:border-box}.youtube_channel.responsive{width:100%}.widget_youtube-channel:after,.youtube_channel:after{visibility:hidden;display:block;font-size:0;content:" ";clear:both;height:0}.youtube_channel .ytc_video_container{float:left}.youtube_channel.responsive .ytc_video_container{width:100%!important}.youtube_channel .ytc_video_container a{border:none}.ytc_thumb{display:block;overflow:hidden;position:relative;height:0;width:100%;top:0;right:0;bottom:0;left:0}.ytc_thumb>span{height:0;width:100%;display:block;-webkit-background-size:cover;background-size:cover}.ytc_thumb>span:before{content:"";display:block;width:100%;height:0;background-image:url(../img/play.png);background-color:transparent;opacity:.6;transition:.4s}.ytc_thumb:hover>span:before{opacity:1}.ytc_thumb.ar16_9,.ytc_thumb.ar16_9>span,.ytc_thumb.ar16_9>span:before{padding-bottom:56.26%}.ytc_thumb.ar16_10,.ytc_thumb.ar16_10>span,.ytc_thumb.ar16_10>span:before{padding-bottom:62.5%}.ytc_thumb.ar4_3,.ytc_thumb.ar4_3>span,.ytc_thumb.ar4_3>span:before{padding-bottom:75%}.youtube_channel .ytc_video_container iframe{margin-bottom:0}.youtube_channel.responsive .ytc_video_container.ar16_9 .fluid-width-video-wrapper{position:relative;padding-bottom:56.25%;height:0}.youtube_channel.responsive .ytc_video_container.ar16_10 .fluid-width-video-wrapper{position:relative;padding-bottom:62.5%;height:0}.youtube_channel.responsive .ytc_video_container.ar4_3 .fluid-width-video-wrapper{position:relative;padding-bottom:75%;height:0}.youtube_channel.responsive .ytc_video_container .fluid-width-video-wrapper iframe{position:absolute;top:0;left:0;width:100%;height:100%}.youtube_channel .ytc_link{position:relative;clear:both;float:left;width:100%}.youtube_channel .ytc_link>p{padding:0;margin:0}
1
+ .ytc_thumb>span,.ytc_thumb>span:before{background-position:center center;background-repeat:no-repeat}.clearfix{clear:both}.youtube_channel{float:left;clear:both;position:relative;box-sizing:border-box}.youtube_channel.responsive{width:100%}.widget_youtube-channel:after,.youtube_channel:after{visibility:hidden;display:block;font-size:0;content:" ";clear:both;height:0}.youtube_channel .ytc_video_container{float:left}.youtube_channel.responsive .ytc_video_container{width:100%!important}.youtube_channel .ytc_video_container a{border:none}.ytc_thumb{display:block;overflow:hidden;position:relative;height:0;width:100%;top:0;right:0;bottom:0;left:0}.ytc_thumb>span{height:0;width:100%;display:block;-webkit-background-size:cover;background-size:cover}.ytc_thumb>span:before{content:"";display:block;width:100%;height:0;background-image:url(../img/play.png);background-color:transparent;opacity:.6;transition:.4s}.ytc_thumb:hover>span:before{opacity:1}.ytc_thumb.ar16_9,.ytc_thumb.ar16_9>span,.ytc_thumb.ar16_9>span:before{padding-bottom:56.26%}.ytc_thumb.ar4_3,.ytc_thumb.ar4_3>span,.ytc_thumb.ar4_3>span:before{padding-bottom:75%}.youtube_channel .ytc_video_container iframe{margin-bottom:0}.youtube_channel.responsive .ytc_video_container.ar16_9 .fluid-width-video-wrapper{position:relative;padding-bottom:56.25%;height:0}.youtube_channel.responsive .ytc_video_container.ar4_3 .fluid-width-video-wrapper{position:relative;padding-bottom:75%;height:0}.youtube_channel.responsive .ytc_video_container .fluid-width-video-wrapper iframe{position:absolute;top:0;left:0;width:100%;height:100%}.youtube_channel .ytc_link{position:relative;clear:both;float:left;width:100%}.youtube_channel .ytc_link>p{padding:0;margin:0}
assets/js/admin.js CHANGED
@@ -1,46 +1,27 @@
1
- jQuery(document).ready(function($){
2
-
3
- $('select[id*="-use_res"]').each(function(e, i){
4
- ytc_toggle_widget_option_select($(this).attr('id'), 2);
5
- });
6
- $('select[id*="-use_res"]').on('change', function(e, i){
7
- ytc_toggle_widget_option_select($(this).attr('id'), 2);
8
- });
9
- $('input[id*="-showgoto"]').each(function(e, i){
10
- ytc_toggle_widget_option_checkbox($(this).attr('id'));
11
- });
12
- $('input[id*="-showgoto"]').on('change', function(e, i){
13
- ytc_toggle_widget_option_checkbox($(this).attr('id'));
14
- });
15
-
16
- $(document).ajaxSuccess(function(e, xhr, settings){
17
- $('select[id*="-use_res"]').each(function(e, i){
18
- ytc_toggle_widget_option_select($(this).attr('id'), 2);
19
- });
20
- $('select[id*="-use_res"]').on('change', function(e, i){
21
- ytc_toggle_widget_option_select($(this).attr('id'), 2);
22
- });
23
- $('input[id*="-showgoto"]').each(function(e, i){
24
- ytc_toggle_widget_option_checkbox($(this).attr('id'));
25
- });
26
- $('input[id*="-showgoto"]').on('change', function(e, i){
27
- ytc_toggle_widget_option_checkbox($(this).attr('id'));
28
- });
29
- });
30
-
31
- function ytc_toggle_widget_option_select(id, value) {
32
- if ( $('#' + id).val() == value ) {
33
- $('p.' + id).addClass('visible').removeClass('hidden');
34
- } else {
35
- $('p.' + id).addClass('hidden').removeClass('visible');
36
- }
37
- }
38
- function ytc_toggle_widget_option_checkbox(id) {
39
- if ( $('#' + id).attr('checked') === 'checked' ) {
40
- $('p.' + id).addClass('visible').removeClass('hidden');
41
- } else {
42
- $('p.' + id).addClass('hidden').removeClass('visible');
43
- }
44
- }
45
-
46
  });
1
+ jQuery(document).ready(function($){
2
+
3
+ $('input[id*="-showgoto"]').each(function(e, i){
4
+ ytc_toggle_widget_option_checkbox($(this).attr('id'));
5
+ });
6
+ $('input[id*="-showgoto"]').on('change', function(e, i){
7
+ ytc_toggle_widget_option_checkbox($(this).attr('id'));
8
+ });
9
+
10
+ $(document).ajaxSuccess(function(e, xhr, settings){
11
+ $('input[id*="-showgoto"]').each(function(e, i){
12
+ ytc_toggle_widget_option_checkbox($(this).attr('id'));
13
+ });
14
+ $('input[id*="-showgoto"]').on('change', function(e, i){
15
+ ytc_toggle_widget_option_checkbox($(this).attr('id'));
16
+ });
17
+ });
18
+
19
+ function ytc_toggle_widget_option_checkbox(id) {
20
+ if ( $('#' + id).attr('checked') === 'checked' ) {
21
+ $('p.' + id).addClass('visible').removeClass('hidden');
22
+ } else {
23
+ $('p.' + id).addClass('hidden').removeClass('visible');
24
+ }
25
+ }
26
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  });
assets/js/admin.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(i){function t(t,e){i("#"+t).val()==e?i("p."+t).addClass("visible").removeClass("hidden"):i("p."+t).addClass("hidden").removeClass("visible")}function e(t){"checked"===i("#"+t).attr("checked")?i("p."+t).addClass("visible").removeClass("hidden"):i("p."+t).addClass("hidden").removeClass("visible")}i('select[id*="-use_res"]').each(function(){t(i(this).attr("id"),2)}),i('select[id*="-use_res"]').on("change",function(){t(i(this).attr("id"),2)}),i('input[id*="-showgoto"]').each(function(){e(i(this).attr("id"))}),i('input[id*="-showgoto"]').on("change",function(){e(i(this).attr("id"))}),i(document).ajaxSuccess(function(){i('select[id*="-use_res"]').each(function(){t(i(this).attr("id"),2)}),i('select[id*="-use_res"]').on("change",function(){t(i(this).attr("id"),2)}),i('input[id*="-showgoto"]').each(function(){e(i(this).attr("id"))}),i('input[id*="-showgoto"]').on("change",function(){e(i(this).attr("id"))})})});
1
+ jQuery(document).ready(function(t){function i(i){"checked"===t("#"+i).attr("checked")?t("p."+i).addClass("visible").removeClass("hidden"):t("p."+i).addClass("hidden").removeClass("visible")}t('input[id*="-showgoto"]').each(function(){i(t(this).attr("id"))}),t('input[id*="-showgoto"]').on("change",function(){i(t(this).attr("id"))}),t(document).ajaxSuccess(function(){t('input[id*="-showgoto"]').each(function(){i(t(this).attr("id"))}),t('input[id*="-showgoto"]').on("change",function(){i(t(this).attr("id"))})})});
assets/js/jquery.fitvids.js DELETED
@@ -1,83 +0,0 @@
1
- /*global jQuery */
2
- /*jshint browser:true */
3
- /*!
4
- * FitVids 1.1
5
- *
6
- * Copyright 2013, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com
7
- * Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/
8
- * Released under the WTFPL license - http://sam.zoy.org/wtfpl/
9
- *
10
- */
11
-
12
- (function( $ ){
13
-
14
- "use strict";
15
-
16
- $.fn.fitVids = function( options ) {
17
- var settings = {
18
- customSelector: null,
19
- ignore: null
20
- };
21
-
22
- if(!document.getElementById('fit-vids-style')) {
23
- // appendStyles: https://github.com/toddmotto/fluidvids/blob/master/dist/fluidvids.js
24
- var head = document.head || document.getElementsByTagName('head')[0];
25
- var css = '.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}';
26
- var div = document.createElement('div');
27
- div.innerHTML = '<p>x</p><style id="fit-vids-style">' + css + '</style>';
28
- head.appendChild(div.childNodes[1]);
29
- }
30
-
31
- if ( options ) {
32
- $.extend( settings, options );
33
- }
34
-
35
- return this.each(function(){
36
- var selectors = [
37
- "iframe[src*='player.vimeo.com']",
38
- "iframe[src*='youtube.com']",
39
- "iframe[src*='youtube-nocookie.com']",
40
- "iframe[src*='kickstarter.com'][src*='video.html']",
41
- "object",
42
- "embed"
43
- ];
44
-
45
- if (settings.customSelector) {
46
- selectors.push(settings.customSelector);
47
- }
48
-
49
- var ignoreList = '.fitvidsignore';
50
-
51
- if(settings.ignore) {
52
- ignoreList = ignoreList + ', ' + settings.ignore;
53
- }
54
-
55
- var $allVideos = $(this).find(selectors.join(','));
56
- $allVideos = $allVideos.not("object object"); // SwfObj conflict patch
57
- $allVideos = $allVideos.not(ignoreList); // Disable FitVids on this video.
58
-
59
- $allVideos.each(function(){
60
- var $this = $(this);
61
- if($this.parents(ignoreList).length > 0) {
62
- return; // Disable FitVids on this video.
63
- }
64
- if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; }
65
- if ((!$this.css('height') && !$this.css('width')) && (isNaN($this.attr('height')) || isNaN($this.attr('width'))))
66
- {
67
- $this.attr('height', 9);
68
- $this.attr('width', 16);
69
- }
70
- var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(),
71
- width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(),
72
- aspectRatio = height / width;
73
- if(!$this.attr('id')){
74
- var videoID = 'fitvid' + Math.floor(Math.random()*999999);
75
- $this.attr('id', videoID);
76
- }
77
- $this.wrap('<div class="fluid-width-video-wrapper"></div>').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+"%");
78
- $this.removeAttr('height').removeAttr('width');
79
- });
80
- });
81
- };
82
- // Works with either jQuery or Zepto
83
- })( window.jQuery || window.Zepto );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/js/jquery.fitvids.min.js DELETED
@@ -1 +0,0 @@
1
- !function(t){"use strict";t.fn.fitVids=function(e){var i={customSelector:null,ignore:null};if(!document.getElementById("fit-vids-style")){var r=document.head||document.getElementsByTagName("head")[0],a=".fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}",d=document.createElement("div");d.innerHTML='<p>x</p><style id="fit-vids-style">'+a+"</style>",r.appendChild(d.childNodes[1])}return e&&t.extend(i,e),this.each(function(){var e=["iframe[src*='player.vimeo.com']","iframe[src*='youtube.com']","iframe[src*='youtube-nocookie.com']","iframe[src*='kickstarter.com'][src*='video.html']","object","embed"];i.customSelector&&e.push(i.customSelector);var r=".fitvidsignore";i.ignore&&(r=r+", "+i.ignore);var a=t(this).find(e.join(","));a=a.not("object object"),a=a.not(r),a.each(function(){var e=t(this);if(!(e.parents(r).length>0||"embed"===this.tagName.toLowerCase()&&e.parent("object").length||e.parent(".fluid-width-video-wrapper").length)){e.css("height")||e.css("width")||!isNaN(e.attr("height"))&&!isNaN(e.attr("width"))||(e.attr("height",9),e.attr("width",16));var i="object"===this.tagName.toLowerCase()||e.attr("height")&&!isNaN(parseInt(e.attr("height"),10))?parseInt(e.attr("height"),10):e.height(),a=isNaN(parseInt(e.attr("width"),10))?e.width():parseInt(e.attr("width"),10),d=i/a;if(!e.attr("id")){var o="fitvid"+Math.floor(999999*Math.random());e.attr("id",o)}e.wrap('<div class="fluid-width-video-wrapper"></div>').parent(".fluid-width-video-wrapper").css("padding-top",100*d+"%"),e.removeAttr("height").removeAttr("width")}})})}}(window.jQuery||window.Zepto);
 
assets/js/youtube-channel.js CHANGED
@@ -1,14 +1,10 @@
1
- jQuery(document).ready(function($) {
2
- $('.ytc-lightbox')
3
- .magnificPopupAU({
4
- disableOn: 700,
5
- type: 'iframe',
6
- mainClass: 'mfp-fade',
7
- removalDelay: 160,
8
- preloader: false,
9
- fixedContentPos: false
10
- });
11
- $(window).on('load', function() {
12
- $(".youtube_channel.responsive .ytc_video_container").fitVids();
13
- });
14
- });
1
+ jQuery(document).ready(function($) {
2
+ $('.ytc-lightbox').magnificPopupAU({
3
+ disableOn: 700,
4
+ type: 'iframe',
5
+ mainClass: 'mfp-fade',
6
+ removalDelay: 160,
7
+ preloader: false,
8
+ fixedContentPos: false
9
+ });
10
+ });
 
 
 
 
assets/js/youtube-channel.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(e){e(".ytc-lightbox").magnificPopupAU({disableOn:700,type:"iframe",mainClass:"mfp-fade",removalDelay:160,preloader:!1,fixedContentPos:!1}),e(window).on("load",function(){e(".youtube_channel.responsive .ytc_video_container").fitVids()})});
1
+ jQuery(document).ready(function(e){e(".ytc-lightbox").magnificPopupAU({disableOn:700,type:"iframe",mainClass:"mfp-fade",removalDelay:160,preloader:!1,fixedContentPos:!1})});
inc/settings.php CHANGED
@@ -49,7 +49,7 @@ if ( ! class_exists('WPAU_YOUTUBE_CHANNEL_SETTINGS') ) {
49
  'ytc_general', // Section Name
50
  array(
51
  'field' => $this->option_name . '[apikey]',
52
- 'description' => sprintf(__('Your YouTube Data API Key (get it from <a href="%s" target="_blank">Google Developers Console</a>)', 'wpsk'), 'https://console.developers.google.com/project'),
53
  'class' => 'regular-text password',
54
  'value' => $this->defaults['apikey'],
55
  ) // args
@@ -63,7 +63,7 @@ if ( ! class_exists('WPAU_YOUTUBE_CHANNEL_SETTINGS') ) {
63
  'ytc_general', // Section Name
64
  array(
65
  'field' => $this->option_name . '[channel]',
66
- 'description' => sprintf(__('Your YouTube Channel ID (get it from <a href="%s" target="_blank">YouTube Account Overview</a>)', 'wpsk'), 'https://www.youtube.com/account_advanced'),
67
  'class' => 'regular-text',
68
  'value' => $this->defaults['channel'],
69
  ) // args
@@ -77,7 +77,7 @@ if ( ! class_exists('WPAU_YOUTUBE_CHANNEL_SETTINGS') ) {
77
  'ytc_general', // section
78
  array(
79
  'field' => $this->option_name . "[vanity]",
80
- 'description' => sprintf(__('Your YouTube Custom Name (get only part after www.youtube.com/c/ instead whole URL from <a href="%s" target="_blank">YouTube Account Overview</a>)', 'wpsk'), 'https://www.youtube.com/account_advanced'),
81
  'class' => 'regular-text',
82
  'value' => $this->defaults['vanity'],
83
  ) // args
@@ -91,7 +91,7 @@ if ( ! class_exists('WPAU_YOUTUBE_CHANNEL_SETTINGS') ) {
91
  'ytc_general', // section
92
  array(
93
  'field' => $this->option_name . "[username]",
94
- 'description' => __('Your YouTube legacy username', 'wpsk'),
95
  'class' => 'regular-text',
96
  'value' => $this->defaults['username'],
97
  ) // args
@@ -105,7 +105,7 @@ if ( ! class_exists('WPAU_YOUTUBE_CHANNEL_SETTINGS') ) {
105
  'ytc_general', // section
106
  array(
107
  'field' => $this->option_name . "[playlist]",
108
- 'description' => __('Enter default playlist ID (not playlist name)', 'wpsk'),
109
  'class' => 'regular-text',
110
  'value' => $this->defaults['playlist'],
111
  ) // args
@@ -131,22 +131,6 @@ if ( ! class_exists('WPAU_YOUTUBE_CHANNEL_SETTINGS') ) {
131
  )
132
  ) // args
133
  );
134
- // Playlist Only
135
- /*
136
- add_settings_field(
137
- $this->option_name . 'only_pl', // id
138
- __('Embed standard playlist', 'wpsk'), // Title
139
- array(&$this, 'settings_field_checkbox'), // Callback
140
- $this->slug . '_general', // Page
141
- 'ytc_general', // section
142
- array(
143
- 'field' => $this->option_name . "[only_pl]",
144
- 'description' => __("Enable this option to embed whole playlist instead single video from playlist when you chose playlist as resource", 'wpsk'),
145
- 'class' => 'checkbox',
146
- 'value' => $this->defaults['only_pl'],
147
- ) // args
148
- );
149
- */
150
  // Cache
151
  add_settings_field(
152
  $this->option_name . 'cache', // id
@@ -232,22 +216,6 @@ if ( ! class_exists('WPAU_YOUTUBE_CHANNEL_SETTINGS') ) {
232
  'value' => $this->defaults['privacy'],
233
  ) // args
234
  );
235
- // Random video
236
- /*
237
- add_settings_field(
238
- $this->option_name . 'random', // id
239
- __('Show random video', 'wpsk'), // Title
240
- array(&$this, 'settings_field_checkbox'), // Callback
241
- $this->slug . '_general', // Page
242
- 'ytc_general', // section
243
- array(
244
- 'field' => $this->option_name . "[random]",
245
- 'description' => __("Get random videos of all fetched from channel or playlist", 'wpsk'),
246
- 'class' => 'checkbox',
247
- 'value' => $this->defaults['random'],
248
- ) // args
249
- );
250
- */
251
  // --- Register setting General so $_POST handling is done ---
252
  register_setting(
253
  'ytc_general', // Setting group
@@ -414,8 +382,7 @@ if ( ! class_exists('WPAU_YOUTUBE_CHANNEL_SETTINGS') ) {
414
  'ytc_video', // section
415
  array(
416
  'field' => $this->option_name . "[modestbranding]",
417
- 'description' => __("Enable this option to hide YouTube logo from playback control bar. Does not work for all videos.
418
- ", 'wpsk'),
419
  'class' => 'checkbox',
420
  'value' => $this->defaults['modestbranding'],
421
  ) // args
@@ -833,10 +800,10 @@ if ( ! class_exists('WPAU_YOUTUBE_CHANNEL_SETTINGS') ) {
833
  case 'ytc_general':
834
  $apikey = ( defined('YOUTUBE_DATA_API_KEY') ) ? YOUTUBE_DATA_API_KEY : '';
835
  $sanitized['apikey'] = ( ! empty($options['apikey']) ) ? trim($options['apikey']) : $apikey;
836
- $sanitized['channel'] = ( ! empty($options['channel']) ) ? trim($options['channel']) : $this->defaults['channel'];
837
- $sanitized['vanity'] = ( ! empty($options['vanity']) ) ? trim($options['vanity']) : $this->defaults['vanity'];
838
- $sanitized['username'] = ( ! empty($options['username']) ) ? trim($options['username']) : $this->defaults['username'];
839
- $sanitized['playlist'] = ( ! empty($options['playlist']) ) ? trim($options['playlist']) : $this->defaults['playlist'];
840
  $sanitized['resource'] = ( isset($options['resource']) ) ? intval($options['resource']) : $this->defaults['resource'];
841
  // $sanitized['only_pl'] = ( ! empty($options['only_pl']) && $options['only_pl'] ) ? 1 : 0;
842
  $sanitized['cache'] = ( isset($options['cache']) ) ? intval($options['cache']) : $this->defaults['cache'];
49
  'ytc_general', // Section Name
50
  array(
51
  'field' => $this->option_name . '[apikey]',
52
+ 'description' => sprintf("<strong>[%s]</strong> " . __('Your YouTube Data API Key (get it from <a href="%s" target="_blank">Google Developers Console</a>)', 'wpsk'), __('Required'), 'https://console.developers.google.com/project'),
53
  'class' => 'regular-text password',
54
  'value' => $this->defaults['apikey'],
55
  ) // args
63
  'ytc_general', // Section Name
64
  array(
65
  'field' => $this->option_name . '[channel]',
66
+ 'description' => sprintf("<strong>[%s]</strong> " . __('Your YouTube Channel ID (get it from <a href="%s" target="_blank">YouTube Account Overview</a>)', 'wpsk'), __('Required'), 'https://www.youtube.com/account_advanced'),
67
  'class' => 'regular-text',
68
  'value' => $this->defaults['channel'],
69
  ) // args
77
  'ytc_general', // section
78
  array(
79
  'field' => $this->option_name . "[vanity]",
80
+ 'description' => sprintf("[%s] " . __('Your YouTube Custom Name (get only part after www.youtube.com/c/ instead whole URL from <a href="%s" target="_blank">YouTube Account Overview</a>)', 'wpsk'), __('Optional'), 'https://www.youtube.com/account_advanced'),
81
  'class' => 'regular-text',
82
  'value' => $this->defaults['vanity'],
83
  ) // args
91
  'ytc_general', // section
92
  array(
93
  'field' => $this->option_name . "[username]",
94
+ 'description' => sprintf("[%s] %s", __('Optional'), __('Your YouTube legacy username', 'wpsk') ),
95
  'class' => 'regular-text',
96
  'value' => $this->defaults['username'],
97
  ) // args
105
  'ytc_general', // section
106
  array(
107
  'field' => $this->option_name . "[playlist]",
108
+ 'description' => sprintf("[%s] %s", __('Optional'), __('Enter default playlist ID (not playlist name)', 'wpsk') ),
109
  'class' => 'regular-text',
110
  'value' => $this->defaults['playlist'],
111
  ) // args
131
  )
132
  ) // args
133
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  // Cache
135
  add_settings_field(
136
  $this->option_name . 'cache', // id
216
  'value' => $this->defaults['privacy'],
217
  ) // args
218
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  // --- Register setting General so $_POST handling is done ---
220
  register_setting(
221
  'ytc_general', // Setting group
382
  'ytc_video', // section
383
  array(
384
  'field' => $this->option_name . "[modestbranding]",
385
+ 'description' => __("Enable this option to hide YouTube logo from playback control bar. Does not work for all videos.", 'wpsk'),
 
386
  'class' => 'checkbox',
387
  'value' => $this->defaults['modestbranding'],
388
  ) // args
800
  case 'ytc_general':
801
  $apikey = ( defined('YOUTUBE_DATA_API_KEY') ) ? YOUTUBE_DATA_API_KEY : '';
802
  $sanitized['apikey'] = ( ! empty($options['apikey']) ) ? trim($options['apikey']) : $apikey;
803
+ $sanitized['channel'] = ( ! empty($options['channel']) ) ? trim($options['channel']) : ''; //$this->defaults['channel'];
804
+ $sanitized['vanity'] = ( ! empty($options['vanity']) ) ? trim($options['vanity']) : ''; //$this->defaults['vanity'];
805
+ $sanitized['username'] = ( ! empty($options['username']) ) ? trim($options['username']) : ''; //$this->defaults['username'];
806
+ $sanitized['playlist'] = ( ! empty($options['playlist']) ) ? trim($options['playlist']) : ''; //$this->defaults['playlist'];
807
  $sanitized['resource'] = ( isset($options['resource']) ) ? intval($options['resource']) : $this->defaults['resource'];
808
  // $sanitized['only_pl'] = ( ! empty($options['only_pl']) && $options['only_pl'] ) ? 1 : 0;
809
  $sanitized['cache'] = ( isset($options['cache']) ) ? intval($options['cache']) : $this->defaults['cache'];
inc/widget.php CHANGED
@@ -37,20 +37,20 @@ class WPAU_YOUTUBE_CHANNEL_Widget extends WP_Widget {
37
  // General Options
38
  $title = (!empty($instance['title'])) ? esc_attr($instance['title']) : '';
39
  $class = (!empty($instance['class'])) ? esc_attr($instance['class']) : '';
40
- $vanity = ( ! empty($instance['vanity']) ) ? esc_attr($instance['vanity']) : trim($defaults['vanity']);
41
  $channel = (!empty($instance['channel'])) ? esc_attr($instance['channel']) : trim($defaults['channel']);
42
  $username = (!empty($instance['username'])) ? esc_attr($instance['username']) : trim($defaults['username']);
43
  $playlist = (!empty($instance['playlist'])) ? esc_attr($instance['playlist']) : trim($defaults['playlist']);
44
 
45
- $resource = (!empty($instance['resource'])) ? esc_attr($instance['resource']) : 0; // resource to use: channel, favorites, playlist
46
  $only_pl = (!empty($instance['only_pl'])) ? esc_attr($instance['only_pl']) : '';
47
 
48
- $cache = (!empty($instance['cache'])) ? esc_attr($instance['cache']) : trim($defaults['cache']);
49
 
50
- $fetch = (!empty($instance['fetch'])) ? esc_attr($instance['fetch']) : trim($defaults['fetch']); // items to fetch
51
- $num = (!empty($instance['num'])) ? esc_attr($instance['num']) : trim($defaults['num']); // number of items to show
52
 
53
- $privacy = (!empty($instance['privacy'])) ? esc_attr($instance['privacy']) : 0;
54
  $random = (!empty($instance['random'])) ? esc_attr($instance['random']) : 0;
55
 
56
  // Video Settings
@@ -69,7 +69,7 @@ class WPAU_YOUTUBE_CHANNEL_Widget extends WP_Widget {
69
 
70
  // Content Layout
71
  $showtitle = (!empty($instance['showtitle'])) ? esc_attr($instance['showtitle']) : '';
72
- $titlebelow = (!empty($instance['titlebelow'])) ? esc_attr($instance['titlebelow']) : '';
73
  $showdesc = (!empty($instance['showdesc'])) ? esc_attr($instance['showdesc']) : '';
74
  $modestbranding = (!empty($instance['modestbranding'])) ? esc_attr($instance['modestbranding']) : '';
75
  $desclen = (!empty($instance['desclen'])) ? esc_attr($instance['desclen']) : 0;
@@ -226,12 +226,12 @@ class WPAU_YOUTUBE_CHANNEL_Widget extends WP_Widget {
226
  $instance['username'] = strip_tags($new_instance['username']);
227
  $instance['playlist'] = strip_tags($new_instance['playlist']);
228
  $instance['vanity'] = strip_tags($new_instance['vanity']);
229
- $instance['num'] = $new_instance['num'];
230
- $instance['resource'] = $new_instance['resource'];
231
- $instance['cache'] = $new_instance['cache'];
232
  $instance['only_pl'] = (isset($new_instance['only_pl'])) ? $new_instance['only_pl'] : false;
233
  $instance['random'] = (isset($new_instance['random'])) ? $new_instance['random'] : false;
234
- $instance['fetch'] = $new_instance['fetch'];
235
 
236
  $instance['showgoto'] = (isset($new_instance['showgoto'])) ? $new_instance['showgoto'] : false;
237
  $instance['goto_txt'] = strip_tags($new_instance['goto_txt']);
@@ -239,10 +239,10 @@ class WPAU_YOUTUBE_CHANNEL_Widget extends WP_Widget {
239
  $instance['link_to'] = $new_instance['link_to'];
240
 
241
  $instance['showtitle'] = (isset($new_instance['showtitle'])) ? $new_instance['showtitle'] : false;
242
- $instance['titlebelow'] = (isset($new_instance['titlebelow'])) ? $new_instance['titlebelow'] : false;
243
- $instance['showdesc'] = (isset($new_instance['showdesc'])) ? $new_instance['showdesc'] : false;
244
  $instance['descappend'] = strip_tags($new_instance['descappend']);
245
- $instance['desclen'] = strip_tags($new_instance['desclen']);
246
  $instance['width'] = strip_tags($new_instance['width']);
247
  $instance['responsive'] = (isset($new_instance['responsive'])) ? $new_instance['responsive'] : '';
248
 
@@ -258,7 +258,7 @@ class WPAU_YOUTUBE_CHANNEL_Widget extends WP_Widget {
258
  $instance['hideinfo'] = (isset($new_instance['hideinfo'])) ? $new_instance['hideinfo'] : '';
259
  $instance['hideanno'] = (isset($new_instance['hideanno'])) ? $new_instance['hideanno'] : '';
260
  $instance['themelight'] = (isset($new_instance['themelight'])) ? $new_instance['themelight'] : '';
261
- $instance['privacy'] = (isset($new_instance['privacy'])) ? $new_instance['privacy'] : '';
262
 
263
  return $instance;
264
  }
37
  // General Options
38
  $title = (!empty($instance['title'])) ? esc_attr($instance['title']) : '';
39
  $class = (!empty($instance['class'])) ? esc_attr($instance['class']) : '';
40
+ $vanity = (!empty($instance['vanity']) ) ? esc_attr($instance['vanity']) : trim($defaults['vanity']);
41
  $channel = (!empty($instance['channel'])) ? esc_attr($instance['channel']) : trim($defaults['channel']);
42
  $username = (!empty($instance['username'])) ? esc_attr($instance['username']) : trim($defaults['username']);
43
  $playlist = (!empty($instance['playlist'])) ? esc_attr($instance['playlist']) : trim($defaults['playlist']);
44
 
45
+ $resource = (!empty($instance['resource'])) ? esc_attr($instance['resource']) : 0; // resource to use: channel, favorites, playlist
46
  $only_pl = (!empty($instance['only_pl'])) ? esc_attr($instance['only_pl']) : '';
47
 
48
+ $cache = (!empty($instance['cache'])) ? esc_attr($instance['cache']) : trim($defaults['cache']);
49
 
50
+ $fetch = (!empty($instance['fetch'])) ? esc_attr($instance['fetch']) : trim($defaults['fetch']); // items to fetch
51
+ $num = (!empty($instance['num'])) ? esc_attr($instance['num']) : trim($defaults['num']); // number of items to show
52
 
53
+ $privacy = (!empty($instance['privacy'])) ? esc_attr($instance['privacy']) : 0;
54
  $random = (!empty($instance['random'])) ? esc_attr($instance['random']) : 0;
55
 
56
  // Video Settings
69
 
70
  // Content Layout
71
  $showtitle = (!empty($instance['showtitle'])) ? esc_attr($instance['showtitle']) : '';
72
+ $titlebelow = (!empty($instance['titlebelow'])) ? esc_attr($instance['titlebelow']) : '';
73
  $showdesc = (!empty($instance['showdesc'])) ? esc_attr($instance['showdesc']) : '';
74
  $modestbranding = (!empty($instance['modestbranding'])) ? esc_attr($instance['modestbranding']) : '';
75
  $desclen = (!empty($instance['desclen'])) ? esc_attr($instance['desclen']) : 0;
226
  $instance['username'] = strip_tags($new_instance['username']);
227
  $instance['playlist'] = strip_tags($new_instance['playlist']);
228
  $instance['vanity'] = strip_tags($new_instance['vanity']);
229
+ $instance['num'] = $new_instance['num'];
230
+ $instance['resource'] = $new_instance['resource'];
231
+ $instance['cache'] = $new_instance['cache'];
232
  $instance['only_pl'] = (isset($new_instance['only_pl'])) ? $new_instance['only_pl'] : false;
233
  $instance['random'] = (isset($new_instance['random'])) ? $new_instance['random'] : false;
234
+ $instance['fetch'] = $new_instance['fetch'];
235
 
236
  $instance['showgoto'] = (isset($new_instance['showgoto'])) ? $new_instance['showgoto'] : false;
237
  $instance['goto_txt'] = strip_tags($new_instance['goto_txt']);
239
  $instance['link_to'] = $new_instance['link_to'];
240
 
241
  $instance['showtitle'] = (isset($new_instance['showtitle'])) ? $new_instance['showtitle'] : false;
242
+ $instance['titlebelow'] = (isset($new_instance['titlebelow'])) ? $new_instance['titlebelow'] : false;
243
+ $instance['showdesc'] = (isset($new_instance['showdesc'])) ? $new_instance['showdesc'] : false;
244
  $instance['descappend'] = strip_tags($new_instance['descappend']);
245
+ $instance['desclen'] = strip_tags($new_instance['desclen']);
246
  $instance['width'] = strip_tags($new_instance['width']);
247
  $instance['responsive'] = (isset($new_instance['responsive'])) ? $new_instance['responsive'] : '';
248
 
258
  $instance['hideinfo'] = (isset($new_instance['hideinfo'])) ? $new_instance['hideinfo'] : '';
259
  $instance['hideanno'] = (isset($new_instance['hideanno'])) ? $new_instance['hideanno'] : '';
260
  $instance['themelight'] = (isset($new_instance['themelight'])) ? $new_instance['themelight'] : '';
261
+ $instance['privacy'] = (isset($new_instance['privacy'])) ? $new_instance['privacy'] : '';
262
 
263
  return $instance;
264
  }
readme.txt CHANGED
@@ -1,597 +1,610 @@
1
- === YouTube Channel ===
2
- Contributors: urkekg
3
- Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Q6Q762MQ97XJ6
4
- Tags: youtube, channel, playlist, single, widget, widgets, youtube player, feed, video, thumbnail, embed, sidebar, iframe, html5, responsive
5
- Requires at least: 3.9.0
6
- Tested up to: 4.2.2
7
- Stable tag: 3.0.6.2
8
- License: GPLv3
9
- License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
-
11
- Show video thumbnails or playable blocks of recent videos from YouTube Channel or Playlist.
12
-
13
- == Description ==
14
-
15
- When you need to display sidebar widget with latest video from some YouTube channel or playlist, you can use customisable `YouTube Channel` plugin.
16
-
17
- Simply insert widget to sidebar, set channel name and if you wish leave all other options on default. You will get latest video from chosen YouTube channel embedded in sidebar widget, with link to channel on the bottom of the widget. If you wish to use playlist instead of channel, just set playlist ID and injoy!
18
-
19
- If you like this extension and you find it useful, please rate it on the right side.
20
-
21
- = Features =
22
- * Display latest videos from YouTube Channel (resources are sorted in reverse chronological order based on the date they were created) or videos naturaly sorted from Favorited Videos, Liked Videos and Playlist
23
- * Option to get random video from any of 4 resources
24
- * Responsive (one full width video per row) or non responsive
25
- * Preferred aspect ratio relative to width (16:9 and 4:3)
26
- * Custom width for video embeded object (default is 306px)
27
- * Enhanced Privacy
28
- * Choose to display video as thumbnail (default), HTML5 (iframe) or HTML5 Asynchronous (iframe2)
29
- * Thumbnail mode opens video in lightbox
30
- * Custom caching timeout
31
- * Optimized data feeds
32
- * Optional video autoplay with optional muted audio
33
- * Show customized link to channel below videos
34
-
35
- = Notice =
36
-
37
- For fully functional plugin you need to have PHP 5.3 or newer! If you experience issues on older PHP, we can't help you as we don't have access to such old development platform.
38
-
39
- = Styling =
40
-
41
- You can use `style.css` from theme to style `YouTube Video` widget content.
42
-
43
- * `.widget_youtube-channel` – class of whole widget (parent for widget title and YTC block)
44
- * `.youtube_channel` – YTC block wrapper class. Additional classes are available:
45
- * `.default` – for non-responsive block
46
- * `.responsive` – when you have enabled responsive option
47
- * `.ytc_title` – class of H3 tag for video title above thumbnail/video object
48
- * `.ytc_video_container` – class of container for single item, plus:
49
- * `.ytc_video_1`, `.ytc_video_2`, … – class of container for single item with ordering number of item in widget
50
- * `.ytc_video_first` – class of first container for single item
51
- * `.ytc_video_mid` – class of all other containers for single item
52
- * `.ytc_video_last` – class of last container for single item
53
- * `.ar16_9` – class for Aspect Ratio 16:9
54
- * `.ar4_3` – class for Aspect Ration 4:3
55
- * `.ytc_thumb` – class of anchor for Thumbnail mode
56
- * `.fluid-width-video-wrapper` – class for parent element of IFRAME for enabled responsive
57
- * `.ytc_description` – class for video description text below thumbnail/video object
58
- * `.ytc_link` – class of container for link to channel
59
-
60
- = Known Issues =
61
-
62
- * Video description for videos from playlist does not work.
63
- * Removing YouTube logo from playback control bar does not work for all videos
64
- * Async HTML5 video does not work for 2nd same video on same page (two YTC blocks set to Async HTML5)
65
- * Thumbnail and opening video in lightbox does not work with `Responz` theme by `Thenify.me` if you wish to hide related videos, because this theme uses original `Magnific Popup` library that does not support `rel` parameter.
66
-
67
- If WordFence or other malware scan tool detect YouTube Channel fule youtube-channel.php as potential risk because `base64_encode()` and `base64_decode()` functions, remember that we use this two functions to store and restore JSON feeds to transient cache, so potential detection is false positive.
68
-
69
- = Credits =
70
-
71
- * For playing videos in lightbox we use enhanced [Magnific Popup](http://dimsemenov.com/plugins/magnific-popup/).
72
- * Initial textdomain adds done by [dimadin](http://wordpress.org/extend/plugins/profile/dimadin).
73
- * [Federico Bozo](http://corchoweb.com/) reminded me to fix z-index problem
74
- * Czech localization by [Ladislav Drábek](http://zholesova.cz)
75
- * Spanish localization by [Diego Riaño](http://Digital03.net)
76
- * Danish localisation by [GSAdev v. Georg Adamsen](http://www.gsadev.dk)
77
-
78
- = Shortcode =
79
-
80
- Along to Widget, you can add YouTube Channel block inline by using shortcode `[youtube_channel]`. Default plugin parameters will be used for shortcode, but you can customize all parameters per shortcode.
81
-
82
- **General Settings**
83
-
84
- * `class` (string) Set custom class if you wish to target special styling for specific YTC block
85
- * `channel` (string) ID of preferred YouTube channel. Do not set full URL to channel, but just last part from URL - ID (name)
86
- * `vanity` (string) part after www.youtube.com/c/ from [Custom URL](https://support.google.com/youtube/answer/2657968?hl=en)
87
- * `playlist` (string) ID of preferred YouTube playlist.
88
- * `resource` (int) Resource to use for feed:
89
- * `0` Channel
90
- * `1` Favorites (for defined channel)
91
- * `2` Playlist
92
- * `3` Liked Videos
93
- * `only_pl` (bool) If you set to use Playlist as resource, you can embed youtube playlist block instead single video from playlist. Simply set this option to true (1 or true)
94
- * `cache` (int) Period in seconds for caching feed. You can disable caching by setting this option to 0, but if you have a lot of visits, consider at least short caching (couple minutes).
95
- * `fetch` (int) Number of videos that will be used as stack for random pick (min 2, max 50)
96
- * `num` (int) Number of videos to display per YTC block.
97
- * `random` (bool) Option to randomize videos on every page load.
98
-
99
- **Video Settings**
100
-
101
- * `ratio` (int) Set preferred aspect ratio for thumbnail and video. You can use:
102
- * `3` 16:9 (widescreen)
103
- * `1` 4:3
104
- * `responsive` (bool) Distribute one full width video per row.
105
- * `width` (int) Width of thumbnail and video in pixels.
106
- * `display` (string) Object that will be used to represent video. We have couple predefined options:
107
- * `thumbnail` Thumbnail will be used and video will be loaded in lightbox. (default)
108
- * `iframe` HTML5 (iframe)
109
- * `iframe2` HTML5 (iframe) with asynchronous loading - recommended
110
- * `no_thumb_title` (bool) By default YouTube thumbnail will have tooltip with info about video title and date of publishing. By setting this option to 1 or true you can hide tooltip
111
- * `themelight` (bool) By default YouTube have dark play controls theme. By setting this option to 1 or true you can get light theme in player (HTML5 and Flash)
112
- * `controls` (bool) Set this option to 1 or true to hide playback controls.
113
- * `autoplay` (bool) Enable autoplay of first video in YTC video stack by setting this option to 1 or true
114
- * `mute` (bool) Set this option to 1 or true to mute videos set to autoplay on load
115
- * `norel` (bool) Set this option to 1 or true to hire related videos after finished playbak
116
- * `nobrand` (bool) Set this option to 1 or true to hire YouTube logo from playback control bar
117
-
118
- **Content Layout**
119
-
120
- * `showtitle` (bool) Set to 1 or true to show video title.
121
- * `titlebelow` (bool) Set to 1 or true to move video title below video.
122
- * `showdesc` (bool) Set to 1 or true to show video description.
123
- * `desclen` (int) Set number of characters to cut down length of video description. Set to 0 to use full length description.
124
- * `noinfo` (bool) Set to 1 or true to hide overlay video infos (from embedded player)
125
- * `noanno` (bool) Set to 1 or true to hide overlay video annotations (from embedded player)
126
-
127
- **Link to Channel**
128
-
129
- * `goto` (bool) Set to 1 or true to display link to channel at the bottom of YTC block.
130
- * `goto_txt` (string)
131
- * `popup` (int) Control where link to channel will be opened:
132
- * `0` open link in same window
133
- * `1` open link in new window with JavaScript
134
- * `2` open link in new window with target="_blank" anchor attribute
135
- * `link_to` (int) URL to link:
136
- * `2` Vanity custom URL (default)
137
- * `1` Channel page
138
- * `0` Legacy username page
139
-
140
- == Installation ==
141
-
142
- You can use the built in installer and upgrader, or you can install the plugin manually.
143
-
144
- 1. You can either use the automatic plugin installer or your FTP program to upload unziped `youtube-channel` directory to your `wp-content/plugins` directory.
145
- 1. Activate the plugin through the `Plugins` menu in WordPress
146
- 1. Add YouTube Channel widget to sidebar
147
- 1. Set Channel ID and save changes
148
-
149
- If you have to upgrade manually simply repeat the installation steps and re-enable the plugin.
150
-
151
- = YouTube Data API Key =
152
- Main difference since v2.x branch is that now we use [YouTube Data API v3](https://developers.google.com/youtube/v3/) so to make plugin to work, you'll need to generate YouTube Data API Key and insert it to General plugin settings.
153
-
154
- Learn more about [Obtaining authorization credentials](https://developers.google.com/youtube/registering_an_application) and for detailed instructions how to generate your own API Key watch video below.
155
-
156
- [youtube http://www.youtube.com/watch?v=8NlXV77QO8U]
157
-
158
- 1. Visit [Google Developers Console](https://console.developers.google.com/project)
159
- 1. If you don't have any project, create new one. Name it so you can recognize it (for example **My WordPress Website**).
160
- 1. Select your new project and from LHS sidebar expand group **APIs & auth**, then select item **APIs**
161
- 1. Locate and click **YouTube Data API** under **YouTube API** section
162
- 1. Click **Enable API** button
163
- 1. When you get enabled YouTube Data API in your project, click **Credentials** item from LHS menu **APIs & auth**
164
- 1. Click **Create New Key** button and select **Server Key**
165
- 1. Leave empty or enter IP of your website. If you get message **Oops, something went wrong.** make sure you set proper IP, or leave any restriction.
166
- 1. Click **Create** button
167
- 1. Copy newly created **API Key**
168
-
169
- When you generate your own YouTube Data API Key, from your **Dashboard** go to **Settings** -> **YouTube Channel** -> **General** and paster key in to field **YouTube Data API Key**.
170
-
171
- Also, do not forget to check and update **Channel ID** in plugin's General settings, Widgets and/or shortcodes.
172
- You can get **Channel ID** from page [Account Advanced](https://www.youtube.com/account_advanced) while you're loagged in to your YouTube account.
173
-
174
- == Frequently Asked Questions ==
175
-
176
- = How to get that YouTube Data API Key? =
177
-
178
- Please folllow [Installation](https://wordpress.org/plugins/youtube-channel/installation/) instructions.
179
-
180
- = I set everything correct but receiveing 'Oops, something went wrong' message =
181
-
182
- Right click that message on your website, click *Inspect Element*, expand tag with class *youtube_channel* and look for HTML comment below it, message will look like this:
183
-
184
- `<!-- YTC ERROR:
185
- domain: youtube.playlistItem
186
- reason: playlistNotFound
187
- message: Not Found
188
- tip: Please check did you set proper Channel ID. We should display videos from channel videos, but YouTube does not recognize your channel ID UCkVThLIHAZVsJc7f28tIsIws as existing and public resource.
189
- -->`
190
-
191
- Do exactly what tip says - check and correct Channel ID in default settings/widget/shortcode.
192
-
193
- `<!-- YTC ERROR:
194
- domain: usageLimits
195
- reason: keyInvalid
196
- message: Bad Request
197
- -->`
198
-
199
- If you followed [Installation](https://wordpress.org/plugins/youtube-channel/installation/) instructions, double check **YouTube Data API Key** entered to Global settings. Do you have correct key generated by you and allowed to be used on your server?
200
-
201
- `<!-- YTC ERROR:
202
- domain: usageLimits
203
- reason: ipRefererBlocked
204
- message: There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed.
205
- -->`
206
-
207
- We still strugling with that Google's restrictions. If you get final solution, please inform us asap. Try with following possible solutions:
208
-
209
- 1. If you are using **Jetpack** plugin with enabled **Protect** sub plugin, try to disable it. (kudos to [yudhita](https://wordpress.org/support/profile/yudhita) for tip)
210
- 1. Try to remove restrictions by referer or IP in your **YouTube Data API Key** and refresh page after couple minutes.
211
- 1. If that does not help, please try to create new API Key for Server w/o restrictions (not to regenerate existing one).
212
-
213
- If there is no `YTC ERROR` code in HTML source, visit [Google API Explorer](https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.playlistItems.list?part=snippet&maxResults=5&playlistId=) and append:
214
-
215
- * for videos from channel replace **UC** with **UU** in Channel ID (so *UCRPqmcpGcJ_gFtTmN_a4aVA* becomes *UURPqmcpGcJ_gFtTmN_a4aVA*)
216
- * for videos from Favourited videos replace **UC** with **FL** (so *UCRPqmcpGcJ_gFtTmN_a4aVA* becomes *FLRPqmcpGcJ_gFtTmN_a4aVA*)
217
- * for videos from Liked Videos replace **UC** with **LL** (so *UCRPqmcpGcJ_gFtTmN_a4aVA* becomes *LLRPqmcpGcJ_gFtTmN_a4aVA*)
218
- * for videos from Playlist simply use Playlist ID (like *PLEC850BE962234400*)
219
-
220
- Note that all four resources are *playlists* (including channel), so append mentioned ID to field **playlistId** (not to **id**), and click **Execute** button at the bottom of that page.
221
-
222
- 1. If you receive some error, fix settings.
223
- 1. If there is no error but you do not get any video in results - contact Google Support
224
- 1. If there are video results but not displayed with YouTube Channel plugin - [contact us](https://wordpress.org/support/plugin/youtube-channel)
225
-
226
- = Where to find correct Channel ID and/or Vanity custom Name? =
227
-
228
- Login to your YouTube account and visit page [Account Advanced](https://www.youtube.com/account_advanced).
229
-
230
- You'll find your **Vanity Name** as "Your custom URL" in **Channel settins** section on that page. For YTC plugin use only part **after www.youtube.com/c/**, not full URL.
231
-
232
- **Channel ID** is **YouTube Channel ID** value composed of mixed characters starting with **UC**.
233
-
234
- = Where to find ID for Favourites and/or Liked Videos? =
235
-
236
- You will not need that two ID's, in general. But, if you really wish to know, these two ID's are produced from your **Channel ID**. Channel ID start with **UC** (like `UCRPqmcpGcJ_gFtTmN_a4aVA`)
237
-
238
- * For Favourites ID replace **UC** with **FL** (so you get `FLRPqmcpGcJ_gFtTmN_a4aVA`)
239
- * For Liked Videos ID replace **UC** with **LL** (so you get `LLRPqmcpGcJ_gFtTmN_a4aVA`)
240
-
241
- = What is Vanity custom URL? =
242
-
243
- Check out [Channel custom URL](https://support.google.com/youtube/answer/2657968?ref_topic=3024172&hl=en-GB) article.
244
-
245
- = Where to find Playlist ID? =
246
-
247
- Playlist ID can be manualy extracted from YouTube playlist URL. Part of strings after `&list=` that begins with uppercase letters **PL** represent Playlist ID (not full URL).
248
-
249
- = How to force embeding 320p video with better audio quality? =
250
-
251
- YouTube provide 320p videos if height of embeded video is set to 320 or more. If you use small YTC video size, 240p will be loaded instead. So, you could not force 720p in tiny YTC.
252
-
253
- = I enabled option `Hide YT Logo` but YouTube logo is still visible =
254
-
255
- Modestbranding option does not work for all videos, so a lot of videos will still have YouTube logo in control bar. I recommend to enable option `Hide player controls` instead.
256
-
257
- Also, even when hidding logo works for your video, on hover or when video is paused in upper right corner will be displayed YouTube link/logo. [Read more here](https://developers.google.com/youtube/player_parameters#modestbranding)
258
-
259
- = How I can achieve 'wall' layout with one featured thumbnail? =
260
-
261
- You can try with shortcode combination:
262
- `[youtube_channel num=7 responsive=1 class=ytc_wall_1-6 resource=2 random=1]`
263
-
264
- and custom CSS code added to theme style.css or similar customization:
265
- `.youtube_channel.ytc_wall_1-6 .ytc_video_container {
266
- padding: 5px;
267
- box-sizing: border-box;
268
- }
269
- .youtube_channel.ytc_wall_1-6 .ytc_video_container:not(:first-child) {
270
- max-width: 33.333%;
271
- }
272
- @media screen and (max-width: 768px) {
273
- .youtube_channel.ytc_wall_1-6 .ytc_video_container:not(:first-child) {
274
- max-width: 50%;
275
- }
276
- }
277
- @media screen and (max-width: 480px) {
278
- .youtube_channel.ytc_wall_1-6 .ytc_video_container:not(:first-child) {
279
- max-width: 100%;
280
- }
281
- }`
282
-
283
- So, we display thumbnails for 7 random videos from default (global) playlist, and distribute small thumbnails to 3 columns on wide screens, 2 columns under 768px and single thumbnail per row under 480px.
284
-
285
- == Changelog ==
286
-
287
- = 3.0.6.2 (2015-05-15) =
288
- * Fix: Fatal error: Cannot unset string offsets in update.php on line 229 (introduced in 3.0.6.1)
289
- * Add: Helpfull links to plugin settings page
290
-
291
- = 3.0.6.1 (2015-05-14) =
292
- * Fix: Undefined index: random
293
- * Fix: Unremoved only_pl from global settings
294
- * Add: Box sizing of .youtube_channel element for crappy themes
295
-
296
- = 3.0.6 (2015-05-13/14) =
297
-
298
- * Fix: Prevent Fatal error on PHP<5.3 because required __DIR__ for updater replaced with dirname(__FILE__)
299
- * Fix: No retrieved or missing videos from some channels so switch `search` to `playlistItems` API call (kudos to @[mmirus](https://wordpress.org/support/profile/mmirus))
300
- * Add: Embed As Playlist for all resources
301
- * Add: Clearfix for crappy themes where clearfix does not exists
302
- * Add: Option to move video title below video (boolean shortcode parameter `titlebelow`)
303
- * Add: PayPal donate button to settings page
304
- * Improved: Move YouTube Data API Key to plugin settings and add notification to remove YOUTUBE_DATA_API_KEY from wp-config.php (optional)
305
- * Improved: Updated shortcode explanation in README and Help tab in plugin settings.
306
- * Improved: Better tips for 'Oops, something went wrong' message.
307
- * Change: Wording `Ups` to `Oops`
308
- * Remove: Options `Embed standard playlist` and `Show random video` from global settings as this should be off by default
309
- * Remove: Loading of fitVids JS library for test before final removing.
310
-
311
- = 3.0.5 (2015-05-11/12) =
312
-
313
- * Fix: Setting back dropdown options with `0` ID does not work on Settings page (Channel as resource to use, Cache timeout, Aspect ratio, What to show, Open link to, Link to)
314
- * Add: Option to export global settings to JSON and add to Tools tab in settings button to download global settings JSON
315
- * Change: Update plugin features
316
- * Improved: Retrieve only fields which will be used for output w/o unused items to reduce
317
- * Improved: More micro optimizations
318
-
319
- = 3.0.4 (2015-05-11) =
320
-
321
- * Add: Tip what to do if error ocurred with YouTube Data API Key printed inside YTC ERROR comment
322
- * Change: Where to ask for support links in widget
323
- * Change: Timeout for getting feed increased from 2 to 5 seconds
324
- * Change: Update FAQ sections in readme file
325
- * Remove: Check for Redux Framework in debug JSON generator
326
-
327
- = 3.0.3 (2015-05-10) =
328
-
329
- * Fix: "Oops, something went wrong." when Playlist selected as resource because wrong switch
330
- * Fix: Jumping thumbnails in responsive wall on hover in Twenty Fifteen theme because border-bottom for anchors
331
- * Fix: Another deprecated shortcode attribute backward compatibility (`use_res`)
332
- * Add: Example of dynamic responsive wall (1 large + 6 small thumbnails) (to [Description](https://wordpress.org/plugins/youtube-channel/))
333
-
334
- = 3.0.2 (2015-05-10) =
335
-
336
- * Fix: (typo - experiencing on frontend when no API Key set) PHP Fatal error: Call to undefined function __sprintf() in youtube-channel.php on line 445
337
- * Fix: shortcode deprecated params `res` and `show` not backward compatibile
338
-
339
- = 3.0.1 (2015-05-10) =
340
-
341
- * Fix: Fatal error: Using $this when not in object context in youtube-channel.php on line 89
342
- * Fix: Link to channel not visible on Twenty Fifteen theme
343
-
344
- = 3.0.0 (2015-05-07/08/09/10) =
345
-
346
- * Fix: Migraton of global and widget settings to v3.0.0
347
- * Add: New Global Settings page as replacement of Redux Framework solution
348
- * Add: Non-Dismissable Dashboard notice if YouTube Data API Key missing with link to explanation page
349
- * Change: Option key `ytc_version` to `youtube_channel_version`
350
- * Change: Shortcode parameters: `res` to `resource`, `show` to `display`; but leave old parameter names for backward compatibility
351
- * Enhance: Various plugin core micro optimizations
352
- * Enhance: Dashboard notices
353
- * Enhance: Proper options migration on plugin update
354
- * Remove: Redux Framework mentioning from core plugin
355
- * Remove: Redux Framework config.php
356
- * Remove: chromeless.swf asset
357
- * Remove: option `Fix height taken by controls` as now YouTube displays control bar only when video is hovered
358
-
359
- = 3.0.0alpha2 (2015-03-07/22/24) =
360
-
361
- * Add: Rewrite plugin to work with YouTube Data API v3
362
- * Add: Vanity link as option to Link to channel (now supports Legacy username, Channel and Vanity URL) with cleanup Vanity ID routine
363
- * Add: Liked videos as resource (now support channel, playlists, favourites and liked videos)
364
- * Add: Admin notification in widget output on front-end if no YouTube Data API Key is defined to prevent errors
365
- * Add: Dismissable Dashboard notice if PHP version is lower than 5.3 as YTC maybe will not work with older versions.
366
- * Change: Global and widget option names: `use_res` to `resource`, `cache_time` to `cache`, `maxrnd` to `fetch`, `vidqty` to `num`, `getrnd` to `random`, `to_show` to `display`, `showvidesc` to `showdesc`, `enhprivacy` to `privacy`, `videsclen` to `desclen`,
367
- * Change: Widget settings functionality, two column options, better toggle for playlist and GoTo section
368
- * Enhance: Caching routine (reduce possibility of failed feed fetch)
369
- * Remove: Chromeless and Flash player - leave only Thumbnail and HTML5
370
- * Remove: Aspect Ration 16:10 (so support only 16:9 and 4:3, same as modern YouTube)
371
- * Remove: "Fix No Item" option - not required for YouTube API 3.0
372
-
373
- **OLD RELEASES**
374
-
375
- = 2.4.2.1 (2015-04-24) =
376
- * Fix: devicesupport workaround strip 1st video from playlist and favourites and apply only for channel
377
-
378
- = 2.4.2 (2015-04-22) =
379
- * Fix: Broken layout introduced by missing responsive for embedded playlist, iframe and iframe2
380
- * Fix: Replace amp's with HTML entity in thumbnail link
381
- * Add: Option to disable thumbnail tooltips (shortcode parameter no_thumb_title)
382
- * Add: List of Shortcode attributes to README file
383
- * Add: Danis localisation by GSAdev v. Georg Adamsen
384
- * Micro optimizations
385
-
386
- = 2.4.1.7 (2015-04-20) =
387
- * Quick Fix: strip 1st video from feed that provides notice "YouTube is upgrading to a newer version, which is not supported by this device or app." (more on www.youtube.com/devicesupport) until we finish YouTube Channel 3.0.0 (on the way)
388
-
389
- = 2.4.1.6 (2015-04-15) =
390
- * Fix: missing responsive support for embedded playlist, iframe and iframe2
391
- * Fix: missing support to hide playback controls, info and annotations for embedded playlist
392
-
393
- = 2.4.1.5 (2015-04-13) =
394
- * (2015-04-13) Change: Add dismiss link for Old PHP notice and lower suggested PHP version to 5.3.x
395
- * (2015-02-19) Fix: missing admin notices if ReduxFramework not active
396
- * (2015-02-10) Add: links to explanations for channel ID and vanity URL
397
- * (2015-02-10) Add: goto macro %vanity% to insert vanity ID
398
- * (2015-02-10) Add: field for vanity URL ID
399
- * (2015-02-10) Add: option to select link to user page, channel page or vanity URL for goto link
400
- * (2015-02-10) Remove: option to use channel instead user page for goto link
401
-
402
- = 2.4.1.4 (2015-04-09) =
403
- * (2015-04-09) Add: Notification about old PHP if lower than 5.3.29
404
- * (2015-04-09) Change: Run admin functions only in dashboard
405
- * (2015-02-09) Fix: strip whitespace from the beginngine/end of channel and playlist ID
406
- * (2014-12-30) Fix: prevent Undefined Offset notice when on resource we get less items than user requested in shortcode/widget
407
- * (2014-12-30) Fix: prevent Undefined Offset notice when on resource we get less items than user requested in shortcode/widget
408
- * (2014-12-30) Add: make fallback cache for every feed and use it if no item occurs to avoid No items
409
-
410
- = 2.4.1.3 (2014-12-10) =
411
- * Fix: previous release broke opening lightbox for thumbnails and load YouTube website.
412
-
413
- = 2.4.1.2 (2014-12-07) =
414
- * Add: Add support for hidden controls and YouTube logo in Thumbnail mode.
415
- * Change: Rename Magnific Popup function to prevent clash with original Modest Branding that does not have support for disabling related videos, player controls and YouTube logo.
416
-
417
- = 2.4.1.1 (2014-12-07) =
418
- * Change: Remove parameter `&rel=1` from thumbnail link because that is a default value and can prevent some lightboxes to load video.
419
-
420
- = 2.4.1 (2014-11-15) =
421
- * Fix: Typo in widget `Do not chache` [2014-10-03]
422
- * Fix: do not show global settings notice with link to settings page if not Redux Framerowk is active [2014-11-15]
423
- * Fix: Plugin name on Support tab in global plugin settings. [2014-11-15]
424
- * Change: Remove protocol from links and leave browser to decide should get resource from HTTP or HTTPS (depends on website protocol) [2014-10-03]
425
- * Change: Add height addition for `Fix height taken by controls` for embedded playlist and count control above video [2014-10-03]
426
- * Change: Move debug log from widget to downloadable dynamic JSON [2014-11-15]
427
- * Add: ModestBranding (remove YouTube logo from player control bar) [2014-10-03]
428
- * Add: Responsive (make video optionally responsive) [2014-10-04]
429
- * Add: Support for WordPress 4.1 [2014-11-15]
430
-
431
- = 2.4.0.2 (2014-10-02) =
432
- * Fix: light theme not applicable to embedded playlist [2014-10-01]
433
- * Fix: add clearfix after YTC widget to prevent jumping out of widget block on bad styled themes [2014-10-02]
434
- * Add: explanation that `What to embed` have no effect for embedded playlist (HTML5 always used) [2014-10-01]
435
-
436
- = 2.4.0.1 (2014-10-01) =
437
- * Fix: fatal error - broken execution for embedded playlist with enhanced privacy
438
- * Add: button to discard warning notice for Redux Framework
439
-
440
- = 2.4.0 (2014-10-01) =
441
- * Fix: false options set in shortcode had no effect to output box and default settings always used [20140924]
442
- * Fix: enabled checkbox in global settings could not be unticked (disabled) [20140924]
443
- * Fix: prevent array_slice notice if channel have no uploaded videos [20141001]
444
- * Add: fitVids for responsive videos [20140924]
445
- * Add: option for additional YTC box class in widget and shortcode [20140924]
446
- * Change: global settings page re-implemented with Redux Framework and requires Redux Framework Plugin [20140924]
447
- * Change: rewrite plugin to be more OOP [20140924]
448
- * Change: removed obsolete methods [20140924]
449
- * Change: default box width changed from 220 to 306px [20140924]
450
- * Change: YTC block and video pieces now floated left to enable horizontal stack [20140924]
451
- * Change: update localization support [20140926]
452
- * Change: updated Serbian localization [20140926]
453
- * Change: removed PayPal donation button from widget and moved to plugin Settings page [20141001]
454
-
455
- = 2.2.3 (2014-09-14) =
456
- * Add: option to disable related videos (not supported by chromeless player)
457
- * Enhance: added support for YouTube `rel` parameter in Magnific PopUp IFRAME module
458
- * Minified assets
459
- * Add plugin icon for WordPress 4.x plugin installer
460
- * Update plugin banner
461
-
462
- = 2.2.2 (2014-07-25) =
463
- * Add: admin notices after upgrade to prevent errors and avare users to do ReCache and prevent mixed json_decode / base64_encode strings for cached feeds
464
- * Change: moved ReCache part to Tools tab on settings page
465
-
466
- = 2.2.1 (2014-07-13) =
467
- * Fix: to prevent broken JSON feed, transient caching changed from plain serialized string to base64_encode
468
- * Add: URL parameter `ytc_force_recache` to force recache, also included on Help tab in plugin settings
469
-
470
- = 2.2.0 =
471
- * Add: open thumbnails in lightbox and stay on site, instead opening YouTube page (Magnific Popup jQuery library)
472
- * Add: make thumbnail responsive
473
- * Add: play indicator for thumbnails
474
- * Add: shortcode [youtube_channel]
475
- * Add: tabbed settings page for default options for shortcodes
476
- * Add: Help tab for shortcode parameters
477
- * Change: moved parts of code to helper functions
478
-
479
- = 2.1.0.2 =
480
- * Fix: remove embed object below old IFRAME implementation
481
-
482
- = 2.1.0.1 =
483
- * Change: add back old iframe functionality, second iframe option is async loading
484
-
485
- = 2.1.0 =
486
- * Change: iframe/HTML5 player inject with IFrame Player API https://developers.google.com/youtube/player_parameters#IFrame_Player_API
487
- * Change: use native WP remote file download function wp_remote_get to fetch feeds (prevent some permission errors on some hosts)
488
- * Change: removed height parameter so height is calculated by aspect ratio selection - 16:9 as default
489
- * Add: mute audio on autoplay if iframe/HTML5 is selected
490
- * Add: converter that will port pre-2.0.0 YTC widgets to 2.0.0+ version
491
- * Fix: playlist parser (now allowed dash and underscore in playlist ID)
492
-
493
- = 2.0.0 =
494
- * Fix: undefined vars notices
495
- * Fix: embedding default plugin playlist instead custom set for "Embed standard playlist"
496
- * Add: caching system
497
- * Add: option to link to channel instead to user
498
- * Add: support for enhanced privacy by YouTube
499
- * Enhance: RSS feed replaced with JSON
500
- * Enhance: better formatted debug info with site URL
501
- * Enhance: re-group widget options
502
- * Enhance: updated wording
503
- * Enhance: added tooltips for options
504
- * Enhance: playlist ID detection from URL
505
- * Remove: modified error_reporting
506
-
507
- = 1.5.1 =
508
- * Fix issue in widget settings when no apache_get_version() support on server
509
- * Fix validation errors for widget settings
510
- * Fix broken sidebar issue introduced in 1.5.0 release
511
-
512
- = 1.5.0 =
513
- * Add inline debug tracker
514
- * Fix deprecated functions - changed rss.php by feed.php and split() by extract()
515
- * Fix video description parser for new YouTube feed format
516
- * Fix autoplay for single video bug
517
- * Fix autoplay for multiple videos to play only first video
518
- * Code cleanup
519
- * Update compatibility to WordPress 3.5.1
520
-
521
- = 1.4.0 =
522
- * Added option to show preferred quantity of videos
523
- * Added option to embed classic playlist
524
- * Added class to video container: universal .ytc_video_container and selective (.ytc_video_first, .ytc_video_mid, .ytc_video_last)
525
- * Added class to video title .ytc_title
526
- * Added class to video description text .ytc_description
527
- * Added class to container for link to channel .ytc_link
528
- * Added routine to unique random video from channel if displayed more than one video
529
- * Added option to set `et cetera` string for shortened video description
530
- * Changed option for random video to use channel or playlist
531
- * Fields for width and height converted to number with spinner
532
- * Improved playlist ID handler
533
-
534
- = 1.3.3 =
535
- * Added Czech translation by Ladislav Drábek
536
-
537
- = 1.3.2 =
538
- * Add option to show video description below video
539
- * Add option to shorten video description to N characters
540
- * Add option to use light theme for controls instead of default dark theme (HTML5 iframe and flash object)
541
- * Add option to hide annotations from video
542
-
543
- = 1.3.1 =
544
- * Add support for playlist full URL
545
- * Fixed no random video for playlist
546
-
547
- = 1.3 =
548
- * Fixed z-index problem with flash and iframe object
549
- * Add option to try to fix 'No items' error
550
- * Add donate button in options dialog
551
-
552
- = 1.2 =
553
- * Fixed number of items for random video (min 1, max 50)
554
- * Fixed no-controls for HTML5 iframe
555
-
556
- = 1.1 =
557
- * Added option to use the playlist instead of channel (suggested by Stacy)
558
-
559
- = 1.0 =
560
- * Ported to WordPress 3.2.1
561
- * Added option to set maximum number of items for random video
562
- * Version changed from major.minor.micro to to major.minor format
563
- * Adds Spanish translation
564
-
565
- = 0.1.3 =
566
- * Uses selected() instead of if [dimadin]
567
- * Uses sprintf for better i18n [dimadin]
568
- * Wraps some strings in gettext [dimadin]
569
- * Adds textdomain and loads it [dimadin]
570
- * Adds target="_blank" for channel link [dimadin]
571
- * Adds option to open channel link in popup
572
- * Uses plugin_dir_url() instead of guessing of location [dimadin]
573
- * Loads widget in its own function [dimadin]
574
- * Adds Serbian translation
575
-
576
- = 0.1.2 =
577
- * Option to display random video from channel
578
-
579
- = 0.1.1 =
580
- * Fixed option to toggle video title visibility
581
- * Added option to hide controls for iframe and object videos
582
- * Added option to hide video info
583
- * Enabled autostart for iframe and object videos
584
-
585
- = 0.1.0 =
586
- * Initial release
587
-
588
- == Upgrade Notice ==
589
-
590
- Responsive, bug fixes, support for WordPress 4.1
591
-
592
- == Screenshots ==
593
-
594
- 1. YouTube Channel default plugin settings (General tab)
595
- 2. YouTube Channel customized widget settings
596
- 3. YouTube Channel in WP Customizer and Dynamic Wall layout
597
- 4. How to add YouTube Data API Key to YouTube Channel
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === YouTube Channel ===
2
+ Contributors: urkekg
3
+ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Q6Q762MQ97XJ6
4
+ Tags: youtube, channel, playlist, single, widget, widgets, youtube player, feed, video, thumbnail, embed, sidebar, iframe, html5, responsive
5
+ Requires at least: 3.9.0
6
+ Tested up to: 4.2.2
7
+ Stable tag: 3.0.7
8
+ License: GPLv3
9
+ License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
+
11
+ Show video thumbnails or playable blocks of recent videos from YouTube Channel or Playlist.
12
+
13
+ == Description ==
14
+
15
+ When you need to display sidebar widget with latest video from some YouTube channel or playlist, you can use customisable `YouTube Channel` plugin.
16
+
17
+ Simply insert widget to sidebar, set channel name and if you wish leave all other options on default. You will get latest video from chosen YouTube channel embedded in sidebar widget, with link to channel on the bottom of the widget. If you wish to use playlist instead of channel, just set playlist ID and injoy!
18
+
19
+ If you like this extension and you find it useful, please rate it on the right side.
20
+
21
+ = Features =
22
+ * Display latest videos from YouTube Channel (resources are sorted in reverse chronological order based on the date they were created) or videos naturaly sorted from Favorited Videos, Liked Videos and Playlist
23
+ * Option to get random video from any of 4 resources
24
+ * Responsive (one full width video per row) or non responsive
25
+ * Preferred aspect ratio relative to width (16:9 and 4:3)
26
+ * Custom width for video embeded object (default is 306px)
27
+ * Enhanced Privacy
28
+ * Choose to display video as thumbnail (default), HTML5 (iframe) or HTML5 Asynchronous (iframe2)
29
+ * Thumbnail mode opens video in lightbox
30
+ * Custom caching timeout
31
+ * Optimized data feeds
32
+ * Optional video autoplay with optional muted audio
33
+ * Show customized link to channel below videos
34
+
35
+ = Notice =
36
+
37
+ For fully functional plugin you need to have PHP 5.3 or newer! If you experience issues on older PHP, we can't help you as we don't have access to such old development platform.
38
+
39
+ = Styling =
40
+
41
+ You can use `style.css` from theme to style `YouTube Video` widget content.
42
+
43
+ * `.widget_youtube-channel` – class of whole widget (parent for widget title and YTC block)
44
+ * `.youtube_channel` – YTC block wrapper class. Additional classes are available:
45
+ * `.default` – for non-responsive block
46
+ * `.responsive` – when you have enabled responsive option
47
+ * `.ytc_title` – class of H3 tag for video title above thumbnail/video object
48
+ * `.ytc_video_container` – class of container for single item, plus:
49
+ * `.ytc_video_1`, `.ytc_video_2`, … – class of container for single item with ordering number of item in widget
50
+ * `.ytc_video_first` – class of first container for single item
51
+ * `.ytc_video_mid` – class of all other containers for single item
52
+ * `.ytc_video_last` – class of last container for single item
53
+ * `.ar16_9` – class for Aspect Ratio 16:9
54
+ * `.ar4_3` – class for Aspect Ration 4:3
55
+ * `.ytc_thumb` – class of anchor for Thumbnail mode
56
+ * `.fluid-width-video-wrapper` – class for parent element of IFRAME for enabled responsive
57
+ * `.ytc_description` – class for video description text below thumbnail/video object
58
+ * `.ytc_link` – class of container for link to channel
59
+
60
+ = Known Issues =
61
+
62
+ * Video description for videos from playlist does not work.
63
+ * Removing YouTube logo from playback control bar does not work for all videos
64
+ * Async HTML5 video does not work for 2nd same video on same page (two YTC blocks set to Async HTML5)
65
+ * Thumbnail and opening video in lightbox does not work with `Responz` theme by `Thenify.me` if you wish to hide related videos, because this theme uses original `Magnific Popup` library that does not support `rel` parameter.
66
+
67
+ If WordFence or other malware scan tool detect YouTube Channel fule youtube-channel.php as potential risk because `base64_encode()` and `base64_decode()` functions, remember that we use this two functions to store and restore JSON feeds to transient cache, so potential detection is false positive.
68
+
69
+ = Credits =
70
+
71
+ * For playing videos in lightbox we use enhanced [Magnific Popup](http://dimsemenov.com/plugins/magnific-popup/).
72
+ * Initial textdomain adds done by [dimadin](http://wordpress.org/extend/plugins/profile/dimadin).
73
+ * [Federico Bozo](http://corchoweb.com/) reminded me to fix z-index problem
74
+ * Czech localization by [Ladislav Drábek](http://zholesova.cz)
75
+ * Spanish localization by [Diego Riaño](http://Digital03.net)
76
+ * Danish localisation by [GSAdev v. Georg Adamsen](http://www.gsadev.dk)
77
+
78
+ = Shortcode =
79
+
80
+ Along to Widget, you can add YouTube Channel block inline by using shortcode `[youtube_channel]`. Default plugin parameters will be used for shortcode, but you can customize all parameters per shortcode.
81
+
82
+ **General Settings**
83
+
84
+ * `class` (string) Set custom class if you wish to target special styling for specific YTC block
85
+ * `channel` (string) ID of preferred YouTube channel. Do not set full URL to channel, but just last part from URL - ID (name)
86
+ * `vanity` (string) part after www.youtube.com/c/ from [Custom URL](https://support.google.com/youtube/answer/2657968?hl=en)
87
+ * `playlist` (string) ID of preferred YouTube playlist.
88
+ * `resource` (int) Resource to use for feed:
89
+ * `0` Channel
90
+ * `1` Favorites (for defined channel)
91
+ * `2` Playlist
92
+ * `3` Liked Videos
93
+ * `only_pl` (bool) If you set to use Playlist as resource, you can embed youtube playlist block instead single video from playlist. Simply set this option to true (1 or true)
94
+ * `cache` (int) Period in seconds for caching feed. You can disable caching by setting this option to 0, but if you have a lot of visits, consider at least short caching (couple minutes).
95
+ * `fetch` (int) Number of videos that will be used as stack for random pick (min 2, max 50)
96
+ * `num` (int) Number of videos to display per YTC block.
97
+ * `random` (bool) Option to randomize videos on every page load.
98
+
99
+ **Video Settings**
100
+
101
+ * `ratio` (int) Set preferred aspect ratio for thumbnail and video. You can use:
102
+ * `3` 16:9 (widescreen)
103
+ * `1` 4:3
104
+ * `responsive` (bool) Distribute one full width video per row.
105
+ * `width` (int) Width of thumbnail and video in pixels.
106
+ * `display` (string) Object that will be used to represent video. We have couple predefined options:
107
+ * `thumbnail` Thumbnail will be used and video will be loaded in lightbox. (default)
108
+ * `iframe` HTML5 (iframe)
109
+ * `iframe2` HTML5 (iframe) with asynchronous loading - recommended
110
+ * `no_thumb_title` (bool) By default YouTube thumbnail will have tooltip with info about video title and date of publishing. By setting this option to 1 or true you can hide tooltip
111
+ * `themelight` (bool) By default YouTube have dark play controls theme. By setting this option to 1 or true you can get light theme in player (HTML5 and Flash)
112
+ * `controls` (bool) Set this option to 1 or true to hide playback controls.
113
+ * `autoplay` (bool) Enable autoplay of first video in YTC video stack by setting this option to 1 or true
114
+ * `mute` (bool) Set this option to 1 or true to mute videos set to autoplay on load
115
+ * `norel` (bool) Set this option to 1 or true to hire related videos after finished playbak
116
+ * `nobrand` (bool) Set this option to 1 or true to hire YouTube logo from playback control bar
117
+
118
+ **Content Layout**
119
+
120
+ * `showtitle` (bool) Set to 1 or true to show video title.
121
+ * `titlebelow` (bool) Set to 1 or true to move video title below video.
122
+ * `showdesc` (bool) Set to 1 or true to show video description.
123
+ * `desclen` (int) Set number of characters to cut down length of video description. Set to 0 to use full length description.
124
+ * `noinfo` (bool) Set to 1 or true to hide overlay video infos (from embedded player)
125
+ * `noanno` (bool) Set to 1 or true to hide overlay video annotations (from embedded player)
126
+
127
+ **Link to Channel**
128
+
129
+ * `goto` (bool) Set to 1 or true to display link to channel at the bottom of YTC block.
130
+ * `goto_txt` (string)
131
+ * `popup` (int) Control where link to channel will be opened:
132
+ * `0` open link in same window
133
+ * `1` open link in new window with JavaScript
134
+ * `2` open link in new window with target="_blank" anchor attribute
135
+ * `link_to` (int) URL to link:
136
+ * `2` Vanity custom URL (default)
137
+ * `1` Channel page
138
+ * `0` Legacy username page
139
+
140
+ == Installation ==
141
+
142
+ You can use the built in installer and upgrader, or you can install the plugin manually.
143
+
144
+ 1. You can either use the automatic plugin installer or your FTP program to upload unziped `youtube-channel` directory to your `wp-content/plugins` directory.
145
+ 1. Activate the plugin through the `Plugins` menu in WordPress
146
+ 1. Add YouTube Channel widget to sidebar
147
+ 1. Set Channel ID and save changes
148
+
149
+ If you have to upgrade manually simply repeat the installation steps and re-enable the plugin.
150
+
151
+ = YouTube Data API Key =
152
+ Main difference since v2.x branch is that now we use [YouTube Data API v3](https://developers.google.com/youtube/v3/) so to make plugin to work, you'll need to generate YouTube Data API Key and insert it to General plugin settings.
153
+
154
+ Learn more about [Obtaining authorization credentials](https://developers.google.com/youtube/registering_an_application) and for detailed instructions how to generate your own API Key watch video below.
155
+
156
+ [youtube http://www.youtube.com/watch?v=8NlXV77QO8U]
157
+
158
+ 1. Visit [Google Developers Console](https://console.developers.google.com/project)
159
+ 1. If you don't have any project, create new one. Name it so you can recognize it (for example **My WordPress Website**).
160
+ 1. Select your new project and from LHS sidebar expand group **APIs & auth**, then select item **APIs**
161
+ 1. Locate and click **YouTube Data API** under **YouTube API** section
162
+ 1. Click **Enable API** button
163
+ 1. When you get enabled YouTube Data API in your project, click **Credentials** item from LHS menu **APIs & auth**
164
+ 1. Click **Create New Key** button and select **Server Key**
165
+ 1. Leave empty or enter IP of your website. If you get message **Oops, something went wrong.** make sure you set proper IP, or leave any restriction.
166
+ 1. Click **Create** button
167
+ 1. Copy newly created **API Key**
168
+
169
+ When you generate your own YouTube Data API Key, from your **Dashboard** go to **Settings** -> **YouTube Channel** -> **General** and paster key in to field **YouTube Data API Key**.
170
+
171
+ Also, do not forget to check and update **Channel ID** in plugin's General settings, Widgets and/or shortcodes.
172
+ You can get **Channel ID** from page [Account Advanced](https://www.youtube.com/account_advanced) while you're loagged in to your YouTube account.
173
+
174
+ == Frequently Asked Questions ==
175
+
176
+ = How to get that YouTube Data API Key? =
177
+
178
+ Please folllow [Installation](https://wordpress.org/plugins/youtube-channel/installation/) instructions.
179
+
180
+ = I set everything correct but receiveing 'Oops, something went wrong' message =
181
+
182
+ Right click that message on your website, click *Inspect Element*, expand tag with class *youtube_channel* and look for HTML comment below it, message will look like this:
183
+
184
+ `<!-- YTC ERROR:
185
+ domain: youtube.playlistItem
186
+ reason: playlistNotFound
187
+ message: Not Found
188
+ tip: Please check did you set proper Channel ID. We should display videos from channel videos, but YouTube does not recognize your channel ID UCkVThLIHAZVsJc7f28tIsIws as existing and public resource.
189
+ -->`
190
+
191
+ Do exactly what tip says - check and correct Channel ID in default settings/widget/shortcode.
192
+
193
+ `<!-- YTC ERROR:
194
+ domain: usageLimits
195
+ reason: keyInvalid
196
+ message: Bad Request
197
+ -->`
198
+
199
+ If you followed [Installation](https://wordpress.org/plugins/youtube-channel/installation/) instructions, double check **YouTube Data API Key** entered to Global settings. Do you have correct key generated by you and allowed to be used on your server?
200
+
201
+ `<!-- YTC ERROR:
202
+ domain: usageLimits
203
+ reason: ipRefererBlocked
204
+ message: There is a per-IP or per-Referer restriction configured on your API key and the request does not match these restrictions. Please use the Google Developers Console to update your API key configuration if request from this IP or referer should be allowed.
205
+ -->`
206
+
207
+ We still strugling with that Google's restrictions. If you get final solution, please inform us asap. Try with following possible solutions:
208
+
209
+ 1. If you are using **Jetpack** plugin with enabled **Protect** sub plugin, try to disable it. (kudos to [yudhita](https://wordpress.org/support/profile/yudhita) for tip)
210
+ 1. Try to remove restrictions by referer or IP in your **YouTube Data API Key** and refresh page after couple minutes.
211
+ 1. If that does not help, please try to create new API Key for Server w/o restrictions (not to regenerate existing one).
212
+
213
+ If there is no `YTC ERROR` code in HTML source, visit [Google API Explorer](https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.playlistItems.list?part=snippet&maxResults=5&playlistId=) and append:
214
+
215
+ * for videos from channel replace **UC** with **UU** in Channel ID (so *UCRPqmcpGcJ_gFtTmN_a4aVA* becomes *UURPqmcpGcJ_gFtTmN_a4aVA*)
216
+ * for videos from Favourited videos replace **UC** with **FL** (so *UCRPqmcpGcJ_gFtTmN_a4aVA* becomes *FLRPqmcpGcJ_gFtTmN_a4aVA*)
217
+ * for videos from Liked Videos replace **UC** with **LL** (so *UCRPqmcpGcJ_gFtTmN_a4aVA* becomes *LLRPqmcpGcJ_gFtTmN_a4aVA*)
218
+ * for videos from Playlist simply use Playlist ID (like *PLEC850BE962234400*)
219
+
220
+ Note that all four resources are *playlists* (including channel), so append mentioned ID to field **playlistId** (not to **id**), and click **Execute** button at the bottom of that page.
221
+
222
+ 1. If you receive some error, fix settings.
223
+ 1. If there is no error but you do not get any video in results - contact Google Support
224
+ 1. If there are video results but not displayed with YouTube Channel plugin - [contact us](https://wordpress.org/support/plugin/youtube-channel)
225
+
226
+ = Where to find correct Channel ID and/or Vanity custom Name? =
227
+
228
+ Login to your YouTube account and visit page [Account Advanced](https://www.youtube.com/account_advanced).
229
+
230
+ You'll find your **Vanity Name** as "Your custom URL" in **Channel settins** section on that page. For YTC plugin use only part **after www.youtube.com/c/**, not full URL.
231
+
232
+ **Channel ID** is **YouTube Channel ID** value composed of mixed characters starting with **UC**.
233
+
234
+ = Where to find ID for Favourites and/or Liked Videos? =
235
+
236
+ You will not need that two ID's, in general. But, if you really wish to know, these two ID's are produced from your **Channel ID**. Channel ID start with **UC** (like `UCRPqmcpGcJ_gFtTmN_a4aVA`)
237
+
238
+ * For Favourites ID replace **UC** with **FL** (so you get `FLRPqmcpGcJ_gFtTmN_a4aVA`)
239
+ * For Liked Videos ID replace **UC** with **LL** (so you get `LLRPqmcpGcJ_gFtTmN_a4aVA`)
240
+
241
+ = What is Vanity custom URL? =
242
+
243
+ Check out [Channel custom URL](https://support.google.com/youtube/answer/2657968?ref_topic=3024172&hl=en-GB) article.
244
+
245
+ = Where to find Playlist ID? =
246
+
247
+ Playlist ID can be manualy extracted from YouTube playlist URL. Part of strings after `&list=` that begins with uppercase letters **PL** represent Playlist ID (not full URL).
248
+
249
+ = How to force embeding 320p video with better audio quality? =
250
+
251
+ YouTube provide 320p videos if height of embeded video is set to 320 or more. If you use small YTC video size, 240p will be loaded instead. So, you could not force 720p in tiny YTC.
252
+
253
+ = I enabled option `Hide YT Logo` but YouTube logo is still visible =
254
+
255
+ Modestbranding option does not work for all videos, so a lot of videos will still have YouTube logo in control bar. I recommend to enable option `Hide player controls` instead.
256
+
257
+ Also, even when hidding logo works for your video, on hover or when video is paused in upper right corner will be displayed YouTube link/logo. [Read more here](https://developers.google.com/youtube/player_parameters#modestbranding)
258
+
259
+ = How I can achieve 'wall' layout with one featured thumbnail? =
260
+
261
+ You can try with shortcode combination:
262
+ `[youtube_channel num=7 responsive=1 class=ytc_wall_1-6 resource=2 random=1]`
263
+
264
+ and custom CSS code added to theme style.css or similar customization:
265
+ `.youtube_channel.ytc_wall_1-6 .ytc_video_container {
266
+ padding: 5px;
267
+ box-sizing: border-box;
268
+ }
269
+ .youtube_channel.ytc_wall_1-6 .ytc_video_container:not(:first-child) {
270
+ max-width: 33.333%;
271
+ }
272
+ @media screen and (max-width: 768px) {
273
+ .youtube_channel.ytc_wall_1-6 .ytc_video_container:not(:first-child) {
274
+ max-width: 50%;
275
+ }
276
+ }
277
+ @media screen and (max-width: 480px) {
278
+ .youtube_channel.ytc_wall_1-6 .ytc_video_container:not(:first-child) {
279
+ max-width: 100%;
280
+ }
281
+ }`
282
+
283
+ So, we display thumbnails for 7 random videos from default (global) playlist, and distribute small thumbnails to 3 columns on wide screens, 2 columns under 768px and single thumbnail per row under 480px.
284
+
285
+ = Your plugin does not support *THIS* or *THAT* =
286
+
287
+ If you really need that missing feature ASAP, feel free to [contact me](urosevic.net/wordpress/contact/). Select *Subject* option "Quote For New Feature in YouTube Channel", provide detailed explanation of feature you need, also provide some example if there is such, and I'll send you price for implementation.
288
+
289
+ If you don't wish to pay for enhancements (then you don't care would that be implemented in a week, month, year or so), then send new [Support topic](https://wordpress.org/support/plugin/youtube-channel) with *Topic title* in format **[Feature Request] ...**
290
+
291
+ == Changelog ==
292
+
293
+ = 3.0.7 (2015-05-17) =
294
+ * Fix: Uncaught TypeError: e(...).fitVids is not a function
295
+ * Change: Remove plugin default Channel ID, Vanity custom name, Legacy username and Playlist ID; leave them empty by default and allow them to be empty parameters; throw error if required value not provided. All this to prevent questions like *Why I see your videos on my website* or *Why my website link to your channel*
296
+ * Cleanup: Deprecated widget toggler for Playlist Only depending on selected Resource
297
+ * Cleanup: Deprecated 16:10 styles
298
+ * Optimize: Minimize admin style for widget layout
299
+
300
+ = 3.0.6.2 (2015-05-15) =
301
+ * Fix: Fatal error: Cannot unset string offsets in update.php on line 229 (introduced in 3.0.6.1)
302
+ * Add: Helpfull links to plugin settings page
303
+
304
+ = 3.0.6.1 (2015-05-14) =
305
+ * Fix: Undefined index: random
306
+ * Fix: Unremoved only_pl from global settings
307
+ * Add: Box sizing of .youtube_channel element for crappy themes
308
+
309
+ = 3.0.6 (2015-05-13/14) =
310
+
311
+ * Fix: Prevent Fatal error on PHP<5.3 because required __DIR__ for updater replaced with dirname(__FILE__)
312
+ * Fix: No retrieved or missing videos from some channels so switch `search` to `playlistItems` API call (kudos to @[mmirus](https://wordpress.org/support/profile/mmirus))
313
+ * Add: Embed As Playlist for all resources
314
+ * Add: Clearfix for crappy themes where clearfix does not exists
315
+ * Add: Option to move video title below video (boolean shortcode parameter `titlebelow`)
316
+ * Add: PayPal donate button to settings page
317
+ * Improved: Move YouTube Data API Key to plugin settings and add notification to remove YOUTUBE_DATA_API_KEY from wp-config.php (optional)
318
+ * Improved: Updated shortcode explanation in README and Help tab in plugin settings.
319
+ * Improved: Better tips for 'Oops, something went wrong' message.
320
+ * Change: Wording `Ups` to `Oops`
321
+ * Remove: Options `Embed standard playlist` and `Show random video` from global settings as this should be off by default
322
+ * Remove: Loading of fitVids JS library for test before final removing.
323
+
324
+ = 3.0.5 (2015-05-11/12) =
325
+
326
+ * Fix: Setting back dropdown options with `0` ID does not work on Settings page (Channel as resource to use, Cache timeout, Aspect ratio, What to show, Open link to, Link to)
327
+ * Add: Option to export global settings to JSON and add to Tools tab in settings button to download global settings JSON
328
+ * Change: Update plugin features
329
+ * Improved: Retrieve only fields which will be used for output w/o unused items to reduce
330
+ * Improved: More micro optimizations
331
+
332
+ = 3.0.4 (2015-05-11) =
333
+
334
+ * Add: Tip what to do if error ocurred with YouTube Data API Key printed inside YTC ERROR comment
335
+ * Change: Where to ask for support links in widget
336
+ * Change: Timeout for getting feed increased from 2 to 5 seconds
337
+ * Change: Update FAQ sections in readme file
338
+ * Remove: Check for Redux Framework in debug JSON generator
339
+
340
+ = 3.0.3 (2015-05-10) =
341
+
342
+ * Fix: "Oops, something went wrong." when Playlist selected as resource because wrong switch
343
+ * Fix: Jumping thumbnails in responsive wall on hover in Twenty Fifteen theme because border-bottom for anchors
344
+ * Fix: Another deprecated shortcode attribute backward compatibility (`use_res`)
345
+ * Add: Example of dynamic responsive wall (1 large + 6 small thumbnails) (to [Description](https://wordpress.org/plugins/youtube-channel/))
346
+
347
+ = 3.0.2 (2015-05-10) =
348
+
349
+ * Fix: (typo - experiencing on frontend when no API Key set) PHP Fatal error: Call to undefined function __sprintf() in youtube-channel.php on line 445
350
+ * Fix: shortcode deprecated params `res` and `show` not backward compatibile
351
+
352
+ = 3.0.1 (2015-05-10) =
353
+
354
+ * Fix: Fatal error: Using $this when not in object context in youtube-channel.php on line 89
355
+ * Fix: Link to channel not visible on Twenty Fifteen theme
356
+
357
+ = 3.0.0 (2015-05-07/08/09/10) =
358
+
359
+ * Fix: Migraton of global and widget settings to v3.0.0
360
+ * Add: New Global Settings page as replacement of Redux Framework solution
361
+ * Add: Non-Dismissable Dashboard notice if YouTube Data API Key missing with link to explanation page
362
+ * Change: Option key `ytc_version` to `youtube_channel_version`
363
+ * Change: Shortcode parameters: `res` to `resource`, `show` to `display`; but leave old parameter names for backward compatibility
364
+ * Enhance: Various plugin core micro optimizations
365
+ * Enhance: Dashboard notices
366
+ * Enhance: Proper options migration on plugin update
367
+ * Remove: Redux Framework mentioning from core plugin
368
+ * Remove: Redux Framework config.php
369
+ * Remove: chromeless.swf asset
370
+ * Remove: option `Fix height taken by controls` as now YouTube displays control bar only when video is hovered
371
+
372
+ = 3.0.0alpha2 (2015-03-07/22/24) =
373
+
374
+ * Add: Rewrite plugin to work with YouTube Data API v3
375
+ * Add: Vanity link as option to Link to channel (now supports Legacy username, Channel and Vanity URL) with cleanup Vanity ID routine
376
+ * Add: Liked videos as resource (now support channel, playlists, favourites and liked videos)
377
+ * Add: Admin notification in widget output on front-end if no YouTube Data API Key is defined to prevent errors
378
+ * Add: Dismissable Dashboard notice if PHP version is lower than 5.3 as YTC maybe will not work with older versions.
379
+ * Change: Global and widget option names: `use_res` to `resource`, `cache_time` to `cache`, `maxrnd` to `fetch`, `vidqty` to `num`, `getrnd` to `random`, `to_show` to `display`, `showvidesc` to `showdesc`, `enhprivacy` to `privacy`, `videsclen` to `desclen`,
380
+ * Change: Widget settings functionality, two column options, better toggle for playlist and GoTo section
381
+ * Enhance: Caching routine (reduce possibility of failed feed fetch)
382
+ * Remove: Chromeless and Flash player - leave only Thumbnail and HTML5
383
+ * Remove: Aspect Ration 16:10 (so support only 16:9 and 4:3, same as modern YouTube)
384
+ * Remove: "Fix No Item" option - not required for YouTube API 3.0
385
+
386
+ **OLD RELEASES**
387
+
388
+ = 2.4.2.1 (2015-04-24) =
389
+ * Fix: devicesupport workaround strip 1st video from playlist and favourites and apply only for channel
390
+
391
+ = 2.4.2 (2015-04-22) =
392
+ * Fix: Broken layout introduced by missing responsive for embedded playlist, iframe and iframe2
393
+ * Fix: Replace amp's with HTML entity in thumbnail link
394
+ * Add: Option to disable thumbnail tooltips (shortcode parameter no_thumb_title)
395
+ * Add: List of Shortcode attributes to README file
396
+ * Add: Danis localisation by GSAdev v. Georg Adamsen
397
+ * Micro optimizations
398
+
399
+ = 2.4.1.7 (2015-04-20) =
400
+ * Quick Fix: strip 1st video from feed that provides notice "YouTube is upgrading to a newer version, which is not supported by this device or app." (more on www.youtube.com/devicesupport) until we finish YouTube Channel 3.0.0 (on the way)
401
+
402
+ = 2.4.1.6 (2015-04-15) =
403
+ * Fix: missing responsive support for embedded playlist, iframe and iframe2
404
+ * Fix: missing support to hide playback controls, info and annotations for embedded playlist
405
+
406
+ = 2.4.1.5 (2015-04-13) =
407
+ * (2015-04-13) Change: Add dismiss link for Old PHP notice and lower suggested PHP version to 5.3.x
408
+ * (2015-02-19) Fix: missing admin notices if ReduxFramework not active
409
+ * (2015-02-10) Add: links to explanations for channel ID and vanity URL
410
+ * (2015-02-10) Add: goto macro %vanity% to insert vanity ID
411
+ * (2015-02-10) Add: field for vanity URL ID
412
+ * (2015-02-10) Add: option to select link to user page, channel page or vanity URL for goto link
413
+ * (2015-02-10) Remove: option to use channel instead user page for goto link
414
+
415
+ = 2.4.1.4 (2015-04-09) =
416
+ * (2015-04-09) Add: Notification about old PHP if lower than 5.3.29
417
+ * (2015-04-09) Change: Run admin functions only in dashboard
418
+ * (2015-02-09) Fix: strip whitespace from the beginngine/end of channel and playlist ID
419
+ * (2014-12-30) Fix: prevent Undefined Offset notice when on resource we get less items than user requested in shortcode/widget
420
+ * (2014-12-30) Fix: prevent Undefined Offset notice when on resource we get less items than user requested in shortcode/widget
421
+ * (2014-12-30) Add: make fallback cache for every feed and use it if no item occurs to avoid No items
422
+
423
+ = 2.4.1.3 (2014-12-10) =
424
+ * Fix: previous release broke opening lightbox for thumbnails and load YouTube website.
425
+
426
+ = 2.4.1.2 (2014-12-07) =
427
+ * Add: Add support for hidden controls and YouTube logo in Thumbnail mode.
428
+ * Change: Rename Magnific Popup function to prevent clash with original Modest Branding that does not have support for disabling related videos, player controls and YouTube logo.
429
+
430
+ = 2.4.1.1 (2014-12-07) =
431
+ * Change: Remove parameter `&rel=1` from thumbnail link because that is a default value and can prevent some lightboxes to load video.
432
+
433
+ = 2.4.1 (2014-11-15) =
434
+ * Fix: Typo in widget `Do not chache` [2014-10-03]
435
+ * Fix: do not show global settings notice with link to settings page if not Redux Framerowk is active [2014-11-15]
436
+ * Fix: Plugin name on Support tab in global plugin settings. [2014-11-15]
437
+ * Change: Remove protocol from links and leave browser to decide should get resource from HTTP or HTTPS (depends on website protocol) [2014-10-03]
438
+ * Change: Add height addition for `Fix height taken by controls` for embedded playlist and count control above video [2014-10-03]
439
+ * Change: Move debug log from widget to downloadable dynamic JSON [2014-11-15]
440
+ * Add: ModestBranding (remove YouTube logo from player control bar) [2014-10-03]
441
+ * Add: Responsive (make video optionally responsive) [2014-10-04]
442
+ * Add: Support for WordPress 4.1 [2014-11-15]
443
+
444
+ = 2.4.0.2 (2014-10-02) =
445
+ * Fix: light theme not applicable to embedded playlist [2014-10-01]
446
+ * Fix: add clearfix after YTC widget to prevent jumping out of widget block on bad styled themes [2014-10-02]
447
+ * Add: explanation that `What to embed` have no effect for embedded playlist (HTML5 always used) [2014-10-01]
448
+
449
+ = 2.4.0.1 (2014-10-01) =
450
+ * Fix: fatal error - broken execution for embedded playlist with enhanced privacy
451
+ * Add: button to discard warning notice for Redux Framework
452
+
453
+ = 2.4.0 (2014-10-01) =
454
+ * Fix: false options set in shortcode had no effect to output box and default settings always used [20140924]
455
+ * Fix: enabled checkbox in global settings could not be unticked (disabled) [20140924]
456
+ * Fix: prevent array_slice notice if channel have no uploaded videos [20141001]
457
+ * Add: fitVids for responsive videos [20140924]
458
+ * Add: option for additional YTC box class in widget and shortcode [20140924]
459
+ * Change: global settings page re-implemented with Redux Framework and requires Redux Framework Plugin [20140924]
460
+ * Change: rewrite plugin to be more OOP [20140924]
461
+ * Change: removed obsolete methods [20140924]
462
+ * Change: default box width changed from 220 to 306px [20140924]
463
+ * Change: YTC block and video pieces now floated left to enable horizontal stack [20140924]
464
+ * Change: update localization support [20140926]
465
+ * Change: updated Serbian localization [20140926]
466
+ * Change: removed PayPal donation button from widget and moved to plugin Settings page [20141001]
467
+
468
+ = 2.2.3 (2014-09-14) =
469
+ * Add: option to disable related videos (not supported by chromeless player)
470
+ * Enhance: added support for YouTube `rel` parameter in Magnific PopUp IFRAME module
471
+ * Minified assets
472
+ * Add plugin icon for WordPress 4.x plugin installer
473
+ * Update plugin banner
474
+
475
+ = 2.2.2 (2014-07-25) =
476
+ * Add: admin notices after upgrade to prevent errors and avare users to do ReCache and prevent mixed json_decode / base64_encode strings for cached feeds
477
+ * Change: moved ReCache part to Tools tab on settings page
478
+
479
+ = 2.2.1 (2014-07-13) =
480
+ * Fix: to prevent broken JSON feed, transient caching changed from plain serialized string to base64_encode
481
+ * Add: URL parameter `ytc_force_recache` to force recache, also included on Help tab in plugin settings
482
+
483
+ = 2.2.0 =
484
+ * Add: open thumbnails in lightbox and stay on site, instead opening YouTube page (Magnific Popup jQuery library)
485
+ * Add: make thumbnail responsive
486
+ * Add: play indicator for thumbnails
487
+ * Add: shortcode [youtube_channel]
488
+ * Add: tabbed settings page for default options for shortcodes
489
+ * Add: Help tab for shortcode parameters
490
+ * Change: moved parts of code to helper functions
491
+
492
+ = 2.1.0.2 =
493
+ * Fix: remove embed object below old IFRAME implementation
494
+
495
+ = 2.1.0.1 =
496
+ * Change: add back old iframe functionality, second iframe option is async loading
497
+
498
+ = 2.1.0 =
499
+ * Change: iframe/HTML5 player inject with IFrame Player API https://developers.google.com/youtube/player_parameters#IFrame_Player_API
500
+ * Change: use native WP remote file download function wp_remote_get to fetch feeds (prevent some permission errors on some hosts)
501
+ * Change: removed height parameter so height is calculated by aspect ratio selection - 16:9 as default
502
+ * Add: mute audio on autoplay if iframe/HTML5 is selected
503
+ * Add: converter that will port pre-2.0.0 YTC widgets to 2.0.0+ version
504
+ * Fix: playlist parser (now allowed dash and underscore in playlist ID)
505
+
506
+ = 2.0.0 =
507
+ * Fix: undefined vars notices
508
+ * Fix: embedding default plugin playlist instead custom set for "Embed standard playlist"
509
+ * Add: caching system
510
+ * Add: option to link to channel instead to user
511
+ * Add: support for enhanced privacy by YouTube
512
+ * Enhance: RSS feed replaced with JSON
513
+ * Enhance: better formatted debug info with site URL
514
+ * Enhance: re-group widget options
515
+ * Enhance: updated wording
516
+ * Enhance: added tooltips for options
517
+ * Enhance: playlist ID detection from URL
518
+ * Remove: modified error_reporting
519
+
520
+ = 1.5.1 =
521
+ * Fix issue in widget settings when no apache_get_version() support on server
522
+ * Fix validation errors for widget settings
523
+ * Fix broken sidebar issue introduced in 1.5.0 release
524
+
525
+ = 1.5.0 =
526
+ * Add inline debug tracker
527
+ * Fix deprecated functions - changed rss.php by feed.php and split() by extract()
528
+ * Fix video description parser for new YouTube feed format
529
+ * Fix autoplay for single video bug
530
+ * Fix autoplay for multiple videos to play only first video
531
+ * Code cleanup
532
+ * Update compatibility to WordPress 3.5.1
533
+
534
+ = 1.4.0 =
535
+ * Added option to show preferred quantity of videos
536
+ * Added option to embed classic playlist
537
+ * Added class to video container: universal .ytc_video_container and selective (.ytc_video_first, .ytc_video_mid, .ytc_video_last)
538
+ * Added class to video title .ytc_title
539
+ * Added class to video description text .ytc_description
540
+ * Added class to container for link to channel .ytc_link
541
+ * Added routine to unique random video from channel if displayed more than one video
542
+ * Added option to set `et cetera` string for shortened video description
543
+ * Changed option for random video to use channel or playlist
544
+ * Fields for width and height converted to number with spinner
545
+ * Improved playlist ID handler
546
+
547
+ = 1.3.3 =
548
+ * Added Czech translation by Ladislav Drábek
549
+
550
+ = 1.3.2 =
551
+ * Add option to show video description below video
552
+ * Add option to shorten video description to N characters
553
+ * Add option to use light theme for controls instead of default dark theme (HTML5 iframe and flash object)
554
+ * Add option to hide annotations from video
555
+
556
+ = 1.3.1 =
557
+ * Add support for playlist full URL
558
+ * Fixed no random video for playlist
559
+
560
+ = 1.3 =
561
+ * Fixed z-index problem with flash and iframe object
562
+ * Add option to try to fix 'No items' error
563
+ * Add donate button in options dialog
564
+
565
+ = 1.2 =
566
+ * Fixed number of items for random video (min 1, max 50)
567
+ * Fixed no-controls for HTML5 iframe
568
+
569
+ = 1.1 =
570
+ * Added option to use the playlist instead of channel (suggested by Stacy)
571
+
572
+ = 1.0 =
573
+ * Ported to WordPress 3.2.1
574
+ * Added option to set maximum number of items for random video
575
+ * Version changed from major.minor.micro to to major.minor format
576
+ * Adds Spanish translation
577
+
578
+ = 0.1.3 =
579
+ * Uses selected() instead of if [dimadin]
580
+ * Uses sprintf for better i18n [dimadin]
581
+ * Wraps some strings in gettext [dimadin]
582
+ * Adds textdomain and loads it [dimadin]
583
+ * Adds target="_blank" for channel link [dimadin]
584
+ * Adds option to open channel link in popup
585
+ * Uses plugin_dir_url() instead of guessing of location [dimadin]
586
+ * Loads widget in its own function [dimadin]
587
+ * Adds Serbian translation
588
+
589
+ = 0.1.2 =
590
+ * Option to display random video from channel
591
+
592
+ = 0.1.1 =
593
+ * Fixed option to toggle video title visibility
594
+ * Added option to hide controls for iframe and object videos
595
+ * Added option to hide video info
596
+ * Enabled autostart for iframe and object videos
597
+
598
+ = 0.1.0 =
599
+ * Initial release
600
+
601
+ == Upgrade Notice ==
602
+
603
+ Responsive, bug fixes, support for WordPress 4.1
604
+
605
+ == Screenshots ==
606
+
607
+ 1. YouTube Channel default plugin settings (General tab)
608
+ 2. YouTube Channel customized widget settings
609
+ 3. YouTube Channel in WP Customizer and Dynamic Wall layout
610
+ 4. How to add YouTube Data API Key to YouTube Channel
youtube-channel.php CHANGED
@@ -1,1217 +1,1230 @@
1
- <?php
2
- /*
3
- Plugin Name: YouTube Channel
4
- Plugin URI: http://urosevic.net/wordpress/plugins/youtube-channel/
5
- Description: <a href="widgets.php">Widget</a> that display latest video thumbnail or iframe (HTML5) video from YouTube Channel, Liked Videos, Favourites or Playlist.
6
- Author: Aleksandar Urošević
7
- Version: 3.0.6.2
8
- Author URI: http://urosevic.net/
9
- */
10
- // @TODO make FitVideo optional
11
-
12
- // Exit if accessed directly
13
- if ( ! defined( 'ABSPATH' ) ) exit;
14
-
15
- if ( !class_exists('WPAU_YOUTUBE_CHANNEL') )
16
- {
17
- class WPAU_YOUTUBE_CHANNEL
18
- {
19
-
20
- const DB_VER = 6;
21
- const VER = '3.0.6.2';
22
-
23
- public $plugin_name = "YouTube Channel";
24
- public $plugin_slug = "youtube-channel";
25
- public $plugin_option = "youtube_channel_defaults";
26
-
27
- public $vanity_id = "AleksandarUrosevic";
28
- public $username_id = "urkekg";
29
- public $channel_id = "UCRPqmcpGcJ_gFtTmN_a4aVA"; // user channel UC; user uploads UU; favourites list FL; liked list LL
30
- public $playlist_id = "PLEC850BE962234400";
31
- public $plugin_url;
32
-
33
- /**
34
- * Construct class
35
- */
36
- function __construct() {
37
-
38
- $this->plugin_url = plugin_dir_url(__FILE__);
39
- load_plugin_textdomain( $this->plugin_slug, false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
40
-
41
- // debug JSON
42
- if ( ! empty($_GET['ytc_debug_json_for']) )
43
- $this->generate_debug_json();
44
-
45
- // Activation hook and maybe update trigger
46
- register_activation_hook( __FILE__, array($this, 'activate') );
47
- add_action( 'plugins_loaded', array($this, 'maybe_update') );
48
-
49
- $this->defaults = self::defaults();
50
-
51
- if ( is_admin() ) {
52
-
53
- // Initialize Plugin Settings Magic
54
- add_action( 'init', array($this, 'admin_init') );
55
-
56
- // Add various Dashboard notices (if needed)
57
- add_action( 'admin_notices', array($this, 'admin_notices') );
58
-
59
- // Enqueue scripts and styles for Widgets page
60
- add_action('admin_enqueue_scripts', array($this, 'widget_scripts'));
61
-
62
- } else { // ELSE if ( is_admin() )
63
-
64
- // Enqueue frontend scripts
65
- add_action( 'wp_enqueue_scripts', array($this, 'enqueue_scripts') );
66
- add_action( 'wp_footer', array($this, 'footer_scripts') );
67
-
68
- } // END if ( is_admin() )
69
-
70
- // Load widget
71
- require_once('inc/widget.php');
72
-
73
- // Register shortcodes `youtube_channel` and `ytc`
74
- add_shortcode( 'youtube_channel', array($this, 'shortcode') );
75
- add_shortcode( 'ytc', array($this, 'shortcode') );
76
-
77
- } // END function __construct()
78
-
79
- /**
80
- * Activate the plugin
81
- * Credits: http://solislab.com/blog/plugin-activation-checklist/#update-routines
82
- */
83
- public static function activate() {
84
-
85
- global $WPAU_YOUTUBE_CHANNEL;
86
- $WPAU_YOUTUBE_CHANNEL->init_options();
87
- $WPAU_YOUTUBE_CHANNEL->maybe_update();
88
-
89
- } // end function activate
90
-
91
- /**
92
- * Return initial options
93
- * @return array Global defaults for current plugin version
94
- */
95
- public function init_options() {
96
-
97
- $init = array(
98
- 'vanity' => $this->vanity_id,
99
- 'channel' => $this->channel_id,
100
- 'username' => $this->username_id,
101
- 'playlist' => $this->playlist_id,
102
- 'resource' => 0, // ex use_res
103
- // 'only_pl' => 0,
104
- 'cache' => 300, // 5 minutes // ex cache_time
105
- 'fetch' => 25, // ex maxrnd
106
- 'num' => 1, // ex vidqty
107
- 'privacy' => 0,
108
- // 'random' => 0, // ex getrnd
109
-
110
- 'ratio' => 3, // 3 - 16:9, 1 - 4:3 (deprecated: 2 - 16:10)
111
- 'width' => 306,
112
- 'responsive' => true,
113
- 'display' => 'thumbnail', // thumbnail, iframe, iframe2 (deprecated: chromeless, object)
114
- 'themelight' => 0,
115
- 'controls' => 0,
116
- 'autoplay' => 0,
117
- 'autoplay_mute' => 0,
118
- 'norel' => 0,
119
-
120
- 'showtitle' => 0,
121
- 'showdesc' => 0,
122
- 'desclen' => 0,
123
- 'descappend' => '&hellip;',
124
- 'modestbranding' => 0,
125
- 'hideanno' => 0,
126
- 'hideinfo' => 0,
127
-
128
- 'goto_txt' => 'Visit our channel',
129
- 'showgoto' => 0,
130
- 'popup_goto' => 0, // 0 same window, 1 new window JS, 2 new window target
131
- 'link_to' => 0 // 0 legacy username, 1 channel, 2 vanity
132
- );
133
-
134
- add_option('youtube_channel_version', self::VER, '', 'no');
135
- add_option('youtube_channel_db_ver', self::DB_VER, '', 'no');
136
- add_option($this->plugin_option, $init, '', 'no');
137
-
138
- } // END public function init_options()
139
-
140
- /**
141
- * Check do we need to migrate options
142
- */
143
- public function maybe_update() {
144
-
145
- // bail if this plugin data doesn't need updating
146
- if ( get_option( 'youtube_channel_db_ver' ) >= self::DB_VER ) {
147
- return;
148
- }
149
-
150
- require_once( dirname(__FILE__) . '/update.php' );
151
- au_youtube_channel_update();
152
-
153
- } // END public function maybe_update()
154
-
155
- /**
156
- * Initialize Settings link for Plugins page and create Settings page
157
- */
158
- function admin_init() {
159
-
160
- add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'add_settings_link') );
161
-
162
- require_once( 'inc/settings.php' );
163
-
164
- global $WPAU_YOUTUBE_CHANNEL_SETTINGS;
165
- if ( empty($WPAU_YOUTUBE_CHANNEL_SETTINGS) )
166
- $WPAU_YOUTUBE_CHANNEL_SETTINGS = new WPAU_YOUTUBE_CHANNEL_SETTINGS();
167
-
168
- } // END function admin_init_settings()
169
-
170
- /**
171
- * Append Settings link for Plugins page
172
- * @param array $links array of links on plugins page
173
- */
174
- function add_settings_link($links) {
175
-
176
- $settings_title = __('Settings');
177
- $settings_link = "<a href=\"options-general.php?page={$this->plugin_slug}\">{$settings_title}</a>";
178
- array_unshift( $links, $settings_link );
179
-
180
- // Free some memory
181
- unset($settings_title, $settings_link);
182
-
183
- // Return updated array of links
184
- return $links;
185
-
186
- } // END function add_settings_link()
187
-
188
- /**
189
- * Enqueue admin scripts and styles for widget customization
190
- */
191
- function widget_scripts() {
192
-
193
- global $pagenow;
194
-
195
- // Enqueue only on widget page
196
- if( $pagenow !== 'widgets.php' && $pagenow !== 'customize.php' ) return;
197
-
198
- wp_enqueue_script(
199
- $this->plugin_slug . '-admin',
200
- plugins_url( 'assets/js/admin.min.js', __FILE__ ),
201
- array('jquery'),
202
- self::VER
203
- );
204
- wp_enqueue_style(
205
- $this->plugin_slug . '-admin',
206
- plugins_url( 'assets/css/admin.css', __FILE__ ),
207
- array(),
208
- self::VER
209
- );
210
-
211
- } // END function widget_scripts()
212
-
213
- /**
214
- * Print dashboard notice
215
- * @return string Formatted notice with usefull explanation
216
- */
217
- function admin_notices() {
218
-
219
- // Get array of dismissed notices
220
- $dismissed_notices = get_option('youtube_channel_dismissed_notices');
221
-
222
- // Dismiss notices if requested and then update option in DB
223
- if ( ! empty($_GET['ytc_dismiss_notice_old_php']) ) {
224
- $dismissed_notices['old_php'] = 1;
225
- update_option('youtube_channel_dismissed_notices', $dismissed_notices);
226
- }
227
- if ( ! empty($_GET['ytc_dismiss_notice_apikey_wpconfig']) ) {
228
- $dismissed_notices['apikey_wpconfig'] = 1;
229
- update_option('youtube_channel_dismissed_notices', $dismissed_notices);
230
- }
231
- if ( ! empty($_GET['ytc_dismiss_notice_vanity_option']) ) {
232
- $dismissed_notices['vanity_option'] = 1;
233
- update_option('youtube_channel_dismissed_notices', $dismissed_notices);
234
- }
235
-
236
- // Prepare vars for notices
237
- $settings_page = 'options-general.php?page=youtube-channel';
238
- $notice = array(
239
- 'error' => '',
240
- 'warning' => '',
241
- 'info' => ''
242
- );
243
-
244
- // Inform if PHP version is lower than 5.3
245
- if ( version_compare(PHP_VERSION, "5.3", "<") && ( empty($dismissed_notices) || ( ! empty($dismissed_notices) && empty($dismissed_notices['old_php']) ) ) ) {
246
- $notice['info'] .= sprintf(
247
- __('<p>Your website running on web server with PHP version %s. Please note that <strong>%s</strong> requires PHP at least 5.3 or newer to work properly. <a href="%s" class="dismiss">Dismiss</a></p>', 'youtube-channel'),
248
- PHP_VERSION,
249
- $this->plugin_name,
250
- '?ytc_dismiss_notice_old_php=1'
251
- );
252
- }
253
-
254
- // Inform if YOUTUBE_DATA_API_KEY is still in wp-config.php
255
- if ( defined('YOUTUBE_DATA_API_KEY') && empty($dismissed_notices['apikey_wpconfig']) ) {
256
- $notice['info'] .= sprintf(
257
- __('<p>Since <strong>%s</strong> v3.0.6 we store <strong>YouTube Data API Key</strong> in plugin settings. So, you can safely remove %s define line from your <strong>wp-config.php</strong> file. <a href="%s" class="dismiss">Dismiss</a></p>', 'youtube-channel'),
258
- $this->plugin_name,
259
- 'YOUTUBE_DATA_API_KEY',
260
- '?ytc_dismiss_notice_apikey_wpconfig=1'
261
- );
262
- }
263
-
264
- // No YouTube DATA Api Key?
265
- if ( empty($this->defaults['apikey']) ) {
266
- $notice['error'] .= sprintf(
267
- __('<p>Please note, to make <strong>%s</strong> plugin v3+ work, generate <strong>YouTube Data API Key</strong> as explained <a href="%s" target="_blank">here</a> and add it at <a href="%s">General plugin settings tab</a>.<br><br>If you have any issue with new version of plugin, please ask for help on official <a href="%s" target="_blank">support forum</a>.<br>This notice will disappear when you add missing key as mentioned above!</p>', 'youtube-channel'),
268
- $this->plugin_name,
269
- 'http://urosevic.net/wordpress/plugins/youtube-channel/#youtube_data_api_key',
270
- 'options-general.php?page=youtube-channel&tab=general',
271
- 'https://wordpress.org/support/plugin/youtube-channel'
272
- );
273
- }
274
-
275
- if ( empty($dismissed_notices) || ( ! empty($dismissed_notices) && empty($dismissed_notices['vanity_option']) ) ) {
276
- $notice['warning'] .= sprintf(
277
- __('<p><strong>%s</strong> since version 2.4 supports linking to channel through <em>Vanity/Custom</em> URL. Please review <a href="%s">global</a> and <a href="%s">widgets</a> settings. <a href="%s" class="dismiss">Dismiss</a>', 'youtube-channel'),
278
- $this->plugin_name,
279
- $settings_page,
280
- 'widgets.php',
281
- '?ytc_dismiss_notice_vanity_option=1'
282
- );
283
- }
284
-
285
- foreach ( $notice as $type => $message ) {
286
- if ( ! empty($message) ) {
287
- echo "<div class=\"notice notice-{$type}\">{$message}</div>";
288
- }
289
- }
290
-
291
- } // END function admin_notices()
292
-
293
- /**
294
- * Get default options from DB
295
- * @return array Latest global defaults
296
- */
297
- public function defaults() {
298
-
299
- $defaults = get_option($this->plugin_option);
300
- if ( empty($defaults) ) {
301
- $this->init_options();
302
- }
303
-
304
- return $defaults;
305
-
306
- }
307
-
308
- function enqueue_scripts() {
309
- wp_enqueue_style( 'youtube-channel', plugins_url('assets/css/youtube-channel.min.css', __FILE__), array(), self::VER );
310
-
311
- // enqueue fitVids
312
- // wp_enqueue_script( 'fitvids', plugins_url('assets/js/jquery.fitvids.min.js', __FILE__), array('jquery'), self::VER, true );
313
-
314
- // enqueue magnific-popup
315
- wp_enqueue_script( 'magnific-popup-au', plugins_url('assets/lib/magnific-popup/jquery.magnific-popup.min.js', __FILE__), array('jquery'), self::VER, true );
316
- wp_enqueue_style( 'magnific-popup-au', plugins_url('assets/lib/magnific-popup/magnific-popup.min.css', __FILE__), array(), self::VER );
317
- wp_enqueue_script( 'youtube-channel', plugins_url('assets/js/youtube-channel.min.js', __FILE__), array(), self::VER, true );
318
- } // end function enqueue_scripts
319
-
320
- function footer_scripts() {
321
- // Print JS only if we have set YTC array
322
- if ( ! empty($_SESSION['ytc_html5_js']) )
323
- {
324
- ?>
325
- <!-- YouTube Channel v<?php echo self::VER; ?> -->
326
- <script type="text/javascript">
327
- var tag = document.createElement('script');
328
- tag.src = "//www.youtube.com/iframe_api";
329
- var firstScriptTag = document.getElementsByTagName('script')[0];
330
- firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
331
- function onYouTubeIframeAPIReady() {
332
- <?php echo $_SESSION['ytc_html5_js']; ?>
333
- }
334
- function ytc_mute(event){
335
- event.target.mute();
336
- }
337
- </script>
338
- <?php
339
- }
340
-
341
- } // eof footer_scripts
342
-
343
- public function shortcode($atts) {
344
-
345
- // get general default settings
346
- $instance = $this->defaults();
347
-
348
- // extract shortcode parameters
349
- extract(
350
- shortcode_atts(
351
- array(
352
- 'vanity' => $instance['vanity'],
353
- 'channel' => $instance['channel'],
354
- 'username' => $instance['username'],
355
- 'playlist' => $instance['playlist'],
356
- 'res' => '', // (deprecated, but leave for back compatibility) ex res
357
- 'use_res' => '', // (deprecated, but leave for back compatibility) ex use_res
358
- 'resource' => $instance['resource'], // ex use_res
359
- 'only_pl' => 0, // disabled by default (was: $instance['only_pl'],)
360
- 'cache' => $instance['cache'], // ex cache_time
361
- 'privacy' => $instance['privacy'], // ex showvidesc
362
- 'fetch' => $instance['fetch'], // ex maxrnd
363
- 'num' => $instance['num'], // ex vidqty
364
-
365
- 'random' => 0, // ex getrnd
366
-
367
- 'ratio' => $instance['ratio'],
368
- 'width' => $instance['width'],
369
- 'responsive' => ( ! empty($instance['responsive']) ) ? $instance['responsive'] : '0',
370
-
371
- 'show' => $instance['display'], // (deprecated, but keep for back compatibility) ex to_show
372
- 'display' => $instance['display'],
373
- 'no_thumb_title' => 0,
374
- 'themelight' => $instance['themelight'],
375
- 'controls' => $instance['controls'],
376
- 'autoplay' => $instance['autoplay'],
377
- 'mute' => $instance['autoplay_mute'],
378
- 'norel' => $instance['norel'],
379
-
380
- 'showtitle' => $instance['showtitle'],
381
- 'titlebelow' => 0, // move title below video
382
- 'showdesc' => $instance['showdesc'], // ex showvidesc
383
- 'nobrand' => ( ! empty($instance['modestbranding']) ) ? $instance['modestbranding'] : '0',
384
- 'desclen' => $instance['desclen'], // ex videsclen
385
- 'noinfo' => $instance['hideinfo'],
386
- 'noanno' => $instance['hideanno'],
387
-
388
- 'goto' => $instance['showgoto'],
389
- 'goto_txt' => $instance['goto_txt'],
390
- 'popup' => $instance['popup_goto'],
391
- 'link_to' => $instance['link_to'],
392
-
393
- 'class' => ( ! empty($instance['class']) ) ? $instance['class'] : ''
394
- ),
395
- $atts
396
- )
397
- );
398
-
399
- // backward compatibility for show -> display shortcode parameter
400
- if ( $show !== $display && $show !== $instance['display'] ) {
401
- $display = $show;
402
- }
403
- // backward compatibility for use_res -> resource shortcode parameter
404
- if ( ! empty($use_res) ) {
405
- $resource = $use_res;
406
- } else if ( ! empty($res) ) {
407
- $resource = $res;
408
- }
409
-
410
- // prepare instance for output
411
- $instance['vanity'] = $vanity;
412
- $instance['channel'] = $channel;
413
- $instance['username'] = $username;
414
- $instance['playlist'] = $playlist;
415
- $instance['resource'] = $resource; // resource: 0 channel, 1 favorites, 2 playlist
416
- $instance['only_pl'] = $only_pl; // use embedded playlist - false by default
417
- $instance['cache'] = $cache; // in seconds, def 5min - settings?
418
- $instance['privacy'] = $privacy; // enhanced privacy
419
-
420
- $instance['fetch'] = $fetch;
421
- $instance['num'] = $num; // num: 1
422
-
423
- $instance['random'] = $random; // use embedded playlist - false by default
424
-
425
- // Video Settings
426
- $instance['ratio'] = $ratio; // aspect ratio: 3 - 16:9, 2 - 16:10, 1 - 4:3
427
- $instance['width'] = $width; // 306
428
- $instance['responsive'] = $responsive; // enable responsivenes?
429
- $instance['display'] = $display; // thumbnail, iframe, iframe2
430
- $instance['no_thumb_title'] = $no_thumb_title; // hide tooltip for thumbnails
431
-
432
- $instance['themelight'] = $themelight; // use light theme, dark by default
433
- $instance['controls'] = $controls; // hide controls, false by default
434
- $instance['autoplay'] = $autoplay; // autoplay disabled by default
435
- $instance['autoplay_mute'] = $mute; // mute sound on autoplay - disabled by default
436
- $instance['norel'] = $norel; // hide related videos
437
-
438
- // Content Layout
439
- $instance['showtitle'] = $showtitle; // show video title, disabled by default
440
- $instance['titlebelow'] = $titlebelow; // show video title, disabled by default
441
- $instance['showdesc'] = $showdesc; // show video description, disabled by default
442
- $instance['modestbranding'] = $nobrand; // hide YT logo
443
- $instance['desclen'] = $desclen; // cut video description, number of characters
444
- $instance['hideinfo'] = $noinfo; // hide info by default
445
- $instance['hideanno'] = $noanno; // hide annotations, false by default
446
-
447
- // Link to Channel
448
- $instance['showgoto'] = $goto; // show goto link, disabled by default
449
- $instance['goto_txt'] = $goto_txt; // text for goto link - use settings
450
- $instance['popup_goto'] = $popup; // open channel in: 0 same window, 1 javascript new, 2 target new
451
- $instance['link_to'] = $link_to; // open channel in: 0 same window, 1 javascript new, 2 target new
452
-
453
- // Customization
454
- $instance['class'] = $class; // custom additional class for container
455
-
456
- return implode(array_values($this->output($instance)));
457
- } // END public function shortcode()
458
-
459
- // Print out YTC block
460
- public function output($instance) {
461
-
462
- // print info about API key to admins
463
- // and "Coming soon..." for visitors
464
- if ( empty($this->defaults['apikey']) ) {
465
- if ( current_user_can('manage_options') ) {
466
- $output[] = sprintf(
467
- __('<strong>%s</strong> version 3+ requires <strong>YouTube DATA API Key</strong> to work. <a href="%s" target="_blank">Learn more here</a>.', 'youtube-channel'),
468
- $this->plugin_name,
469
- 'http://urosevic.net/wordpress/plugins/youtube-channel/#youtube_data_api_key'
470
- );
471
-
472
- } else {
473
- $output[] = "Coming soon...";
474
- }
475
- return $output;
476
- }
477
-
478
- // 1) Get resource from widget/shortcode
479
- // 2) If not set, get global default
480
- // 3) if no global, get plugin's default
481
- $resource = intval($instance['resource']);
482
- if ( empty($resource) && $resource !== 0 ) {
483
- $resource = intval($this->defaults['resource']);
484
- if ( empty($resource) ) {
485
- $resource = 0;
486
- }
487
- }
488
-
489
- // Get Channel or Playlist ID based on requested resource
490
- switch ($resource) {
491
-
492
- // Playlist
493
- case '2':
494
- // 1) Get Playlist from shortcode/widget
495
- // 2) If not set, use global default
496
- // 3) If no global, use plugin's default
497
- if ( ! empty($instance['playlist']) ) {
498
- $playlist = trim($instance['playlist']);
499
- } else {
500
- $playlist = trim($this->defaults['playlist']);
501
- if ( $playlist == "" ) {
502
- $playlist = trim($this->playlist_id);
503
- }
504
- }
505
- break;
506
-
507
- // Channel, Favourites, Liked
508
- default:
509
- /* Channel */
510
- // 1) Get channel from shortcode/widget
511
- // 2) If not set, use global default
512
- // 3) If no global, use plugin's default
513
- if ( ! empty($instance['channel']) ) {
514
- $channel = trim($instance['channel']);
515
- } else {
516
- $channel = trim($this->defaults['channel']);
517
- if ( empty($channel) ) {
518
- $channel = trim($this->channel_id);
519
- }
520
- }
521
-
522
- } // END switch ($resource)
523
-
524
- // Set custom class and responsive if needed
525
- $class = $instance['class'] ? $instance['class'] : 'default';
526
- if ( ! empty($instance['responsive']) ) {
527
- $class .= ' responsive';
528
- }
529
-
530
- switch ($resource) {
531
- case 1: // Favourites
532
- $resource_name = 'favourites';
533
- $resource_id = preg_replace('/^UC/', 'FL', $channel);
534
- break;
535
- case 2: // Playlist
536
- $resource_name = 'playlist';
537
- $resource_id = $playlist;
538
- break;
539
- case 3: // Liked
540
- $resource_name = 'liked';
541
- $resource_id = preg_replace('/^UC/', 'LL', $channel);
542
- break;
543
- default: // Channel
544
- $resource_name = 'channel';
545
- $resource_id = preg_replace('/^UC/', 'UU', $channel); //$channel;
546
- }
547
-
548
- // Start output array
549
- $output = array();
550
-
551
- $output[] = "<div class=\"youtube_channel {$class}\">";
552
-
553
- if ( $instance['only_pl'] ) { // print standard playlist
554
-
555
- $output = array_merge($output, self::embed_playlist($resource_id, $instance));
556
-
557
- } else { // videos from channel, favourites, liked or playlist
558
-
559
- // get max items for random video
560
- $fetch = $instance['fetch'];
561
- if ( $fetch < 1 ) { $fetch = 10; } // default 10
562
- elseif ( $fetch > 50 ) { $fetch = 50; } // max 50
563
-
564
- $resource_key = "{$resource_id}_{$fetch}";
565
-
566
- // Do we need cache? let we define cache fallback key
567
- $cache_key_fallback = 'ytc_' . md5($resource_key) . '_fallback';
568
-
569
- // Do cache magic
570
- if ( $instance['cache'] > 0 ) {
571
-
572
- // generate feed cache key for caching time
573
- $cache_key = 'ytc_'.md5($resource_key).'_'.$instance['cache'];
574
-
575
- if ( ! empty($_GET['ytc_force_recache']) )
576
- delete_transient($cache_key);
577
-
578
- // get/set transient cache
579
- if ( false === ($json = get_transient($cache_key)) || empty($json) ) {
580
-
581
- // no cached JSON, get new
582
- $json = $this->fetch_youtube_feed($resource_id, $fetch);
583
-
584
- // set decoded JSON to transient cache_key
585
- set_transient($cache_key, base64_encode($json), $instance['cache']);
586
-
587
- } else {
588
-
589
- // we already have cached feed JSON, get it encoded
590
- $json = base64_decode($json);
591
-
592
- }
593
-
594
- } else {
595
-
596
- // just get fresh feed if cache disabled
597
- $json = $this->fetch_youtube_feed($resource_id, $fetch);
598
-
599
- }
600
-
601
- // free some memory
602
- unset( $response );
603
-
604
- // decode JSON data
605
- $json_output = json_decode($json);
606
-
607
- // if current feed is messed up, try to get it from fallback cache
608
- if ( is_wp_error($json_output) && ! is_object($json_output) && empty($json_output->items) ) {
609
- // error_log("[YTC] Get fallback feed for $feed_url");
610
- // do we have fallback cache?!
611
- if ( true === ( $json_fallback = get_transient( $cache_key_fallback ) ) && ! empty($json_fallback) ) {
612
- $json_output = json_decode( base64_decode($json_fallback) );
613
- // and free memory
614
- unset( $json_fallback );
615
- }
616
- }
617
-
618
- // Predefine `max_items` to prevent undefined notices
619
- $max_items = 0;
620
- if ( ! is_wp_error($json_output) && is_object($json_output) && !empty($json_output->items) ) {
621
- // Sort by date uploaded
622
- $json_entry = $json_output->items;
623
-
624
- $num = $instance['num'];
625
- if ( $num > $fetch ) { $fetch = $num; }
626
- $max_items = ( $fetch > sizeof($json_entry) ) ? sizeof($json_entry) : $fetch;
627
-
628
- if ( ! empty($instance['random']) ) {
629
- $items = array_slice($json_entry, 0, $max_items);
630
- } else {
631
- if ( ! $num ) $num = 1;
632
- $items = array_slice($json_entry, 0, $num);
633
- }
634
- }
635
-
636
- if ($max_items == 0) {
637
-
638
- // is this WP error?
639
- if ( is_wp_error($json_output) ) {
640
- $error_string = $json_output->get_error_message();
641
- $output[] = $error_string;
642
- unset($error_string);
643
- } else {
644
- $output[] = __("Oops, something went wrong.", 'youtube-channel');
645
- // append YouTube DATA API error reason as comment
646
- if ( ! empty($json_output) && is_object($json_output) && !empty($json_output->error->errors) ) {
647
- $output[] = "<!-- YTC ERROR:\n";
648
- $output[] = 'domain: ' . $json_output->error->errors[0]->domain . "\n";
649
- $output[] = 'reason: ' . $json_output->error->errors[0]->reason . "\n";
650
- $output[] = 'message: ' . $json_output->error->errors[0]->message . "\n";
651
-
652
- if ( $json_output->error->errors[0]->reason == 'playlistNotFound' ) {
653
- if ( $resource_name == 'playlist' ) {
654
- $output[] = "tip: Please check did you set existing Playlist ID. We should display videos from {$resource_name} videos, but YouTube does not recognize {$resource_id} as existing and public playlist.\n";
655
- } else {
656
- $output[] = "tip: Please check did you set proper Channel ID. We should display videos from {$resource_name} videos, but YouTube does not recognize your channel ID {$channel} as existing and public resource.\n";
657
- }
658
- }
659
- elseif ( $json_output->error->errors[0]->reason == 'keyInvalid' ) {
660
- $output[] = "tip: Double check YouTube Data API Key on General plugin tab and make sure it`s correct. Check https://wordpress.org/plugins/youtube-channel/installation/\n";
661
- }
662
- elseif ( $json_output->error->errors[0]->reason == 'ipRefererBlocked' ) {
663
- $output[] = "tip: Check YouTube Data API Key restrictions, empty cache if enabled and append in browser address bar parameter ?ytc_force_recache=1\n";
664
- }
665
- elseif ( $json_output->error->errors[0]->reason == 'invalidChannelId' ) {
666
- $output[] = "tip: You have set wrong Channel ID. Fix that in General plugin settings, Widget and/or shortcode. Check https://wordpress.org/plugins/youtube-channel/faq/\n";
667
- }
668
- $output[] = "-->\n";
669
- }
670
- }
671
-
672
- } else { // ELSE if ($max_items == 0)
673
-
674
- // looks that feed is OK, let we update fallback that never expire
675
- set_transient($cache_key_fallback, base64_encode($json), 0);
676
-
677
- // and now free some memory
678
- unset ( $json, $json_output, $json_entry );
679
-
680
- // set array for unique random item
681
- if ( ! empty($instance['random']) ) {
682
- $random_used = array();
683
- }
684
-
685
- /* AU:20141230 reduce number of videos if requested > available */
686
- if ( $num > sizeof($items) ) {
687
- $num = sizeof($items);
688
- }
689
-
690
- for ($y = 1; $y <= $num; ++$y) {
691
- if ( ! empty($instance['random']) ) {
692
-
693
- $random_item = mt_rand( 0, (count($items)-1) );
694
- while ( $y > 1 && in_array($random_item, $random_used) ) {
695
- $random_item = mt_rand(0, (count($items)-1));
696
- }
697
- $random_used[] = $random_item;
698
- $item = $items[ $random_item ];
699
- } else {
700
- $item = $items[ $y - 1 ];
701
- }
702
-
703
- // print single video block
704
- $output = array_merge( $output, $this->ytc_print_video($item, $instance, $y) );
705
- }
706
- // Free some memory
707
- unset($random_used, $random_item, $json);
708
-
709
- } // END if ($max_items == 0)
710
-
711
- } // single playlist or ytc way
712
-
713
- if ( ! empty($instance['showgoto']) ) {
714
- $output = array_merge( $output, $this->ytc_channel_link($instance) ); // insert link to channel on bootom of widget
715
- }
716
-
717
- $output[] = '</div><!-- .youtube_channel -->';
718
-
719
- // fix overflow on crappy themes
720
- $output[] = '<div class="clearfix"></div>';
721
-
722
- return $output;
723
-
724
- } // END public function output($instance)
725
-
726
- // --- HELPER FUNCTIONS ---
727
-
728
- /**
729
- * Download YouTube video feed through API 3.0
730
- * @param string $id ID of resource
731
- * @param integer $items Number of items to fetch (min 2, max 50)
732
- * @return array JSON with videos
733
- */
734
- function fetch_youtube_feed($resource_id, $items) {
735
-
736
- $feed_url = 'https://www.googleapis.com/youtube/v3/playlistItems?';
737
- $feed_url .= 'part=snippet';
738
- $feed_url .= "&playlistId={$resource_id}";
739
- $feed_url .= '&fields=items(snippet(title%2Cdescription%2CpublishedAt%2CresourceId(videoId)))';
740
- $feed_url .= "&maxResults={$items}";
741
- $feed_url .= "&key={$this->defaults['apikey']}";
742
-
743
- $wprga = array(
744
- 'timeout' => 5 // five seconds only
745
- );
746
- $response = wp_remote_get($feed_url, $wprga);
747
- $json = wp_remote_retrieve_body( $response );
748
-
749
- // free some memory
750
- unset($response);
751
-
752
- return $json;
753
-
754
- } // END function fetch_youtube_feed($resource_id, $items)
755
-
756
- // function to calculate height by width and ratio
757
- function height_ratio($width=306, $ratio) {
758
-
759
- switch ($ratio)
760
- {
761
- case 1:
762
- $height = round(($width / 4 ) * 3);
763
- break;
764
- case 2:
765
- case 3:
766
- default:
767
- $height = round(($width / 16 ) * 9);
768
- }
769
- return $height;
770
- } // END function height_ratio($width=306, $ratio)
771
-
772
- /**
773
- * Generate link to YouTUbe channel/user
774
- * @param array $instance widget or shortcode settings
775
- * @return array components prepared for output
776
- */
777
- function ytc_channel_link($instance) {
778
-
779
- // initialize array
780
- $output = array();
781
-
782
- // do we need to show goto link?
783
- if ( $instance['showgoto'] ) {
784
-
785
- $link_to = $instance['link_to'];
786
-
787
- $channel = trim($instance['channel']);
788
- if ( empty( $channel ) )
789
- $channel = $this->channel_id;
790
-
791
- $username = trim($instance['username']);
792
- if ( empty( $username ) )
793
- $username = $this->username_id;
794
-
795
- // sanity vanity content (strip all in front of last slash to cleanup vanity ID only)
796
- $vanity = trim($instance['vanity']);
797
- if ( ! empty( $vanity ) && strpos($vanity, 'youtube.com') !== false )
798
- $vanity = preg_replace('/^.*\//', '', $vanity);
799
-
800
- // if $vanity is empty, use default
801
- if ( empty( $vanity ) )
802
- $vanity = $this->vanity_id;
803
-
804
- $goto_txt = trim($instance['goto_txt']);
805
-
806
- if ( $goto_txt == "" )
807
- $goto_txt = __('Visit our YouTube channel', 'youtube-channel');
808
-
809
- $goto_txt = str_replace('%username%', $username, $goto_txt);
810
- $goto_txt = str_replace('%channel%', $channel, $goto_txt);
811
- $goto_txt = str_replace('%vanity%', $vanity, $goto_txt);
812
-
813
- $output[] = '<div class="clearfix"></div>';
814
- $output[] = '<div class="ytc_link">';
815
-
816
- $goto_url = "https://www.youtube.com/";
817
- if ( $link_to == '2' ) { // vanity
818
- $goto_url .= "c/$vanity";
819
- } else if ( $link_to == '0') { // legacy username
820
- $goto_url .= "user/$username";
821
- } else { // channel (default)
822
- $goto_url .= "channel/$channel";
823
- }
824
-
825
- $newtab = __("in new window/tab", 'youtube-channel');
826
-
827
- $output[] = '<p>';
828
- switch ( $instance['popup_goto'] ) {
829
- case 1:
830
- $output[] = "<a href=\"javascript: window.open('{$goto_url}'); void 0;\" title=\"{$goto_txt} {$newtab}\">{$goto_txt}</a>";
831
- break;
832
- case 2:
833
- $output[] = "<a href=\"{$goto_url}\" target=\"_blank\" title=\"{$goto_txt} {$newtab}\">{$goto_txt}</a>";
834
- break;
835
- default:
836
- $output[] = "<a href=\"{$goto_url}\" title=\"{$goto_txt}\">$goto_txt</a>";
837
- } // switch popup_goto
838
- $output[] = '</p>';
839
- $output[] = '</div>';
840
-
841
- } // showgoto
842
-
843
- return $output;
844
- } // end function ytc_channel_link
845
-
846
- /* function to print video block */
847
- function ytc_print_video($item, $instance, $y) {
848
-
849
- // get hideinfo, autoplay and controls settings
850
- // where this is used?
851
- $hideinfo = $instance['hideinfo'];
852
- $autoplay = $instance['autoplay'];
853
- $autoplay_mute = $instance['autoplay_mute'];
854
- $controls = $instance['controls'];
855
- $norel = $instance['norel'];
856
- $class = $instance['class'];
857
- $modestbranding = $instance['modestbranding'];
858
-
859
- // set width and height
860
- $width = ( empty($instance['width']) ) ? 306 : $instance['width'];
861
- $height = $this->height_ratio($width, $instance['ratio']);
862
-
863
- // calculate image height based on width for 4:3 thumbnail
864
- $imgfixedheight = $width / 4 * 3;
865
-
866
- // which type to show
867
- $display = (empty($instance['display'])) ? 'object' : $instance['display'];
868
- $hideanno = $instance['hideanno'];
869
- $themelight = $instance['themelight'];
870
- /* end of video settings */
871
-
872
- // Prepare Video ID from Resource
873
- $yt_id = $item->snippet->resourceId->videoId;
874
- $yt_url = "v/$yt_id";
875
- $yt_thumb = "//img.youtube.com/vi/$yt_id/0.jpg"; // zero for HD thumb
876
- $yt_video = "//www.youtube.com/watch?v=" . $yt_id;
877
-
878
- $yt_title = $item->snippet->title;
879
- $yt_date = $item->snippet->publishedAt;
880
-
881
- switch ($y) {
882
- case 1:
883
- $vnumclass = 'first';
884
- break;
885
- case $instance['num']:
886
- $autoplay = false;
887
- $vnumclass = 'last';
888
- break;
889
- default:
890
- $vnumclass = 'mid';
891
- $autoplay = false;
892
- break;
893
- }
894
-
895
- // set proper class for responsive thumbs per selected aspect ratio
896
- switch ($instance['ratio'])
897
- {
898
- case 1: $arclass = 'ar4_3'; break;
899
- default: $arclass = 'ar16_9';
900
- }
901
- $output[] = "<div class=\"ytc_video_container ytc_video_{$y} ytc_video_{$vnumclass} ${arclass}\" style=\"width:{$width}px\">";
902
-
903
- // show video title above video?
904
- if ( ! empty($instance['showtitle']) && empty($instance['titlebelow']) ) {
905
- $output[] = "<h3 class=\"ytc_title\">{$yt_title}</h3>";
906
- }
907
-
908
- // Define object ID
909
- $ytc_vid = "ytc_{$yt_id}";
910
-
911
- // Enhanced privacy?
912
- $youtube_domain = $this->youtube_domain($instance);
913
-
914
- // Print out video
915
- if ( $display == "iframe" ) {
916
- if ( empty($usepl) ) {
917
- $yt_url = $yt_id;
918
- }
919
-
920
- // Start wrapper for responsive item
921
- if ( $instance['responsive'] ) {
922
- $output[] = '<div class="fluid-width-video-wrapper">';
923
- }
924
-
925
- $output[] = "<iframe title=\"YouTube Video Player\" width=\"{$width}\" height=\"{$height}\" src=\"//{$youtube_domain}/embed/{$yt_url}?wmode=opaque";
926
- if ( $controls ) $output[] = "&amp;controls=0";
927
- if ( $hideinfo ) $output[] = "&amp;showinfo=0";
928
- if ( $autoplay ) $output[] = "&amp;autoplay=1";
929
- if ( $hideanno ) $output[] = "&amp;iv_load_policy=3";
930
- if ( $themelight ) $output[] = "&amp;theme=light";
931
- if ( $modestbranding ) $output[] = "&amp;modestbranding=1";
932
- // disable related videos
933
- if ( $norel ) $output[] = "&amp;rel=0";
934
-
935
- $output[] = "\" style=\"border:0;\" allowfullscreen id=\"{$ytc_vid}\"></iframe>";
936
-
937
- // Close wrapper for responsive item
938
- if ( $instance['responsive'] ) {
939
- $output[] = '</div>';
940
- }
941
-
942
- } else if ( $display == "iframe2" ) {
943
-
944
- // youtube API async
945
- if ( empty($usepl) ) $yt_url = $yt_id;
946
-
947
- $js_rel = ( $norel ) ? "rel: 0," : '';
948
- $js_controls = ( $controls ) ? "controls: 0," : '';
949
- $js_showinfo = ( $hideinfo ) ? "showinfo: 0," : '';
950
- $js_iv_load_policy = ( $hideanno ) ? "iv_load_policy: 3," : '';
951
- $js_theme = ( $themelight ) ? "theme: 'light'," : '';
952
- $js_autoplay = ( $autoplay ) ? "autoplay: 1," : '';
953
- $js_modestbranding = ( $modestbranding ) ? "modestbranding: 1," : '';
954
- $js_autoplay_mute = ( $autoplay && $autoplay_mute ) ? "events: {'onReady': ytc_mute}" : '';
955
- $js_player_id = str_replace('-', '_', $yt_url);
956
-
957
- // Start wrapper for responsive item
958
- if ( $instance['responsive'] ) {
959
- $output[] = '<div class="fluid-width-video-wrapper">';
960
- }
961
-
962
- $output[] = '<div id="ytc_player_'.$js_player_id.'"></div>';
963
-
964
- // Close wrapper for responsive item
965
- if ( $instance['responsive'] ) {
966
- $output[] = '</div>';
967
- }
968
-
969
- $site_domain = $_SERVER['HTTP_HOST'];
970
- $ytc_html5_js = <<<JS
971
- var ytc_player_$js_player_id;
972
- ytc_player_$js_player_id = new YT.Player('ytc_player_$js_player_id', {
973
- height: '$height',
974
- width: '$width',
975
- videoId: '$yt_url',
976
- enablejsapi: 1,
977
- playerVars: {
978
- $js_autoplay $js_showinfo $js_controls $js_theme $js_rel $js_modestbranding wmmode: 'opaque'
979
- },
980
- origin: '$site_domain',
981
- $js_iv_load_policy $js_autoplay_mute
982
- });
983
- JS;
984
-
985
- // prepare JS for footer
986
- if ( empty($_SESSION['ytc_html5_js']) )
987
- $_SESSION['ytc_html5_js'] = $ytc_html5_js;
988
- else
989
- $_SESSION['ytc_html5_js'] .= $ytc_html5_js;
990
-
991
- } else { // default is thumbnail
992
-
993
- // set proper class for responsive thumbs per selected aspect ratio
994
- switch ($instance['ratio']) {
995
- case 1:
996
- $arclass = 'ar4_3';
997
- break;
998
- default:
999
- $arclass = 'ar16_9';
1000
- }
1001
-
1002
- // Do we need tooltip for thumbnail?
1003
- if ( empty($instance['no_thumb_title']) ) {
1004
- $title = sprintf( __('Watch video %1$s published on %2$s', 'youtube-channel' ), $yt_title, $yt_date );
1005
- }
1006
-
1007
- $p = '';
1008
- if ( $norel ) $p .= '&amp;rel=0';
1009
- if ( $modestbranding ) $p .= "&amp;modestbranding=1";
1010
- if ( $controls ) $p .= "&amp;controls=0";
1011
-
1012
- // Do we need thumbnail w/ or w/o tooltip
1013
- if ( empty($instance['no_thumb_title']) ) {
1014
- $output[] = "<a href=\"${yt_video}${p}\" title=\"{$yt_title}\" class=\"ytc_thumb ytc-lightbox {$arclass}\"><span style=\"background-image: url({$yt_thumb});\" title=\"{$title}\" id=\"{$ytc_vid}\"></span></a>";
1015
- } else {
1016
- $output[] = "<a href=\"${yt_video}${p}\" class=\"ytc_thumb ytc-lightbox {$arclass}\"><span style=\"background-image: url({$yt_thumb});\" id=\"{$ytc_vid}\"></span></a>";
1017
- }
1018
-
1019
- } // what to show conditions
1020
-
1021
- // show video title below video?
1022
- if ( ! empty($instance['showtitle']) && ! empty($instance['titlebelow']) ) {
1023
- $output[] = "<h3 class=\"ytc_title\">{$yt_title}</h3>";
1024
- }
1025
-
1026
- // do we need to show video description?
1027
- if ( $instance['showdesc'] ) {
1028
-
1029
- $video_description = $item->snippet->description;
1030
- $etcetera = '';
1031
- if ( $instance['desclen'] > 0 ) {
1032
- if ( strlen($video_description) > $instance['desclen'] ) {
1033
- $video_description = substr($video_description, 0, $instance['desclen']);
1034
- if ( $instance['descappend'] ) {
1035
- $etcetera = $instance['descappend'];
1036
- } else {
1037
- $etcetera = '&hellip;';
1038
- }
1039
- }
1040
- }
1041
-
1042
- if ( ! empty($video_description) ) {
1043
- $output[] = "<p class=\"ytc_description\">{$video_description}{$etcetera}</p>";
1044
- }
1045
-
1046
- }
1047
-
1048
- $output[] = '</div><!-- .ytc_video_container -->';
1049
-
1050
- return $output;
1051
- } // end function ytc_print_video
1052
-
1053
- /* function to print standard playlist embed code */
1054
- function embed_playlist($resource_id, $instance) {
1055
-
1056
- $width = ( empty($instance['width']) ) ? 306 : $instance['width'];
1057
- $height = self::height_ratio($width, $instance['ratio']);
1058
- $autoplay = (empty($instance['autoplay'])) ? '' : '&autoplay=1';
1059
- $theme = (empty($instance['themelight'])) ? '' : '&theme=light';
1060
- $modestbranding = (empty($instance['modestbranding'])) ? '' : '&modestbranding=1';
1061
- $rel = (empty($instance['norel'])) ? '' : '&rel=0';
1062
-
1063
- // enhanced privacy
1064
- $youtube_domain = $this->youtube_domain($instance);
1065
-
1066
- $output[] = "<div class=\"ytc_video_container ytc_video_1 ytc_video_single ytc_playlist_only\">";
1067
- $output[] = "<iframe src=\"//{$youtube_domain}/embed/videoseries?list={$resource_id}{$autoplay}{$theme}{$modestbranding}{$rel}\"";
1068
- $output[] = " width=\"{$width}\" height=\"{$height}\" frameborder=\"0\"></iframe></div>";
1069
-
1070
- return $output;
1071
-
1072
- } // END function embed_playlist($resource_id, $instance)
1073
-
1074
- // Helper function cache_time()
1075
- function cache_time($cache_time)
1076
- {
1077
- $times = array(
1078
- 'minute' => array(
1079
- 1 => __("1 minute", 'youtube-channel'),
1080
- 5 => __("5 minutes", 'youtube-channel'),
1081
- 15 => __("15 minutes", 'youtube-channel'),
1082
- 30 => __("30 minutes", 'youtube-channel')
1083
- ),
1084
- 'hour' => array(
1085
- 1 => __("1 hour", 'youtube-channel'),
1086
- 2 => __("2 hours", 'youtube-channel'),
1087
- 5 => __("5 hours", 'youtube-channel'),
1088
- 10 => __("10 hours", 'youtube-channel'),
1089
- 12 => __("12 hours", 'youtube-channel'),
1090
- 18 => __("18 hours", 'youtube-channel')
1091
- ),
1092
- 'day' => array(
1093
- 1 => __("1 day", 'youtube-channel'),
1094
- 2 => __("2 days", 'youtube-channel'),
1095
- 3 => __("3 days", 'youtube-channel'),
1096
- 4 => __("4 days", 'youtube-channel'),
1097
- 5 => __("5 days", 'youtube-channel'),
1098
- 6 => __("6 days", 'youtube-channel')
1099
- ),
1100
- 'week' => array(
1101
- 1 => __("1 week", 'youtube-channel'),
1102
- 2 => __("2 weeks", 'youtube-channel'),
1103
- 3 => __("3 weeks", 'youtube-channel'),
1104
- 4 => __("1 month", 'youtube-channel')
1105
- )
1106
- );
1107
-
1108
- $out = "";
1109
- foreach ($times as $period => $timeset)
1110
- {
1111
- switch ($period)
1112
- {
1113
- case 'minute':
1114
- $sc = MINUTE_IN_SECONDS;
1115
- break;
1116
- case 'hour':
1117
- $sc = HOUR_IN_SECONDS;
1118
- break;
1119
- case 'day':
1120
- $sc = DAY_IN_SECONDS;
1121
- break;
1122
- case 'week':
1123
- $sc = WEEK_IN_SECONDS;
1124
- break;
1125
- }
1126
-
1127
- foreach ($timeset as $n => $s)
1128
- {
1129
- $sec = $sc * $n;
1130
- $out .='<option value="'.$sec.'" '. selected( $cache_time, $sec, 0 ).'>'.__($s, $this->plugin_slug).'</option>';
1131
- unset($sec);
1132
- }
1133
- }
1134
- return $out;
1135
- } // end function cache_time
1136
-
1137
- function youtube_domain($instance) {
1138
- $youtube_domain = ( !empty($instance['privacy']) ) ? 'www.youtube-nocookie.com' : 'www.youtube.com';
1139
- return $youtube_domain;
1140
- } // end function youtube_domain
1141
-
1142
- function clean_playlist_id($playlist) {
1143
- if ( substr($playlist,0,4) == "http" ) {
1144
- // if URL provided, extract playlist ID
1145
- $playlist = preg_replace('/.*list=PL([A-Za-z0-9\-\_]*).*/','$1', $playlist);
1146
- } else if ( substr($playlist,0,2) == 'PL' ) {
1147
- $playlist = substr($playlist,2);
1148
- }
1149
- return $playlist;
1150
- } // end function clean_playlist_id
1151
-
1152
- function generate_debug_json()
1153
- {
1154
- global $wp_version;
1155
-
1156
- // get widget ID from parameter
1157
- $for = $_GET['ytc_debug_json_for'];
1158
-
1159
- if ( $for == 'global' ) {
1160
- // global settings
1161
- $options = get_option('youtube_channel_defaults');
1162
-
1163
- if ( ! is_array($options) )
1164
- return;
1165
-
1166
- // remove YouTube Data API Key from config JSON
1167
- unset($options['apikey']);
1168
-
1169
- } else {
1170
- // for widget
1171
- // prepare option name and widget ID
1172
- $option_name = "widget_".substr($for,0,strrpos($for,"-"));
1173
- $widget_id = substr($for,strrpos($for,"-")+1);
1174
-
1175
- // get YTC widgets options
1176
- $widget_options = get_option($option_name);
1177
-
1178
- if ( ! is_array($widget_options[$widget_id]) )
1179
- return;
1180
-
1181
- $options = $widget_options[$widget_id];
1182
- unset ($widget_options);
1183
- }
1184
-
1185
- // prepare debug data with settings of current widget
1186
- $data = array_merge(
1187
- array(
1188
- 'date' => date("r"),
1189
- 'server' => $_SERVER["SERVER_SOFTWARE"],
1190
- 'php' => PHP_VERSION,
1191
- 'wp' => $wp_version,
1192
- 'ytc' => self::VER,
1193
- 'url' => get_site_url(),
1194
- 'for' => $for
1195
- ),
1196
- $options
1197
- );
1198
-
1199
- // return JSON file
1200
- header('Content-disposition: attachment; filename='.$for.'.json');
1201
- header('Content-Type: application/json');
1202
- echo json_encode($data);
1203
-
1204
- // destroy vars
1205
- unset($data,$options,$widget_id,$option_name,$for);
1206
-
1207
- // exit now, because we need only debug data in JSON file, not settings or any other page
1208
- exit;
1209
- }
1210
- } // end class
1211
- } // end class check
1212
-
1213
- // add_action('plugins_loaded', create_function( '', '$WPAU_YOUTUBE_CHANNEL = new WPAU_YOUTUBE_CHANNEL();' ) );
1214
-
1215
- global $WPAU_YOUTUBE_CHANNEL;
1216
- if ( empty($WPAU_YOUTUBE_CHANNEL) )
1217
- $WPAU_YOUTUBE_CHANNEL = new WPAU_YOUTUBE_CHANNEL();
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: YouTube Channel
4
+ Plugin URI: http://urosevic.net/wordpress/plugins/youtube-channel/
5
+ Description: <a href="widgets.php">Widget</a> that display latest video thumbnail or iframe (HTML5) video from YouTube Channel, Liked Videos, Favourites or Playlist.
6
+ Author: Aleksandar Urošević
7
+ Version: 3.0.7
8
+ Author URI: http://urosevic.net/
9
+ */
10
+
11
+ // Exit if accessed directly
12
+ if ( ! defined( 'ABSPATH' ) ) exit;
13
+
14
+ if ( !class_exists('WPAU_YOUTUBE_CHANNEL') )
15
+ {
16
+ class WPAU_YOUTUBE_CHANNEL
17
+ {
18
+
19
+ const DB_VER = 7;
20
+ const VER = '3.0.7';
21
+
22
+ public $plugin_name = "YouTube Channel";
23
+ public $plugin_slug = "youtube-channel";
24
+ public $plugin_option = "youtube_channel_defaults";
25
+ public $plugin_url;
26
+
27
+ /**
28
+ * Construct class
29
+ */
30
+ function __construct() {
31
+
32
+ $this->plugin_url = plugin_dir_url(__FILE__);
33
+ load_plugin_textdomain( $this->plugin_slug, false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
34
+
35
+ // debug JSON
36
+ if ( ! empty($_GET['ytc_debug_json_for']) )
37
+ $this->generate_debug_json();
38
+
39
+ // Activation hook and maybe update trigger
40
+ register_activation_hook( __FILE__, array($this, 'activate') );
41
+ add_action( 'plugins_loaded', array($this, 'maybe_update') );
42
+
43
+ $this->defaults = self::defaults();
44
+
45
+ if ( is_admin() ) {
46
+
47
+ // Initialize Plugin Settings Magic
48
+ add_action( 'init', array($this, 'admin_init') );
49
+
50
+ // Add various Dashboard notices (if needed)
51
+ add_action( 'admin_notices', array($this, 'admin_notices') );
52
+
53
+ // Enqueue scripts and styles for Widgets page
54
+ add_action('admin_enqueue_scripts', array($this, 'widget_scripts'));
55
+
56
+ } else { // ELSE if ( is_admin() )
57
+
58
+ // Enqueue frontend scripts
59
+ add_action( 'wp_enqueue_scripts', array($this, 'enqueue_scripts') );
60
+ add_action( 'wp_footer', array($this, 'footer_scripts') );
61
+
62
+ } // END if ( is_admin() )
63
+
64
+ // Load widget
65
+ require_once('inc/widget.php');
66
+
67
+ // Register shortcodes `youtube_channel` and `ytc`
68
+ add_shortcode( 'youtube_channel', array($this, 'shortcode') );
69
+ add_shortcode( 'ytc', array($this, 'shortcode') );
70
+
71
+ } // END function __construct()
72
+
73
+ /**
74
+ * Activate the plugin
75
+ * Credits: http://solislab.com/blog/plugin-activation-checklist/#update-routines
76
+ */
77
+ public static function activate() {
78
+
79
+ global $WPAU_YOUTUBE_CHANNEL;
80
+ $WPAU_YOUTUBE_CHANNEL->init_options();
81
+ $WPAU_YOUTUBE_CHANNEL->maybe_update();
82
+
83
+ } // end function activate
84
+
85
+ /**
86
+ * Return initial options
87
+ * @return array Global defaults for current plugin version
88
+ */
89
+ public function init_options() {
90
+
91
+ $init = array(
92
+ 'vanity' => '', // $this->vanity_id,
93
+ 'channel' => '', // $this->channel_id,
94
+ 'username' => '', // $this->username_id,
95
+ 'playlist' => '', // $this->playlist_id,
96
+ 'resource' => 0, // ex use_res
97
+ 'cache' => 300, // 5 minutes // ex cache_time
98
+ 'fetch' => 25, // ex maxrnd
99
+ 'num' => 1, // ex vidqty
100
+ 'privacy' => 0,
101
+
102
+ 'ratio' => 3, // 3 - 16:9, 1 - 4:3 (deprecated: 2 - 16:10)
103
+ 'width' => 306,
104
+ 'responsive' => true,
105
+ 'display' => 'thumbnail', // thumbnail, iframe, iframe2 (deprecated: chromeless, object)
106
+ 'themelight' => 0,
107
+ 'controls' => 0,
108
+ 'autoplay' => 0,
109
+ 'autoplay_mute' => 0,
110
+ 'norel' => 0,
111
+
112
+ 'showtitle' => 0,
113
+ 'showdesc' => 0,
114
+ 'desclen' => 0,
115
+ 'descappend' => '&hellip;',
116
+ 'modestbranding' => 0,
117
+ 'hideanno' => 0,
118
+ 'hideinfo' => 0,
119
+
120
+ 'goto_txt' => 'Visit our channel',
121
+ 'showgoto' => 0,
122
+ 'popup_goto' => 0, // 0 same window, 1 new window JS, 2 new window target
123
+ 'link_to' => 0 // 0 legacy username, 1 channel, 2 vanity
124
+ );
125
+
126
+ add_option('youtube_channel_version', self::VER, '', 'no');
127
+ add_option('youtube_channel_db_ver', self::DB_VER, '', 'no');
128
+ add_option($this->plugin_option, $init, '', 'no');
129
+
130
+ } // END public function init_options()
131
+
132
+ /**
133
+ * Check do we need to migrate options
134
+ */
135
+ public function maybe_update() {
136
+
137
+ // bail if this plugin data doesn't need updating
138
+ if ( get_option( 'youtube_channel_db_ver' ) >= self::DB_VER ) {
139
+ return;
140
+ }
141
+
142
+ require_once( dirname(__FILE__) . '/update.php' );
143
+ au_youtube_channel_update();
144
+
145
+ } // END public function maybe_update()
146
+
147
+ /**
148
+ * Initialize Settings link for Plugins page and create Settings page
149
+ */
150
+ function admin_init() {
151
+
152
+ add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'add_settings_link') );
153
+
154
+ require_once( 'inc/settings.php' );
155
+
156
+ global $WPAU_YOUTUBE_CHANNEL_SETTINGS;
157
+ if ( empty($WPAU_YOUTUBE_CHANNEL_SETTINGS) )
158
+ $WPAU_YOUTUBE_CHANNEL_SETTINGS = new WPAU_YOUTUBE_CHANNEL_SETTINGS();
159
+
160
+ } // END function admin_init_settings()
161
+
162
+ /**
163
+ * Append Settings link for Plugins page
164
+ * @param array $links array of links on plugins page
165
+ */
166
+ function add_settings_link($links) {
167
+
168
+ $settings_title = __('Settings');
169
+ $settings_link = "<a href=\"options-general.php?page={$this->plugin_slug}\">{$settings_title}</a>";
170
+ array_unshift( $links, $settings_link );
171
+
172
+ // Free some memory
173
+ unset($settings_title, $settings_link);
174
+
175
+ // Return updated array of links
176
+ return $links;
177
+
178
+ } // END function add_settings_link()
179
+
180
+ /**
181
+ * Enqueue admin scripts and styles for widget customization
182
+ */
183
+ function widget_scripts() {
184
+
185
+ global $pagenow;
186
+
187
+ // Enqueue only on widget page
188
+ if( $pagenow !== 'widgets.php' && $pagenow !== 'customize.php' ) return;
189
+
190
+ wp_enqueue_script(
191
+ $this->plugin_slug . '-admin',
192
+ plugins_url( 'assets/js/admin.min.js', __FILE__ ),
193
+ array('jquery'),
194
+ self::VER
195
+ );
196
+ wp_enqueue_style(
197
+ $this->plugin_slug . '-admin',
198
+ plugins_url( 'assets/css/admin.min.css', __FILE__ ),
199
+ array(),
200
+ self::VER
201
+ );
202
+
203
+ } // END function widget_scripts()
204
+
205
+ /**
206
+ * Print dashboard notice
207
+ * @return string Formatted notice with usefull explanation
208
+ */
209
+ function admin_notices() {
210
+
211
+ // Get array of dismissed notices
212
+ $dismissed_notices = get_option('youtube_channel_dismissed_notices');
213
+
214
+ // Dismiss notices if requested and then update option in DB
215
+ if ( ! empty($_GET['ytc_dismiss_notice_old_php']) ) {
216
+ $dismissed_notices['old_php'] = 1;
217
+ update_option('youtube_channel_dismissed_notices', $dismissed_notices);
218
+ }
219
+ if ( ! empty($_GET['ytc_dismiss_notice_apikey_wpconfig']) ) {
220
+ $dismissed_notices['apikey_wpconfig'] = 1;
221
+ update_option('youtube_channel_dismissed_notices', $dismissed_notices);
222
+ }
223
+ if ( ! empty($_GET['ytc_dismiss_notice_vanity_option']) ) {
224
+ $dismissed_notices['vanity_option'] = 1;
225
+ update_option('youtube_channel_dismissed_notices', $dismissed_notices);
226
+ }
227
+
228
+ // Prepare vars for notices
229
+ $settings_page = 'options-general.php?page=youtube-channel';
230
+ $notice = array(
231
+ 'error' => '',
232
+ 'warning' => '',
233
+ 'info' => ''
234
+ );
235
+
236
+ // Inform if PHP version is lower than 5.3
237
+ if ( version_compare(PHP_VERSION, "5.3", "<") && ( empty($dismissed_notices) || ( ! empty($dismissed_notices) && empty($dismissed_notices['old_php']) ) ) ) {
238
+ $notice['info'] .= sprintf(
239
+ __('<p>Your website running on web server with PHP version %s. Please note that <strong>%s</strong> requires PHP at least 5.3 or newer to work properly. <a href="%s" class="dismiss">Dismiss</a></p>', 'youtube-channel'),
240
+ PHP_VERSION,
241
+ $this->plugin_name,
242
+ '?ytc_dismiss_notice_old_php=1'
243
+ );
244
+ }
245
+
246
+ // Inform if YOUTUBE_DATA_API_KEY is still in wp-config.php
247
+ if ( defined('YOUTUBE_DATA_API_KEY') && empty($dismissed_notices['apikey_wpconfig']) ) {
248
+ $notice['info'] .= sprintf(
249
+ __('<p>Since <strong>%s</strong> v3.0.6 we store <strong>YouTube Data API Key</strong> in plugin settings. So, you can safely remove %s define line from your <strong>wp-config.php</strong> file. <a href="%s" class="dismiss">Dismiss</a></p>', 'youtube-channel'),
250
+ $this->plugin_name,
251
+ 'YOUTUBE_DATA_API_KEY',
252
+ '?ytc_dismiss_notice_apikey_wpconfig=1'
253
+ );
254
+ }
255
+
256
+ // No YouTube DATA Api Key?
257
+ if ( empty($this->defaults['apikey']) ) {
258
+ $notice['error'] .= sprintf(
259
+ __('<p>Please note, to make <strong>%s</strong> plugin v3+ work, generate <strong>YouTube Data API Key</strong> as explained <a href="%s" target="_blank">here</a> and add it at <a href="%s">General plugin settings tab</a>.<br><br>If you have any issue with new version of plugin, please ask for help on official <a href="%s" target="_blank">support forum</a>.<br>This notice will disappear when you add missing key as mentioned above!</p>', 'youtube-channel'),
260
+ $this->plugin_name,
261
+ 'http://urosevic.net/wordpress/plugins/youtube-channel/#youtube_data_api_key',
262
+ 'options-general.php?page=youtube-channel&tab=general',
263
+ 'https://wordpress.org/support/plugin/youtube-channel'
264
+ );
265
+ }
266
+
267
+ if ( empty($dismissed_notices) || ( ! empty($dismissed_notices) && empty($dismissed_notices['vanity_option']) ) ) {
268
+ $notice['warning'] .= sprintf(
269
+ __('<p><strong>%s</strong> since version 2.4 supports linking to channel through <em>Vanity/Custom</em> URL. Please review <a href="%s">global</a> and <a href="%s">widgets</a> settings. <a href="%s" class="dismiss">Dismiss</a>', 'youtube-channel'),
270
+ $this->plugin_name,
271
+ $settings_page,
272
+ 'widgets.php',
273
+ '?ytc_dismiss_notice_vanity_option=1'
274
+ );
275
+ }
276
+
277
+ foreach ( $notice as $type => $message ) {
278
+ if ( ! empty($message) ) {
279
+ echo "<div class=\"notice notice-{$type}\">{$message}</div>";
280
+ }
281
+ }
282
+
283
+ } // END function admin_notices()
284
+
285
+ /**
286
+ * Get default options from DB
287
+ * @return array Latest global defaults
288
+ */
289
+ public function defaults() {
290
+
291
+ $defaults = get_option($this->plugin_option);
292
+ if ( empty($defaults) ) {
293
+ $this->init_options();
294
+ }
295
+
296
+ return $defaults;
297
+
298
+ }
299
+
300
+ function enqueue_scripts() {
301
+ wp_enqueue_style( 'youtube-channel', plugins_url('assets/css/youtube-channel.min.css', __FILE__), array(), self::VER );
302
+
303
+ // enqueue magnific-popup
304
+ wp_enqueue_script( 'magnific-popup-au', plugins_url('assets/lib/magnific-popup/jquery.magnific-popup.min.js', __FILE__), array('jquery'), self::VER, true );
305
+ wp_enqueue_style( 'magnific-popup-au', plugins_url('assets/lib/magnific-popup/magnific-popup.min.css', __FILE__), array(), self::VER );
306
+ wp_enqueue_script( 'youtube-channel', plugins_url('assets/js/youtube-channel.min.js', __FILE__), array(), self::VER, true );
307
+ } // end function enqueue_scripts
308
+
309
+ function footer_scripts() {
310
+ // Print JS only if we have set YTC array
311
+ if ( ! empty($_SESSION['ytc_html5_js']) )
312
+ {
313
+ ?>
314
+ <!-- YouTube Channel v<?php echo self::VER; ?> -->
315
+ <script type="text/javascript">
316
+ var tag = document.createElement('script');
317
+ tag.src = "//www.youtube.com/iframe_api";
318
+ var firstScriptTag = document.getElementsByTagName('script')[0];
319
+ firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
320
+ function onYouTubeIframeAPIReady() {
321
+ <?php echo $_SESSION['ytc_html5_js']; ?>
322
+ }
323
+ function ytc_mute(event){
324
+ event.target.mute();
325
+ }
326
+ </script>
327
+ <?php
328
+ }
329
+
330
+ } // eof footer_scripts
331
+
332
+ public function shortcode($atts) {
333
+
334
+ // get general default settings
335
+ $instance = $this->defaults();
336
+
337
+ // extract shortcode parameters
338
+ extract(
339
+ shortcode_atts(
340
+ array(
341
+ 'vanity' => $instance['vanity'],
342
+ 'channel' => $instance['channel'],
343
+ 'username' => $instance['username'],
344
+ 'playlist' => $instance['playlist'],
345
+ 'res' => '', // (deprecated, but leave for back compatibility) ex res
346
+ 'use_res' => '', // (deprecated, but leave for back compatibility) ex use_res
347
+ 'resource' => $instance['resource'], // ex use_res
348
+ 'only_pl' => 0, // disabled by default (was: $instance['only_pl'],)
349
+ 'cache' => $instance['cache'], // ex cache_time
350
+ 'privacy' => $instance['privacy'], // ex showvidesc
351
+ 'fetch' => $instance['fetch'], // ex maxrnd
352
+ 'num' => $instance['num'], // ex vidqty
353
+
354
+ 'random' => 0, // ex getrnd
355
+
356
+ 'ratio' => $instance['ratio'],
357
+ 'width' => $instance['width'],
358
+ 'responsive' => ( ! empty($instance['responsive']) ) ? $instance['responsive'] : '0',
359
+
360
+ 'show' => $instance['display'], // (deprecated, but keep for back compatibility) ex to_show
361
+ 'display' => $instance['display'],
362
+ 'no_thumb_title' => 0,
363
+ 'themelight' => $instance['themelight'],
364
+ 'controls' => $instance['controls'],
365
+ 'autoplay' => $instance['autoplay'],
366
+ 'mute' => $instance['autoplay_mute'],
367
+ 'norel' => $instance['norel'],
368
+
369
+ 'showtitle' => $instance['showtitle'],
370
+ 'titlebelow' => 0, // move title below video
371
+ 'showdesc' => $instance['showdesc'], // ex showvidesc
372
+ 'nobrand' => ( ! empty($instance['modestbranding']) ) ? $instance['modestbranding'] : '0',
373
+ 'desclen' => $instance['desclen'], // ex videsclen
374
+ 'noinfo' => $instance['hideinfo'],
375
+ 'noanno' => $instance['hideanno'],
376
+
377
+ 'goto' => $instance['showgoto'],
378
+ 'goto_txt' => $instance['goto_txt'],
379
+ 'popup' => $instance['popup_goto'],
380
+ 'link_to' => $instance['link_to'],
381
+
382
+ 'class' => ( ! empty($instance['class']) ) ? $instance['class'] : ''
383
+ ),
384
+ $atts
385
+ )
386
+ );
387
+
388
+ // backward compatibility for show -> display shortcode parameter
389
+ if ( $show !== $display && $show !== $instance['display'] ) {
390
+ $display = $show;
391
+ }
392
+ // backward compatibility for use_res -> resource shortcode parameter
393
+ if ( ! empty($use_res) ) {
394
+ $resource = $use_res;
395
+ } else if ( ! empty($res) ) {
396
+ $resource = $res;
397
+ }
398
+
399
+ // prepare instance for output
400
+ $instance['vanity'] = $vanity;
401
+ $instance['channel'] = $channel;
402
+ $instance['username'] = $username;
403
+ $instance['playlist'] = $playlist;
404
+ $instance['resource'] = $resource; // resource: 0 channel, 1 favorites, 2 playlist
405
+ $instance['only_pl'] = $only_pl; // use embedded playlist - false by default
406
+ $instance['cache'] = $cache; // in seconds, def 5min - settings?
407
+ $instance['privacy'] = $privacy; // enhanced privacy
408
+
409
+ $instance['fetch'] = $fetch;
410
+ $instance['num'] = $num; // num: 1
411
+
412
+ $instance['random'] = $random; // use embedded playlist - false by default
413
+
414
+ // Video Settings
415
+ $instance['ratio'] = $ratio; // aspect ratio: 3 - 16:9, 2 - 16:10, 1 - 4:3
416
+ $instance['width'] = $width; // 306
417
+ $instance['responsive'] = $responsive; // enable responsivenes?
418
+ $instance['display'] = $display; // thumbnail, iframe, iframe2
419
+ $instance['no_thumb_title'] = $no_thumb_title; // hide tooltip for thumbnails
420
+
421
+ $instance['themelight'] = $themelight; // use light theme, dark by default
422
+ $instance['controls'] = $controls; // hide controls, false by default
423
+ $instance['autoplay'] = $autoplay; // autoplay disabled by default
424
+ $instance['autoplay_mute'] = $mute; // mute sound on autoplay - disabled by default
425
+ $instance['norel'] = $norel; // hide related videos
426
+
427
+ // Content Layout
428
+ $instance['showtitle'] = $showtitle; // show video title, disabled by default
429
+ $instance['titlebelow'] = $titlebelow; // show video title, disabled by default
430
+ $instance['showdesc'] = $showdesc; // show video description, disabled by default
431
+ $instance['modestbranding'] = $nobrand; // hide YT logo
432
+ $instance['desclen'] = $desclen; // cut video description, number of characters
433
+ $instance['hideinfo'] = $noinfo; // hide info by default
434
+ $instance['hideanno'] = $noanno; // hide annotations, false by default
435
+
436
+ // Link to Channel
437
+ $instance['showgoto'] = $goto; // show goto link, disabled by default
438
+ $instance['goto_txt'] = $goto_txt; // text for goto link - use settings
439
+ $instance['popup_goto'] = $popup; // open channel in: 0 same window, 1 javascript new, 2 target new
440
+ $instance['link_to'] = $link_to; // open channel in: 0 same window, 1 javascript new, 2 target new
441
+
442
+ // Customization
443
+ $instance['class'] = $class; // custom additional class for container
444
+
445
+ return implode(array_values($this->output($instance)));
446
+ } // END public function shortcode()
447
+
448
+ // Print out YTC block
449
+ public function output($instance) {
450
+
451
+ // print info about API key to admins
452
+ // and "Coming soon..." for visitors
453
+ if ( empty($this->defaults['apikey']) ) {
454
+ if ( current_user_can('manage_options') ) {
455
+ $output[] = sprintf(
456
+ __('<strong>%s</strong> version 3+ requires <strong>YouTube DATA API Key</strong> to work. <a href="%s" target="_blank">Learn more here</a>.', 'youtube-channel'),
457
+ $this->plugin_name,
458
+ 'http://urosevic.net/wordpress/plugins/youtube-channel/#youtube_data_api_key'
459
+ );
460
+
461
+ } else {
462
+ $output[] = "Coming soon...";
463
+ $output[] = "<!-- YTC ERROR:\n";
464
+ $output[] = "tip: No YouTube Data API Key provided!\n";
465
+ $output[] = "-->\n";
466
+ }
467
+ return $output;
468
+ }
469
+
470
+ // 1) Get resource from widget/shortcode
471
+ // 2) If not set, get global default
472
+ // 3) if no global, get plugin's default
473
+ $resource = intval($instance['resource']);
474
+ if ( empty($resource) && $resource !== 0 ) {
475
+ $resource = intval($this->defaults['resource']);
476
+ if ( empty($resource) ) {
477
+ $resource = 0;
478
+ }
479
+ }
480
+
481
+ // Get Channel or Playlist ID based on requested resource
482
+ switch ($resource) {
483
+
484
+ // Playlist
485
+ case '2':
486
+ // 1) Get Playlist from shortcode/widget
487
+ // 2) If not set, use global default
488
+ // 3) If no global, throw error
489
+ if ( ! empty($instance['playlist']) ) {
490
+ $playlist = trim($instance['playlist']);
491
+ } else {
492
+ $playlist = trim($this->defaults['playlist']);
493
+ }
494
+ // Now check has Playlist ID set or throw error
495
+ if ( $playlist == "" ) {
496
+ $output[] = "Comming soon...";
497
+ $output[] = "<!-- YTC ERROR:\n";
498
+ $output[] = "tip: Playlist selected as resource but no Playlist ID provided!\n";
499
+ $output[] = "-->\n";
500
+ return $output;
501
+ }
502
+ break;
503
+
504
+ // Channel, Favourites, Liked
505
+ default:
506
+ /* Channel */
507
+ // 1) Get channel from shortcode/widget
508
+ // 2) If not set, use global default
509
+ // 3) If no global, throw error
510
+ if ( ! empty($instance['channel']) ) {
511
+ $channel = trim($instance['channel']);
512
+ } else {
513
+ $channel = trim($this->defaults['channel']);
514
+ }
515
+ // Now check is Channel ID set or throw error
516
+ if ( $channel == '' ) {
517
+ $output[] = "Comming soon...";
518
+ $output[] = "<!-- YTC ERROR:\n";
519
+ if ( $resource == 1 ) { $resource_name = 'Favourited videos'; }
520
+ elseif ( $resource == 3 ) { $resource_name = 'Liked videos'; }
521
+ else { $resource_name = 'Channel (User uploads)'; }
522
+ $output[] = sprintf('tip: %s selected as resource but no Channel ID provided!', $resource_name) . "\n";
523
+ $output[] = "-->\n";
524
+ return $output;
525
+ }
526
+
527
+ } // END switch ($resource)
528
+
529
+ /* OK, we have required resource (Playlist or Channel ID), so we can proceed to real job */
530
+
531
+ // Set custom class and responsive if needed
532
+ $class = $instance['class'] ? $instance['class'] : 'default';
533
+ if ( ! empty($instance['responsive']) ) {
534
+ $class .= ' responsive';
535
+ }
536
+
537
+ switch ($resource) {
538
+ case 1: // Favourites
539
+ $resource_name = 'favourites';
540
+ $resource_id = preg_replace('/^UC/', 'FL', $channel);
541
+ break;
542
+ case 2: // Playlist
543
+ $resource_name = 'playlist';
544
+ $resource_id = $playlist;
545
+ break;
546
+ case 3: // Liked
547
+ $resource_name = 'liked';
548
+ $resource_id = preg_replace('/^UC/', 'LL', $channel);
549
+ break;
550
+ default: // Channel
551
+ $resource_name = 'channel';
552
+ $resource_id = preg_replace('/^UC/', 'UU', $channel); //$channel;
553
+ }
554
+
555
+ // Start output array
556
+ $output = array();
557
+
558
+ $output[] = "<div class=\"youtube_channel {$class}\">";
559
+
560
+ if ( $instance['only_pl'] ) { // print standard playlist
561
+
562
+ $output = array_merge( $output, self::embed_playlist($resource_id, $instance) );
563
+
564
+ } else { // videos from channel, favourites, liked or playlist
565
+
566
+ // Get max items for random video
567
+ $fetch = $instance['fetch'];
568
+ if ( $fetch < 1 ) { $fetch = 10; } // default 10
569
+ elseif ( $fetch > 50 ) { $fetch = 50; } // max 50
570
+
571
+ $resource_key = "{$resource_id}_{$fetch}";
572
+
573
+ // Do we need cache? Let we define cache fallback key
574
+ $cache_key_fallback = 'ytc_' . md5($resource_key) . '_fallback';
575
+
576
+ // Do cache magic
577
+ if ( $instance['cache'] > 0 ) {
578
+
579
+ // generate feed cache key for caching time
580
+ $cache_key = 'ytc_'.md5($resource_key).'_'.$instance['cache'];
581
+
582
+ if ( ! empty($_GET['ytc_force_recache']) ) {
583
+ delete_transient($cache_key);
584
+ }
585
+
586
+ // get/set transient cache
587
+ if ( false === ($json = get_transient($cache_key)) || empty($json) ) {
588
+
589
+ // no cached JSON, get new
590
+ $json = $this->fetch_youtube_feed($resource_id, $fetch);
591
+
592
+ // set decoded JSON to transient cache_key
593
+ set_transient($cache_key, base64_encode($json), $instance['cache']);
594
+
595
+ } else {
596
+
597
+ // we already have cached feed JSON, get it encoded
598
+ $json = base64_decode($json);
599
+
600
+ }
601
+
602
+ } else {
603
+
604
+ // just get fresh feed if cache disabled
605
+ $json = $this->fetch_youtube_feed($resource_id, $fetch);
606
+
607
+ }
608
+
609
+ // free some memory
610
+ unset( $response );
611
+
612
+ // decode JSON data
613
+ $json_output = json_decode($json);
614
+
615
+ // YTC 3.0.7: Do we need this, still?
616
+ // if current feed is messed up, try to get it from fallback cache
617
+ if ( is_wp_error($json_output) && ! is_object($json_output) && empty($json_output->items) ) {
618
+ // do we have fallback cache?!
619
+ if ( true === ( $json_fallback = get_transient( $cache_key_fallback ) ) && ! empty($json_fallback) ) {
620
+ $json_output = json_decode( base64_decode($json_fallback) );
621
+ // and free memory
622
+ unset( $json_fallback );
623
+ }
624
+ }
625
+
626
+ // Predefine `max_items` to prevent undefined notices
627
+ $max_items = 0;
628
+ if ( ! is_wp_error($json_output) && is_object($json_output) && !empty($json_output->items) ) {
629
+ // Sort by date uploaded
630
+ $json_entry = $json_output->items;
631
+
632
+ $num = $instance['num'];
633
+ if ( $num > $fetch ) { $fetch = $num; }
634
+ $max_items = ( $fetch > sizeof($json_entry) ) ? sizeof($json_entry) : $fetch;
635
+
636
+ if ( ! empty($instance['random']) ) {
637
+ $items = array_slice($json_entry, 0, $max_items);
638
+ } else {
639
+ if ( ! $num ) $num = 1;
640
+ $items = array_slice($json_entry, 0, $num);
641
+ }
642
+ }
643
+
644
+ if ($max_items == 0) {
645
+
646
+ // is this WP error?
647
+ if ( is_wp_error($json_output) ) {
648
+ $error_string = $json_output->get_error_message();
649
+ $output[] = $error_string;
650
+ unset($error_string);
651
+ } else {
652
+ $output[] = __("Oops, something went wrong.", 'youtube-channel');
653
+ // append YouTube DATA API error reason as comment
654
+ if ( ! empty($json_output) && is_object($json_output) && !empty($json_output->error->errors) ) {
655
+ $output[] = "<!-- YTC ERROR:\n";
656
+ $output[] = 'domain: ' . $json_output->error->errors[0]->domain . "\n";
657
+ $output[] = 'reason: ' . $json_output->error->errors[0]->reason . "\n";
658
+ $output[] = 'message: ' . $json_output->error->errors[0]->message . "\n";
659
+
660
+ if ( $json_output->error->errors[0]->reason == 'playlistNotFound' ) {
661
+ if ( $resource_name == 'playlist' ) {
662
+ $output[] = "tip: Please check did you set existing Playlist ID. We should display videos from {$resource_name} videos, but YouTube does not recognize {$resource_id} as existing and public playlist.\n";
663
+ } else {
664
+ $output[] = "tip: Please check did you set proper Channel ID. We should display videos from {$resource_name} videos, but YouTube does not recognize your channel ID {$channel} as existing and public resource.\n";
665
+ }
666
+ }
667
+ elseif ( $json_output->error->errors[0]->reason == 'keyInvalid' ) {
668
+ $output[] = "tip: Double check YouTube Data API Key on General plugin tab and make sure it`s correct. Check https://wordpress.org/plugins/youtube-channel/installation/\n";
669
+ }
670
+ elseif ( $json_output->error->errors[0]->reason == 'ipRefererBlocked' ) {
671
+ $output[] = "tip: Check YouTube Data API Key restrictions, empty cache if enabled and append in browser address bar parameter ?ytc_force_recache=1\n";
672
+ }
673
+ elseif ( $json_output->error->errors[0]->reason == 'invalidChannelId' ) {
674
+ $output[] = "tip: You have set wrong Channel ID. Fix that in General plugin settings, Widget and/or shortcode. Check https://wordpress.org/plugins/youtube-channel/faq/\n";
675
+ }
676
+ $output[] = "-->\n";
677
+ }
678
+ }
679
+
680
+ } else { // ELSE if ($max_items == 0)
681
+
682
+ // looks that feed is OK, let we update fallback that never expire
683
+ set_transient($cache_key_fallback, base64_encode($json), 0);
684
+
685
+ // and now free some memory
686
+ unset ( $json, $json_output, $json_entry );
687
+
688
+ // set array for unique random item
689
+ if ( ! empty($instance['random']) ) {
690
+ $random_used = array();
691
+ }
692
+
693
+ /* AU:20141230 reduce number of videos if requested > available */
694
+ if ( $num > sizeof($items) ) {
695
+ $num = sizeof($items);
696
+ }
697
+
698
+ for ($y = 1; $y <= $num; ++$y) {
699
+ if ( ! empty($instance['random']) ) {
700
+
701
+ $random_item = mt_rand( 0, (count($items)-1) );
702
+ while ( $y > 1 && in_array($random_item, $random_used) ) {
703
+ $random_item = mt_rand(0, (count($items)-1));
704
+ }
705
+ $random_used[] = $random_item;
706
+ $item = $items[ $random_item ];
707
+ } else {
708
+ $item = $items[ $y - 1 ];
709
+ }
710
+
711
+ // print single video block
712
+ $output = array_merge( $output, $this->ytc_print_video($item, $instance, $y) );
713
+ }
714
+ // Free some memory
715
+ unset($random_used, $random_item, $json);
716
+
717
+ } // END if ($max_items == 0)
718
+
719
+ } // single playlist or ytc way
720
+
721
+ if ( ! empty($instance['showgoto']) ) {
722
+ $output = array_merge( $output, $this->ytc_channel_link($instance) ); // insert link to channel on bootom of widget
723
+ }
724
+
725
+ $output[] = '</div><!-- .youtube_channel -->';
726
+
727
+ // fix overflow on crappy themes
728
+ $output[] = '<div class="clearfix"></div>';
729
+
730
+ return $output;
731
+
732
+ } // END public function output($instance)
733
+
734
+ // --- HELPER FUNCTIONS ---
735
+
736
+ /**
737
+ * Download YouTube video feed through API 3.0
738
+ * @param string $id ID of resource
739
+ * @param integer $items Number of items to fetch (min 2, max 50)
740
+ * @return array JSON with videos
741
+ */
742
+ function fetch_youtube_feed($resource_id, $items) {
743
+
744
+ $feed_url = 'https://www.googleapis.com/youtube/v3/playlistItems?';
745
+ $feed_url .= 'part=snippet';
746
+ $feed_url .= "&playlistId={$resource_id}";
747
+ $feed_url .= '&fields=items(snippet(title%2Cdescription%2CpublishedAt%2CresourceId(videoId)))';
748
+ $feed_url .= "&maxResults={$items}";
749
+ $feed_url .= "&key={$this->defaults['apikey']}";
750
+
751
+ $wprga = array(
752
+ 'timeout' => 5 // five seconds only
753
+ );
754
+ $response = wp_remote_get($feed_url, $wprga);
755
+ $json = wp_remote_retrieve_body( $response );
756
+
757
+ // free some memory
758
+ unset($response);
759
+
760
+ return $json;
761
+
762
+ } // END function fetch_youtube_feed($resource_id, $items)
763
+
764
+ // function to calculate height by width and ratio
765
+ function height_ratio($width=306, $ratio) {
766
+
767
+ switch ($ratio)
768
+ {
769
+ case 1:
770
+ $height = round(($width / 4 ) * 3);
771
+ break;
772
+ case 2:
773
+ case 3:
774
+ default:
775
+ $height = round(($width / 16 ) * 9);
776
+ }
777
+ return $height;
778
+ } // END function height_ratio($width=306, $ratio)
779
+
780
+ /**
781
+ * Generate link to YouTUbe channel/user
782
+ * @param array $instance widget or shortcode settings
783
+ * @return array components prepared for output
784
+ */
785
+ function ytc_channel_link($instance) {
786
+
787
+ // initialize array
788
+ $output = array();
789
+
790
+ // do we need to show goto link?
791
+ if ( $instance['showgoto'] ) {
792
+
793
+ $link_to = $instance['link_to'];
794
+
795
+ $channel = trim($instance['channel']);
796
+ $username = trim($instance['username']);
797
+
798
+ // sanity vanity content (strip all in front of last slash to cleanup vanity ID only)
799
+ $vanity = trim($instance['vanity']);
800
+ if ( ! empty( $vanity ) && strpos($vanity, 'youtube.com') !== false )
801
+ $vanity = preg_replace('/^.*\//', '', $vanity);
802
+
803
+ $goto_txt = trim($instance['goto_txt']);
804
+ if ( $goto_txt == "" ) {
805
+ $goto_txt = __('Visit our YouTube channel', 'youtube-channel');
806
+ }
807
+
808
+ if ( ! empty($username) ) {
809
+ $goto_txt = str_replace('%username%', $username, $goto_txt);
810
+ }
811
+ if ( ! empty($channel) ) {
812
+ $goto_txt = str_replace('%channel%', $channel, $goto_txt);
813
+ }
814
+ if ( ! empty( $vanity ) ) {
815
+ $goto_txt = str_replace('%vanity%', $vanity, $goto_txt);
816
+ }
817
+
818
+ $goto_url = "https://www.youtube.com/";
819
+ if ( $link_to == '2' ) { // vanity
820
+ if ( empty($vanity) ) {
821
+ return array("<!-- YTC ERROR: Selected Vanity custom URL to be linked but no Vanity Name provided! -->");
822
+ }
823
+ $goto_url .= "c/$vanity";
824
+ } else if ( $link_to == '0') { // legacy username
825
+ if ( empty($username) ) {
826
+ return array("<!-- YTC ERROR: Selected Legacy username to be linked but no Legacy username provided! -->");
827
+ }
828
+ $goto_url .= "user/$username";
829
+ } else { // channel (default)
830
+ if ( empty($channel) ) {
831
+ return array("<!-- YTC ERROR: Selected Channel page to be linked but no Channel ID provided! -->");
832
+ }
833
+ $goto_url .= "channel/$channel";
834
+ }
835
+
836
+ $newtab = __("in new window/tab", 'youtube-channel');
837
+
838
+ $output[] = '<div class="clearfix"></div>';
839
+ $output[] = '<div class="ytc_link">';
840
+ $output[] = '<p>';
841
+ switch ( $instance['popup_goto'] ) {
842
+ case 1:
843
+ $output[] = "<a href=\"javascript: window.open('{$goto_url}'); void 0;\" title=\"{$goto_txt} {$newtab}\">{$goto_txt}</a>";
844
+ break;
845
+ case 2:
846
+ $output[] = "<a href=\"{$goto_url}\" target=\"_blank\" title=\"{$goto_txt} {$newtab}\">{$goto_txt}</a>";
847
+ break;
848
+ default:
849
+ $output[] = "<a href=\"{$goto_url}\" title=\"{$goto_txt}\">$goto_txt</a>";
850
+ } // switch popup_goto
851
+ $output[] = '</p>';
852
+ $output[] = '</div>';
853
+
854
+ } // showgoto
855
+
856
+ return $output;
857
+ } // end function ytc_channel_link
858
+
859
+ /* function to print video block */
860
+ function ytc_print_video($item, $instance, $y) {
861
+
862
+ // get hideinfo, autoplay and controls settings
863
+ // where this is used?
864
+ $hideinfo = $instance['hideinfo'];
865
+ $autoplay = $instance['autoplay'];
866
+ $autoplay_mute = $instance['autoplay_mute'];
867
+ $controls = $instance['controls'];
868
+ $norel = $instance['norel'];
869
+ $class = $instance['class'];
870
+ $modestbranding = $instance['modestbranding'];
871
+
872
+ // set width and height
873
+ $width = ( empty($instance['width']) ) ? 306 : $instance['width'];
874
+ $height = $this->height_ratio($width, $instance['ratio']);
875
+
876
+ // calculate image height based on width for 4:3 thumbnail
877
+ $imgfixedheight = $width / 4 * 3;
878
+
879
+ // which type to show
880
+ $display = (empty($instance['display'])) ? 'object' : $instance['display'];
881
+ $hideanno = $instance['hideanno'];
882
+ $themelight = $instance['themelight'];
883
+ /* end of video settings */
884
+
885
+ // Prepare Video ID from Resource
886
+ $yt_id = $item->snippet->resourceId->videoId;
887
+ $yt_url = "v/$yt_id";
888
+ $yt_thumb = "//img.youtube.com/vi/$yt_id/0.jpg"; // zero for HD thumb
889
+ $yt_video = "//www.youtube.com/watch?v=" . $yt_id;
890
+
891
+ $yt_title = $item->snippet->title;
892
+ $yt_date = $item->snippet->publishedAt;
893
+
894
+ switch ($y) {
895
+ case 1:
896
+ $vnumclass = 'first';
897
+ break;
898
+ case $instance['num']:
899
+ $autoplay = false;
900
+ $vnumclass = 'last';
901
+ break;
902
+ default:
903
+ $vnumclass = 'mid';
904
+ $autoplay = false;
905
+ break;
906
+ }
907
+
908
+ // set proper class for responsive thumbs per selected aspect ratio
909
+ switch ($instance['ratio'])
910
+ {
911
+ case 1: $arclass = 'ar4_3'; break;
912
+ default: $arclass = 'ar16_9';
913
+ }
914
+ $output[] = "<div class=\"ytc_video_container ytc_video_{$y} ytc_video_{$vnumclass} ${arclass}\" style=\"width:{$width}px\">";
915
+
916
+ // show video title above video?
917
+ if ( ! empty($instance['showtitle']) && empty($instance['titlebelow']) ) {
918
+ $output[] = "<h3 class=\"ytc_title\">{$yt_title}</h3>";
919
+ }
920
+
921
+ // Define object ID
922
+ $ytc_vid = "ytc_{$yt_id}";
923
+
924
+ // Enhanced privacy?
925
+ $youtube_domain = $this->youtube_domain($instance);
926
+
927
+ // Print out video
928
+ if ( $display == "iframe" ) {
929
+ if ( empty($usepl) ) {
930
+ $yt_url = $yt_id;
931
+ }
932
+
933
+ // Start wrapper for responsive item
934
+ if ( $instance['responsive'] ) {
935
+ $output[] = '<div class="fluid-width-video-wrapper">';
936
+ }
937
+
938
+ $output[] = "<iframe title=\"YouTube Video Player\" width=\"{$width}\" height=\"{$height}\" src=\"//{$youtube_domain}/embed/{$yt_url}?wmode=opaque";
939
+ if ( $controls ) $output[] = "&amp;controls=0";
940
+ if ( $hideinfo ) $output[] = "&amp;showinfo=0";
941
+ if ( $autoplay ) $output[] = "&amp;autoplay=1";
942
+ if ( $hideanno ) $output[] = "&amp;iv_load_policy=3";
943
+ if ( $themelight ) $output[] = "&amp;theme=light";
944
+ if ( $modestbranding ) $output[] = "&amp;modestbranding=1";
945
+ // disable related videos
946
+ if ( $norel ) $output[] = "&amp;rel=0";
947
+
948
+ $output[] = "\" style=\"border:0;\" allowfullscreen id=\"{$ytc_vid}\"></iframe>";
949
+
950
+ // Close wrapper for responsive item
951
+ if ( $instance['responsive'] ) {
952
+ $output[] = '</div>';
953
+ }
954
+
955
+ } else if ( $display == "iframe2" ) {
956
+
957
+ // youtube API async
958
+ if ( empty($usepl) ) $yt_url = $yt_id;
959
+
960
+ $js_rel = ( $norel ) ? "rel: 0," : '';
961
+ $js_controls = ( $controls ) ? "controls: 0," : '';
962
+ $js_showinfo = ( $hideinfo ) ? "showinfo: 0," : '';
963
+ $js_iv_load_policy = ( $hideanno ) ? "iv_load_policy: 3," : '';
964
+ $js_theme = ( $themelight ) ? "theme: 'light'," : '';
965
+ $js_autoplay = ( $autoplay ) ? "autoplay: 1," : '';
966
+ $js_modestbranding = ( $modestbranding ) ? "modestbranding: 1," : '';
967
+ $js_autoplay_mute = ( $autoplay && $autoplay_mute ) ? "events: {'onReady': ytc_mute}" : '';
968
+ $js_player_id = str_replace('-', '_', $yt_url);
969
+
970
+ // Start wrapper for responsive item
971
+ if ( $instance['responsive'] ) {
972
+ $output[] = '<div class="fluid-width-video-wrapper">';
973
+ }
974
+
975
+ $output[] = '<div id="ytc_player_'.$js_player_id.'"></div>';
976
+
977
+ // Close wrapper for responsive item
978
+ if ( $instance['responsive'] ) {
979
+ $output[] = '</div>';
980
+ }
981
+
982
+ $site_domain = $_SERVER['HTTP_HOST'];
983
+ $ytc_html5_js = <<<JS
984
+ var ytc_player_$js_player_id;
985
+ ytc_player_$js_player_id = new YT.Player('ytc_player_$js_player_id', {
986
+ height: '$height',
987
+ width: '$width',
988
+ videoId: '$yt_url',
989
+ enablejsapi: 1,
990
+ playerVars: {
991
+ $js_autoplay $js_showinfo $js_controls $js_theme $js_rel $js_modestbranding wmmode: 'opaque'
992
+ },
993
+ origin: '$site_domain',
994
+ $js_iv_load_policy $js_autoplay_mute
995
+ });
996
+ JS;
997
+
998
+ // prepare JS for footer
999
+ if ( empty($_SESSION['ytc_html5_js']) )
1000
+ $_SESSION['ytc_html5_js'] = $ytc_html5_js;
1001
+ else
1002
+ $_SESSION['ytc_html5_js'] .= $ytc_html5_js;
1003
+
1004
+ } else { // default is thumbnail
1005
+
1006
+ // set proper class for responsive thumbs per selected aspect ratio
1007
+ switch ($instance['ratio']) {
1008
+ case 1:
1009
+ $arclass = 'ar4_3';
1010
+ break;
1011
+ default:
1012
+ $arclass = 'ar16_9';
1013
+ }
1014
+
1015
+ // Do we need tooltip for thumbnail?
1016
+ if ( empty($instance['no_thumb_title']) ) {
1017
+ $title = sprintf( __('Watch video %1$s published on %2$s', 'youtube-channel' ), $yt_title, $yt_date );
1018
+ }
1019
+
1020
+ $p = '';
1021
+ if ( $norel ) $p .= '&amp;rel=0';
1022
+ if ( $modestbranding ) $p .= "&amp;modestbranding=1";
1023
+ if ( $controls ) $p .= "&amp;controls=0";
1024
+
1025
+ // Do we need thumbnail w/ or w/o tooltip
1026
+ if ( empty($instance['no_thumb_title']) ) {
1027
+ $output[] = "<a href=\"${yt_video}${p}\" title=\"{$yt_title}\" class=\"ytc_thumb ytc-lightbox {$arclass}\"><span style=\"background-image: url({$yt_thumb});\" title=\"{$title}\" id=\"{$ytc_vid}\"></span></a>";
1028
+ } else {
1029
+ $output[] = "<a href=\"${yt_video}${p}\" class=\"ytc_thumb ytc-lightbox {$arclass}\"><span style=\"background-image: url({$yt_thumb});\" id=\"{$ytc_vid}\"></span></a>";
1030
+ }
1031
+
1032
+ } // what to show conditions
1033
+
1034
+ // show video title below video?
1035
+ if ( ! empty($instance['showtitle']) && ! empty($instance['titlebelow']) ) {
1036
+ $output[] = "<h3 class=\"ytc_title\">{$yt_title}</h3>";
1037
+ }
1038
+
1039
+ // do we need to show video description?
1040
+ if ( $instance['showdesc'] ) {
1041
+
1042
+ $video_description = $item->snippet->description;
1043
+ $etcetera = '';
1044
+ if ( $instance['desclen'] > 0 ) {
1045
+ if ( strlen($video_description) > $instance['desclen'] ) {
1046
+ $video_description = substr($video_description, 0, $instance['desclen']);
1047
+ if ( $instance['descappend'] ) {
1048
+ $etcetera = $instance['descappend'];
1049
+ } else {
1050
+ $etcetera = '&hellip;';
1051
+ }
1052
+ }
1053
+ }
1054
+
1055
+ if ( ! empty($video_description) ) {
1056
+ $output[] = "<p class=\"ytc_description\">{$video_description}{$etcetera}</p>";
1057
+ }
1058
+
1059
+ }
1060
+
1061
+ $output[] = '</div><!-- .ytc_video_container -->';
1062
+
1063
+ return $output;
1064
+ } // end function ytc_print_video
1065
+
1066
+ /* function to print standard playlist embed code */
1067
+ function embed_playlist($resource_id, $instance) {
1068
+
1069
+ $width = ( empty($instance['width']) ) ? 306 : $instance['width'];
1070
+ $height = self::height_ratio($width, $instance['ratio']);
1071
+ $autoplay = (empty($instance['autoplay'])) ? '' : '&autoplay=1';
1072
+ $theme = (empty($instance['themelight'])) ? '' : '&theme=light';
1073
+ $modestbranding = (empty($instance['modestbranding'])) ? '' : '&modestbranding=1';
1074
+ $rel = (empty($instance['norel'])) ? '' : '&rel=0';
1075
+
1076
+ // enhanced privacy
1077
+ $youtube_domain = $this->youtube_domain($instance);
1078
+
1079
+ $output[] = "<div class=\"ytc_video_container ytc_video_1 ytc_video_single ytc_playlist_only\">";
1080
+ $output[] = "<iframe src=\"//{$youtube_domain}/embed/videoseries?list={$resource_id}{$autoplay}{$theme}{$modestbranding}{$rel}\"";
1081
+ $output[] = " width=\"{$width}\" height=\"{$height}\" frameborder=\"0\"></iframe></div>";
1082
+
1083
+ return $output;
1084
+
1085
+ } // END function embed_playlist($resource_id, $instance)
1086
+
1087
+ // Helper function cache_time()
1088
+ function cache_time($cache_time)
1089
+ {
1090
+ $times = array(
1091
+ 'minute' => array(
1092
+ 1 => __("1 minute", 'youtube-channel'),
1093
+ 5 => __("5 minutes", 'youtube-channel'),
1094
+ 15 => __("15 minutes", 'youtube-channel'),
1095
+ 30 => __("30 minutes", 'youtube-channel')
1096
+ ),
1097
+ 'hour' => array(
1098
+ 1 => __("1 hour", 'youtube-channel'),
1099
+ 2 => __("2 hours", 'youtube-channel'),
1100
+ 5 => __("5 hours", 'youtube-channel'),
1101
+ 10 => __("10 hours", 'youtube-channel'),
1102
+ 12 => __("12 hours", 'youtube-channel'),
1103
+ 18 => __("18 hours", 'youtube-channel')
1104
+ ),
1105
+ 'day' => array(
1106
+ 1 => __("1 day", 'youtube-channel'),
1107
+ 2 => __("2 days", 'youtube-channel'),
1108
+ 3 => __("3 days", 'youtube-channel'),
1109
+ 4 => __("4 days", 'youtube-channel'),
1110
+ 5 => __("5 days", 'youtube-channel'),
1111
+ 6 => __("6 days", 'youtube-channel')
1112
+ ),
1113
+ 'week' => array(
1114
+ 1 => __("1 week", 'youtube-channel'),
1115
+ 2 => __("2 weeks", 'youtube-channel'),
1116
+ 3 => __("3 weeks", 'youtube-channel'),
1117
+ 4 => __("1 month", 'youtube-channel')
1118
+ )
1119
+ );
1120
+
1121
+ $out = "";
1122
+ foreach ($times as $period => $timeset)
1123
+ {
1124
+ switch ($period)
1125
+ {
1126
+ case 'minute':
1127
+ $sc = MINUTE_IN_SECONDS;
1128
+ break;
1129
+ case 'hour':
1130
+ $sc = HOUR_IN_SECONDS;
1131
+ break;
1132
+ case 'day':
1133
+ $sc = DAY_IN_SECONDS;
1134
+ break;
1135
+ case 'week':
1136
+ $sc = WEEK_IN_SECONDS;
1137
+ break;
1138
+ }
1139
+
1140
+ foreach ($timeset as $n => $s)
1141
+ {
1142
+ $sec = $sc * $n;
1143
+ $out .='<option value="'.$sec.'" '. selected( $cache_time, $sec, 0 ).'>'.__($s, $this->plugin_slug).'</option>';
1144
+ unset($sec);
1145
+ }
1146
+ }
1147
+ return $out;
1148
+ } // end function cache_time
1149
+
1150
+ function youtube_domain($instance) {
1151
+ $youtube_domain = ( !empty($instance['privacy']) ) ? 'www.youtube-nocookie.com' : 'www.youtube.com';
1152
+ return $youtube_domain;
1153
+ } // end function youtube_domain
1154
+
1155
+ function clean_playlist_id($playlist) {
1156
+ if ( substr($playlist,0,4) == "http" ) {
1157
+ // if URL provided, extract playlist ID
1158
+ $playlist = preg_replace('/.*list=PL([A-Za-z0-9\-\_]*).*/','$1', $playlist);
1159
+ } else if ( substr($playlist,0,2) == 'PL' ) {
1160
+ $playlist = substr($playlist,2);
1161
+ }
1162
+ return $playlist;
1163
+ } // end function clean_playlist_id
1164
+
1165
+ function generate_debug_json()
1166
+ {
1167
+ global $wp_version;
1168
+
1169
+ // get widget ID from parameter
1170
+ $for = $_GET['ytc_debug_json_for'];
1171
+
1172
+ if ( $for == 'global' ) {
1173
+ // global settings
1174
+ $options = get_option('youtube_channel_defaults');
1175
+
1176
+ if ( ! is_array($options) )
1177
+ return;
1178
+
1179
+ // remove YouTube Data API Key from config JSON
1180
+ unset($options['apikey']);
1181
+
1182
+ } else {
1183
+ // for widget
1184
+ // prepare option name and widget ID
1185
+ $option_name = "widget_".substr($for,0,strrpos($for,"-"));
1186
+ $widget_id = substr($for,strrpos($for,"-")+1);
1187
+
1188
+ // get YTC widgets options
1189
+ $widget_options = get_option($option_name);
1190
+
1191
+ if ( ! is_array($widget_options[$widget_id]) )
1192
+ return;
1193
+
1194
+ $options = $widget_options[$widget_id];
1195
+ unset ($widget_options);
1196
+ }
1197
+
1198
+ // prepare debug data with settings of current widget
1199
+ $data = array_merge(
1200
+ array(
1201
+ 'date' => date("r"),
1202
+ 'server' => $_SERVER["SERVER_SOFTWARE"],
1203
+ 'php' => PHP_VERSION,
1204
+ 'wp' => $wp_version,
1205
+ 'ytc' => self::VER,
1206
+ 'url' => get_site_url(),
1207
+ 'for' => $for
1208
+ ),
1209
+ $options
1210
+ );
1211
+
1212
+ // return JSON file
1213
+ header('Content-disposition: attachment; filename='.$for.'.json');
1214
+ header('Content-Type: application/json');
1215
+ echo json_encode($data);
1216
+
1217
+ // destroy vars
1218
+ unset($data,$options,$widget_id,$option_name,$for);
1219
+
1220
+ // exit now, because we need only debug data in JSON file, not settings or any other page
1221
+ exit;
1222
+ }
1223
+ } // end class
1224
+ } // end class check
1225
+
1226
+ // add_action('plugins_loaded', create_function( '', '$WPAU_YOUTUBE_CHANNEL = new WPAU_YOUTUBE_CHANNEL();' ) );
1227
+
1228
+ global $WPAU_YOUTUBE_CHANNEL;
1229
+ if ( empty($WPAU_YOUTUBE_CHANNEL) )
1230
+ $WPAU_YOUTUBE_CHANNEL = new WPAU_YOUTUBE_CHANNEL();