PluginProbe
Automatic YouTube Gallery – Embed Auto-Updating YouTube Video Galleries, Feeds, Playlists & Channels / 2.3.8
Automatic YouTube Gallery – Embed Auto-Updating YouTube Video Galleries, Feeds, Playlists & Channels v2.3.8
2.9.1 2.9.0 trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 2.0.0 2.1.0 2.2.0 2.3.2 2.3.3 2.3.5 2.3.6 2.3.8 2.3.9 2.4.3 All 37 releases
← All changes | includes/functions.php +511 -310 1.2.02.3.8 View file →
@@ -17,12 +17,14 @@
17 17 /**
18 18 * Build gallery HTML output.
19 19 *
20 20 * @since 1.0.0
21 - * @param array $atts An associative array of attributes.
21 + * @param array $args An array of gallery options.
22 22 * @return mixed
23 23 */
24 -function ayg_build_gallery( $atts ) {
24 +function ayg_build_gallery( $args ) {
25 + global $post;
26 +
25 27 // Vars
26 28 $fields = ayg_get_editor_fields();
27 29 $defaults = array();
28 30
@@ -31,10 +33,15 @@
31 33 $defaults[ $field['name'] ] = $field['value'];
32 34 }
33 35 }
34 36
35 - $attributes = shortcode_atts( $defaults, $atts );
37 + $attributes = shortcode_atts( $defaults, $args );
36 38
39 + $attributes['post_id'] = 0;
40 + if ( isset( $post->ID ) ) {
41 + $attributes['post_id'] = (int) $post->ID;
42 + }
43 +
37 44 $attributes['columns'] = min( 12, (int) $attributes['columns'] );
38 45 if ( empty( $attributes['columns'] ) ) {
39 46 $attributes['columns'] = 3;
40 47 }
@@ -48,46 +55,358 @@
48 55 if ( empty( $attributes['per_page'] ) ) {
49 56 $attributes['per_page'] = 50;
50 57 }
51 58
52 - // Get Videos
53 59 $source_type = sanitize_text_field( $attributes['type'] );
60 + if ( 'livestream' == $source_type ) {
61 + $attributes['livestream'] = $attributes['channel'];
62 + }
54 63
64 + if ( isset( $args['uid'] ) && ! empty( $args['uid'] ) ) {
65 + $attributes['uid'] = $args['uid'];
66 + } else {
67 + $attributes['uid'] = md5( $source_type . sanitize_text_field( $attributes[ $source_type ] ) . sanitize_text_field( $attributes['theme'] ) );
68 + }
69 +
70 + // Get Videos
55 71 $api_params = array(
56 72 'type' => $source_type,
57 - 'id' => sanitize_text_field( $attributes[ $source_type ] ),
58 - 'order' => sanitize_text_field( $attributes['order'] ), // works only when type=search
73 + 'src' => sanitize_text_field( $attributes[ $source_type ] ),
74 + 'order' => sanitize_text_field( $attributes['order'] ), // applicable only when type=search
59 75 'maxResults' => $attributes['per_page'],
60 76 'cache' => (int) $attributes['cache']
61 77 );
62 78
79 + $api_params = apply_filters( 'ayg_youtube_api_request_params', $api_params, $args );
80 +
63 81 $youtube_api = new AYG_YouTube_API();
64 - $response = $youtube_api->get_videos( $api_params );
82 + $response = $youtube_api->query( $api_params );
65 83
66 84 // Process output
67 85 if ( ! isset( $response->error ) ) {
86 + // Store Gallery ID
87 + if ( $attributes['post_id'] > 0 && isset( $attributes['deeplinking'] ) && 1 == $attributes['deeplinking'] ) {
88 + $pages = get_option( 'ayg_gallery_page_ids', array() );
89 + $page_id = $attributes['post_id'];
90 +
91 + if ( ! in_array( $page_id, $pages ) ) {
92 + $pages[] = $page_id;
93 + update_option( 'ayg_gallery_page_ids', $pages );
94 + }
95 + }
96 +
97 + // Enqueue dependencies
98 + wp_enqueue_style( AYG_SLUG . '-public' );
99 + wp_enqueue_script( AYG_SLUG . '-public' );
100 +
68 101 // Gallery
69 - $videos = array();
102 + $videos = array();
103 +
104 + $gallery_id_from_url = get_query_var( 'ayg_gallery_id' );
105 + $video_id_from_url = get_query_var( 'ayg_video_id' );
106 +
107 + if ( $attributes['uid'] == $gallery_id_from_url ) {
108 + $video = ayg_db_get_video( $video_id_from_url );
109 +
110 + if ( $video ) {
111 + $videos[] = $video;
112 + } else {
113 + $video_id_from_url = '';
114 + }
115 + }
70 116
71 117 if ( isset( $response->videos ) ) {
72 - $videos = $response->videos;
118 + if ( ! empty( $video_id_from_url ) ) {
119 + foreach ( $response->videos as $video ) {
120 + if ( $video->id != $video_id_from_url ) {
121 + $videos[] = $video;
122 + }
123 + }
124 + } else {
125 + $videos = $response->videos;
126 + }
73 127 }
74 128
75 129 // Pagination
76 130 if ( isset( $response->page_info ) ) {
77 - $attributes = array_merge( $attributes, $response->page_info, $api_params );
131 + $attributes = array_merge( $attributes, $api_params, $response->page_info );
78 132 }
79 133
134 + // Theme
135 + $theme = 'classic';
136 +
137 + if ( 'video' == $source_type ) {
138 + $theme = 'single';
139 + } elseif ( 'livestream' == $source_type ) {
140 + $theme = 'livestream';
141 + } else {
142 + if ( 1 == count( $videos ) ) {
143 + $theme = 'single';
144 + }
145 + }
146 +
80 147 // Output
81 148 ob_start();
82 - include ayg_get_template( AYG_DIR . 'public/templates/theme-classic.php', $attributes['theme'] );
149 + include ayg_get_template( AYG_DIR . "public/templates/theme-{$theme}.php", $attributes['theme'] );
83 150 return ob_get_clean();
84 151 } else {
85 - return $response->error_message;
152 + return sprintf( '<div class="ayg ayg-error">%s</div>', wp_kses_post( $response->error_message ) );
86 153 }
87 154 }
88 155
89 156 /**
157 + * Create a custom database table "{$wpdb->prefix}ayg_videos"
158 + *
159 + * @since 2.1.0
160 + */
161 +function ayg_db_create_videos_table() {
162 + global $wpdb;
163 +
164 + $charset_collate = $wpdb->get_charset_collate();
165 +
166 + $sql = "CREATE TABLE `{$wpdb->prefix}ayg_videos` (
167 + NUM bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
168 + id varchar(100) NOT NULL,
169 + title text NOT NULL,
170 + description text NOT NULL,
171 + thumbnails text NOT NULL,
172 + duration varchar(25) NOT NULL,
173 + status varchar(100) NOT NULL,
174 + published_at varchar(100) NOT NULL,
175 + PRIMARY KEY (NUM)
176 + ) $charset_collate;";
177 +
178 + require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
179 + dbDelta( $sql );
180 +}
181 +
182 +/**
183 + * Store videos in our custom database table "{$wpdb->prefix}ayg_videos"
184 + *
185 + * @since 2.1.0
186 + * @param object $data YouTube API response object.
187 + */
188 +function ayg_db_store_videos( $data ) {
189 + if ( AYG_VERSION !== get_option( 'ayg_version' ) ) {
190 + return false;
191 + }
192 +
193 + global $wpdb, $post;
194 +
195 + $table_name = $wpdb->prefix . 'ayg_videos';
196 +
197 + if ( isset( $data->kind ) && 'youtube#channelListResponse' == $data->kind ) {
198 + return false;
199 + }
200 +
201 + if ( ! isset( $data->items ) ) {
202 + return false;
203 + }
204 +
205 + $items = $data->items;
206 + if ( ! is_array( $items ) || 0 == count( $items ) ) {
207 + return false;
208 + }
209 +
210 + // Store Videos
211 + foreach ( $items as $item ) {
212 + $row = array();
213 +
214 + // Video ID
215 + $row['id'] = '';
216 +
217 + if ( isset( $item->snippet->resourceId ) && isset( $item->snippet->resourceId->videoId ) ) {
218 + $row['id'] = $item->snippet->resourceId->videoId;
219 + } elseif ( isset( $item->contentDetails ) && isset( $item->contentDetails->videoId ) ) {
220 + $row['id'] = $item->contentDetails->videoId;
221 + } elseif ( isset( $item->id ) && isset( $item->id->videoId ) ) {
222 + $row['id'] = $item->id->videoId;
223 + } elseif ( isset( $item->id ) ) {
224 + $row['id'] = $item->id;
225 + }
226 +
227 + if ( empty( $row['id'] ) ) {
228 + continue;
229 + }
230 +
231 + // Video title
232 + $row['title'] = $item->snippet->title;
233 +
234 + // Video description
235 + $row['description'] = $item->snippet->description;
236 +
237 + // Video thumbnails
238 + $row['thumbnails'] = '';
239 + if ( isset( $item->snippet->thumbnails ) ) {
240 + $row['thumbnails'] = serialize( $item->snippet->thumbnails );
241 + }
242 +
243 + // Video duration
244 + $row['duration'] = '';
245 + if ( isset( $item->contentDetails ) && isset( $item->contentDetails->duration ) ) {
246 + $row['duration'] = $item->contentDetails->duration;
247 + }
248 +
249 + // Video status
250 + $row['status'] = 'private';
251 +
252 + if ( isset( $item->status ) && ( 'public' == $item->status->privacyStatus || 'unlisted' == $item->status->privacyStatus ) ) {
253 + $row['status'] = 'public';
254 + }
255 +
256 + if ( isset( $item->snippet->status ) && ( 'public' == $item->snippet->status->privacyStatus || 'unlisted' == $item->snippet->status->privacyStatus ) ) {
257 + $row['status'] = 'public';
258 + }
259 +
260 + if ( 'youtube#searchResult' == $item->kind ) {
261 + $row['status'] = 'public';
262 + }
263 +
264 + // Video publish date
265 + $row['published_at'] = $item->snippet->publishedAt;
266 +
267 + // Store
268 + $query = $wpdb->prepare( "SELECT NUM FROM $table_name WHERE id = %s", $row['id'] );
269 + $insert_id = $wpdb->get_var( $query );
270 +
271 + if ( empty( $insert_id ) ) {
272 + $wpdb->insert(
273 + $table_name,
274 + $row,
275 + array( '%s', '%s', '%s', '%s', '%s', '%s', '%s' )
276 + );
277 + } else {
278 + $wpdb->update(
279 + $table_name,
280 + $row,
281 + array( 'NUM' => $insert_id ),
282 + array( '%s', '%s', '%s', '%s', '%s', '%s', '%s' ),
283 + array( '%d' )
284 + );
285 + }
286 + }
287 +}
288 +
289 +/**
290 + * Get a single video record from our custom database table "{$wpdb->prefix}ayg_videos"
291 + *
292 + * @since 2.1.0
293 + * @param string $video_id YouTube Video ID.
294 + * @return mixed
295 + */
296 +function ayg_db_get_video( $video_id ) {
297 + global $wpdb;
298 +
299 + $cache_key = 'ayg_'. $video_id;
300 + $row = wp_cache_get( $cache_key );
301 +
302 + if ( false === $row ) {
303 + $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}ayg_videos WHERE id = %s", $video_id );
304 + $row = $wpdb->get_row( $query );
305 +
306 + if ( $row ) {
307 + if ( ! empty( $row->thumbnails ) ) {
308 + $row->thumbnails = unserialize( $row->thumbnails );
309 + }
310 +
311 + wp_cache_set( $cache_key, $row );
312 + }
313 + }
314 +
315 + return $row;
316 +}
317 +
318 +/**
319 + * Dump our plugin transients.
320 + *
321 + * @since 2.1.0
322 + */
323 +function ayg_delete_cache() {
324 + delete_option( 'ayg_gallery_page_ids' );
325 +
326 + // Get the current list of transients
327 + $transient_keys = get_option( 'ayg_transient_keys', array() );
328 +
329 + // For each key, delete that transient
330 + foreach ( $transient_keys as $key ) {
331 + delete_transient( $key );
332 + }
333 +
334 + // Reset our DB value
335 + update_option( 'ayg_transient_keys', array() );
336 +}
337 +
338 +/**
339 + * Get current address bar URL.
340 + *
341 + * @since 2.1.0
342 + * @return string Current Page URL.
343 + */
344 +function ayg_get_current_url() {
345 + global $wp;
346 + $current_url = home_url( add_query_arg( array(), $wp->request ) );
347 +
348 + return $current_url;
349 +}
350 +
351 +/**
352 + * Get default plugin settings.
353 + *
354 + * @since 1.6.4
355 + * @return array $defaults Array of plugin settings.
356 + */
357 +function ayg_get_default_settings() {
358 + $defaults = array(
359 + 'ayg_general_settings' => array(
360 + 'api_key' => '',
361 + 'development_mode' => 1
362 + ),
363 + 'ayg_gallery_settings' => array(
364 + 'theme' => 'classic',
365 + 'columns' => 3,
366 + 'per_page' => 12,
367 + 'thumb_ratio' => 56.25,
368 + 'thumb_title' => 1,
369 + 'thumb_title_length' => 0,
370 + 'thumb_excerpt' => 1,
371 + 'thumb_excerpt_length' => 75,
372 + 'pagination' => 1,
373 + 'pagination_type' => 'more',
374 + 'more_button_label' => __( 'Load More', 'automatic-youtube-gallery' ),
375 + 'previous_button_label' => __( 'Previous', 'automatic-youtube-gallery' ),
376 + 'next_button_label' => __( 'Next', 'automatic-youtube-gallery' )
377 + ),
378 + 'ayg_player_settings' => array(
379 + 'player_ratio' => 56.25,
380 + 'player_title' => 1,
381 + 'player_description' => 1,
382 + 'autoplay' => 0,
383 + 'autoadvance' => 1,
384 + 'loop' => 0,
385 + 'muted' => 0,
386 + 'controls' => 1,
387 + 'modestbranding' => 1,
388 + 'cc_load_policy' => 0,
389 + 'iv_load_policy' => 0,
390 + 'hl' => '',
391 + 'cc_lang_pref' => '',
392 + 'privacy_enhanced_mode' => 0,
393 + 'origin' => 0
394 + ),
395 + 'ayg_livestream_settings' => array(
396 + 'fallback_message' => __( 'Sorry, but the channel is not currently streaming live content. Please check back later.', 'automatic-youtube-gallery' )
397 + ),
398 + 'ayg_privacy_settings' => array(
399 + 'cookie_consent' => 0,
400 + 'consent_message' => __( 'Please accept YouTube cookies to play this video. By accepting you will be accessing content from YouTube, a service provided by an external third party.', 'automatic-youtube-gallery' ),
401 + 'button_label' => __( 'Accept', 'automatic-youtube-gallery' )
402 + )
403 + );
404 +
405 + return $defaults;
406 +}
407 +
408 +/**
90 409 * Get editor fields.
91 410 *
92 411 * @since 1.0.0
93 412 * @return array Array of fields.
@@ -94,9 +413,9 @@
94 413 */
95 414 function ayg_get_editor_fields() {
96 415 $fields = array(
97 416 'source' => array(
98 - 'label' => __( 'Source', 'automatic-youtube-gallery' ),
417 + 'label' => __( 'General', 'automatic-youtube-gallery' ),
99 418 'fields' => array(
100 419 array(
101 420 'name' => 'type',
102 421 'label' => __( 'Source Type', 'automatic-youtube-gallery' ),
@@ -102,14 +421,15 @@
102 421 'label' => __( 'Source Type', 'automatic-youtube-gallery' ),
103 422 'description' => '',
104 423 'type' => 'select',
105 424 'options' => array(
106 - 'playlist' => __( 'Playlist', 'automatic-youtube-gallery' ),
107 - 'channel' => __( 'Channel', 'automatic-youtube-gallery' ),
108 - 'username' => __( 'Username', 'automatic-youtube-gallery' ),
109 - 'search' => __( 'Keyword', 'automatic-youtube-gallery' ),
110 - 'videos' => __( 'Videos', 'automatic-youtube-gallery' ),
111 - 'video' => __( 'Video', 'automatic-youtube-gallery' )
425 + 'playlist' => __( 'Playlist', 'automatic-youtube-gallery' ),
426 + 'channel' => __( 'Channel', 'automatic-youtube-gallery' ),
427 + 'username' => __( 'Username', 'automatic-youtube-gallery' ),
428 + 'search' => __( 'Search Keywords', 'automatic-youtube-gallery' ),
429 + 'video' => __( 'Single Video', 'automatic-youtube-gallery' ),
430 + 'livestream' => __( 'Livestream', 'automatic-youtube-gallery' ),
431 + 'videos' => __( 'Custom Videos List', 'automatic-youtube-gallery' )
112 432 ),
113 433 'value' => 'playlist',
114 434 'sanitize_callback' => 'sanitize_key'
115 435 ),
@@ -114,9 +434,9 @@
114 434 'sanitize_callback' => 'sanitize_key'
115 435 ),
116 436 array(
117 437 'name' => 'playlist',
118 - 'label' => __( 'YouTube Playlist URL', 'automatic-youtube-gallery' ),
438 + 'label' => __( 'YouTube Playlist ID (or) URL', 'automatic-youtube-gallery' ),
119 439 'description' => sprintf( '%s: https://www.youtube.com/playlist?list=XXXXXXXXXX', __( 'Example', 'automatic-youtube-gallery' ) ),
120 440 'type' => 'url',
121 441 'value' => '',
122 442 'sanitize_callback' => 'sanitize_text_field'
@@ -122,9 +442,9 @@
122 442 'sanitize_callback' => 'sanitize_text_field'
123 443 ),
124 444 array(
125 445 'name' => 'channel',
126 - 'label' => __( 'YouTube Channel URL', 'automatic-youtube-gallery' ),
446 + 'label' => __( 'YouTube Channel ID (or) a YouTube Video URL from the Channel', 'automatic-youtube-gallery' ),
127 447 'description' => sprintf( '%s: https://www.youtube.com/channel/XXXXXXXXXX', __( 'Example', 'automatic-youtube-gallery' ) ),
128 448 'type' => 'url',
129 449 'value' => '',
130 450 'sanitize_callback' => 'sanitize_text_field'
@@ -138,10 +458,10 @@
138 458 'sanitize_callback' => 'sanitize_text_field'
139 459 ),
140 460 array(
141 461 'name' => 'search',
142 - 'label' => __( 'Enter a Search Keyword', 'automatic-youtube-gallery' ),
143 - 'description' => sprintf( '%s: Cartoon', __( 'Example', 'automatic-youtube-gallery' ) ),
462 + 'label' => __( 'Search Keywords', 'automatic-youtube-gallery' ),
463 + 'description' => sprintf( '%s: Cartoon (space:AND , -:NOT , |:OR)', __( 'Example', 'automatic-youtube-gallery' ) ),
144 464 'type' => 'text',
145 465 'value' => '',
146 466 'sanitize_callback' => 'sanitize_text_field'
147 467 ),
@@ -146,23 +466,23 @@
146 466 'sanitize_callback' => 'sanitize_text_field'
147 467 ),
148 468 array(
149 469 'name' => 'video',
150 - 'label' => __( 'Enter a YouTube Video URL', 'automatic-youtube-gallery' ),
470 + 'label' => __( 'YouTube Video ID (or) URL', 'automatic-youtube-gallery' ),
151 471 'description' => sprintf( '%s: https://www.youtube.com/watch?v=XXXXXXXXXX', __( 'Example', 'automatic-youtube-gallery' ) ),
152 472 'type' => 'url',
153 473 'value' => '',
154 474 'sanitize_callback' => 'sanitize_text_field'
155 - ),
475 + ),
156 476 array(
157 477 'name' => 'videos',
158 - 'label' => __( 'YouTube Video URLs', 'automatic-youtube-gallery' ),
478 + 'label' => __( 'YouTube Video IDs (or) URLs', 'automatic-youtube-gallery' ),
159 479 'description' => sprintf( '%s: https://www.youtube.com/watch?v=XXXXXXXXXX', __( 'Example', 'automatic-youtube-gallery' ) ),
160 480 'type' => 'textarea',
161 481 'placeholder' => __( 'Enter one video per line', 'automatic-youtube-gallery' ),
162 482 'value' => '',
163 483 'sanitize_callback' => 'sanitize_text_field'
164 - ),
484 + ),
165 485 array(
166 486 'name' => 'order',
167 487 'label' => __( 'Order Videos by', 'automatic-youtube-gallery' ),
168 488 'description' => '',
@@ -188,21 +508,20 @@
188 508 'sanitize_callback' => 'intval'
189 509 ),
190 510 array(
191 511 'name' => 'cache',
192 - 'label' => __( 'Refresh the data every (Cache time)', 'automatic-youtube-gallery' ),
193 - 'description' => __( 'Specifies how frequently the plugin should check your YouTube source for any new update.', 'automatic-youtube-gallery' ),
512 + 'label' => __( 'Cache Duration', 'automatic-youtube-gallery' ),
513 + 'description' => __( 'Specifies how frequently we should check your YouTube source for new videos/updates.', 'automatic-youtube-gallery' ),
194 514 'type' => 'select',
195 515 'options' => array(
196 - '0' => __( 'Page load', 'automatic-youtube-gallery' ),
197 - '900' => __( '15 minutes', 'automatic-youtube-gallery' ),
198 - '1800' => __( '30 minutes', 'automatic-youtube-gallery' ),
199 - '3600' => __( 'Hour', 'automatic-youtube-gallery' ),
200 - '86400' => __( 'Day', 'automatic-youtube-gallery' ),
201 - '604800' => __( 'Week', 'automatic-youtube-gallery' ),
202 - '2419200' => __( 'Month', 'automatic-youtube-gallery' )
516 + '900' => __( '15 Minutes', 'automatic-youtube-gallery' ),
517 + '1800' => __( '30 Minutes', 'automatic-youtube-gallery' ),
518 + '3600' => __( '1 Hour', 'automatic-youtube-gallery' ),
519 + '86400' => __( '1 Day', 'automatic-youtube-gallery' ),
520 + '604800' => __( '1 Week', 'automatic-youtube-gallery' ),
521 + '2419200' => __( '1 Month', 'automatic-youtube-gallery' )
203 522 ),
204 - 'value' => 0,
523 + 'value' => 86400,
205 524 'sanitize_callback' => 'intval'
206 525 )
207 526 )
208 527 ),
@@ -219,109 +538,8 @@
219 538 return apply_filters( 'ayg_editor_fields', $fields );
220 539 }
221 540
222 541 /**
223 - * Get gallery thumbnail video excerpt (short description).
224 - *
225 - * @since 1.0.0
226 - * @param stdClass $video YouTube video object.
227 - * @param array $attributes Array of user attributes.
228 - * @return string Video excerpt.
229 - */
230 -function ayg_get_gallery_thumb_excerpt( $video, $attributes ) {
231 - $char_length = (int) $attributes['thumb_excerpt_length'];
232 - $char_length++;
233 -
234 - $content = '';
235 - if ( ! empty( $attributes['thumb_excerpt'] ) ) {
236 - $content = ( $char_length > 1 ) ? wp_strip_all_tags( $video->description, true ) : nl2br( $video->description );
237 - }
238 -
239 - $excerpt = '';
240 -
241 - if ( $char_length > 1 && mb_strlen( $content ) > $char_length ) {
242 - $subex = mb_substr( $content, 0, $char_length - 5 );
243 - $exwords = explode( ' ', $subex );
244 - $excut = - ( mb_strlen( $exwords[ count( $exwords ) - 1 ] ) );
245 - if ( $excut < 0 ) {
246 - $excerpt = mb_substr( $subex, 0, $excut );
247 - } else {
248 - $excerpt = $subex;
249 - }
250 - $excerpt .= '[...]';
251 - } else {
252 - $excerpt = $content;
253 - }
254 -
255 - return apply_filters( 'ayg_gallery_thumb_excerpt', $excerpt, $video, $attributes );
256 -}
257 -
258 -/**
259 - * Get gallery thumbnail image.
260 - *
261 - * @since 1.0.0
262 - * @param stdClass $video YouTube video object.
263 - * @param array $attributes Array of user attributes.
264 - * @return string Video thumbnail image.
265 - */
266 -function ayg_get_gallery_thumb_image( $video, $attributes ) {
267 - $image = '';
268 -
269 - if ( isset( $video->thumbnails->default ) ) {
270 - $image = $video->thumbnails->default->url;
271 - }
272 -
273 - // 4:3 ( default - 120x90, high - 480x360, standard - 640x480 )
274 - if ( 75 == (int) $attributes['thumb_ratio'] ) {
275 - if ( isset( $video->thumbnails->high ) ) {
276 - $image = $video->thumbnails->high->url;
277 - }
278 - }
279 -
280 - // 16:9 ( medium - 320x180, maxres - 1280x720 )
281 - if ( 56.25 == (float) $attributes['thumb_ratio'] ) {
282 - if ( isset( $video->thumbnails->medium ) ) {
283 - $image = $video->thumbnails->medium->url;
284 - }
285 - }
286 -
287 - return apply_filters( 'ayg_gallery_thumb_image', $image, $video, $attributes );
288 -}
289 -
290 -/**
291 - * Get gallery thumbnail video title.
292 - *
293 - * @since 1.0.0
294 - * @param stdClass $video YouTube video object.
295 - * @param array $attributes Array of user attributes.
296 - * @return string Video title.
297 - */
298 -function ayg_get_gallery_thumb_title( $video, $attributes ) {
299 - $text = ! empty( $attributes['thumb_title'] ) ? $video->title : '';
300 -
301 - $char_length = (int) $attributes['thumb_title_length'];
302 - $char_length++;
303 -
304 - $title = '';
305 -
306 - if ( $char_length > 1 && mb_strlen( $text ) > $char_length ) {
307 - $subex = mb_substr( $text, 0, $char_length - 5 );
308 - $exwords = explode( ' ', $subex );
309 - $excut = - ( mb_strlen( $exwords[ count( $exwords ) - 1 ] ) );
310 - if ( $excut < 0 ) {
311 - $title = mb_substr( $subex, 0, $excut );
312 - } else {
313 - $title = $subex;
314 - }
315 - $title .= '[...]';
316 - } else {
317 - $title = $text;
318 - }
319 -
320 - return apply_filters( 'ayg_gallery_thumb_title', $title, $video, $attributes );
321 -}
322 -
323 -/**
324 542 * Get gallery settings fields.
325 543 *
326 544 * @since 1.0.0
327 545 * @return array $fields Array of fields.
@@ -331,10 +549,10 @@
331 549
332 550 $fields = array(
333 551 array(
334 552 'name' => 'theme',
335 - 'label' => __( 'Select Theme', 'automatic-youtube-gallery' ),
336 - 'description' => ( ayg_fs()->is_not_paying() ? sprintf( __( '<a href="%s">Upgrade Pro</a> for more themes (Popup, Slider, Playlister).', 'automatic-youtube-gallery' ), esc_url( ayg_fs()->get_upgrade_url() ) ) : '' ),
553 + 'label' => __( 'Select Theme (Layout)', 'automatic-youtube-gallery' ),
554 + 'description' => ( ayg_fs()->is_not_paying() ? sprintf( __( '<a href="%s">Upgrade Pro</a> for more themes (Popup, Inline, Slider, Playlist).', 'automatic-youtube-gallery' ), esc_url( ayg_fs()->get_upgrade_url() ) ) : '' ),
337 555 'type' => 'select',
338 556 'options' => array(
339 557 'classic' => __( 'Classic', 'automatic-youtube-gallery' )
340 558 ),
@@ -352,9 +570,9 @@
352 570 'sanitize_callback' => 'intval'
353 571 ),
354 572 array(
355 573 'name' => 'per_page',
356 - 'label' => __( 'Videos per page', 'automatic-youtube-gallery' ),
574 + 'label' => __( 'Videos per Page', 'automatic-youtube-gallery' ),
357 575 'description' => __( 'Enter the number of videos to show per page. Maximum of 50.', 'automatic-youtube-gallery' ),
358 576 'type' => 'number',
359 577 'min' => 0,
360 578 'max' => 50,
@@ -362,9 +580,10 @@
362 580 'sanitize_callback' => 'intval'
363 581 ),
364 582 array(
365 583 'name' => 'thumb_ratio',
366 - 'label' => __( 'Thumbnail Ratio', 'automatic-youtube-gallery' ),
584 + 'label' => __( 'Image Height (Ratio)', 'automatic-youtube-gallery' ),
585 + 'description' => __( 'Select the ratio value used to calculate the image height in the gallery thumbnails.', 'automatic-youtube-gallery' ),
367 586 'type' => 'radio',
368 587 'options' => array(
369 588 '56.25' => '16:9',
370 589 '75' => '4:3'
@@ -420,13 +639,38 @@
420 639 'name' => 'pagination_type',
421 640 'label' => __( 'Pagination Type', 'automatic-youtube-gallery' ),
422 641 'type' => 'select',
423 642 'options' => array(
424 - 'pager' => __( 'Pager', 'automatic-youtube-gallery' ),
425 - 'load_more' => __( 'Load More', 'automatic-youtube-gallery' )
643 + 'more' => __( 'More Button', 'automatic-youtube-gallery' ),
644 + 'pager' => __( 'Pager', 'automatic-youtube-gallery' )
645 +
426 646 ),
427 647 'value' => $gallery_settings['pagination_type'],
428 648 'sanitize_callback' => 'sanitize_key'
649 + ),
650 + array(
651 + 'name' => 'more_button_label',
652 + 'label' => __( 'More Button Label', 'automatic-youtube-gallery' ),
653 + 'description' => __( 'Enter the more button label text.', 'automatic-youtube-gallery' ),
654 + 'type' => 'text',
655 + 'value' => isset( $gallery_settings['more_button_label'] ) ? $gallery_settings['more_button_label'] : __( 'Load More', 'automatic-youtube-gallery' ),
656 + 'sanitize_callback' => 'sanitize_text_field'
657 + ),
658 + array(
659 + 'name' => 'previous_button_label',
660 + 'label' => __( 'Previous Button Label', 'automatic-youtube-gallery' ),
661 + 'description' => __( 'Enter the previous button label text.', 'automatic-youtube-gallery' ),
662 + 'type' => 'text',
663 + 'value' => isset( $gallery_settings['previous_button_label'] ) ? $gallery_settings['previous_button_label'] : __( 'Previous', 'automatic-youtube-gallery' ),
664 + 'sanitize_callback' => 'sanitize_text_field'
665 + ),
666 + array(
667 + 'name' => 'next_button_label',
668 + 'label' => __( 'Next Button Label', 'automatic-youtube-gallery' ),
669 + 'description' => __( 'Enter the next button label text.', 'automatic-youtube-gallery' ),
670 + 'type' => 'text',
671 + 'value' => isset( $gallery_settings['next_button_label'] ) ? $gallery_settings['next_button_label'] : __( 'Next', 'automatic-youtube-gallery' ),
672 + 'sanitize_callback' => 'sanitize_text_field'
429 673 )
430 674 );
431 675
432 676 return apply_filters( 'ayg_gallery_settings_fields', $fields );
@@ -436,90 +680,29 @@
436 680 * Get video description to show on top of the player.
437 681 *
438 682 * @since 1.0.0
439 683 * @param stdClass $video YouTube video object.
440 - * @param array $attributes Array of user attributes.
441 684 * @param int $words_count Number of words to show by default.
442 685 * @return string Video description.
443 686 */
444 -function ayg_get_player_description( $video, $attributes, $words_count = 30 ) {
445 - $description = ! empty( $attributes['player_description'] ) ? $video->description : '';
687 +function ayg_get_player_description( $video, $words_count = 30 ) {
688 + $description = $video->description;
446 689
447 - $words_array = explode( ' ', strip_tags( $description ) );
448 -
690 + $words_array = explode( ' ', strip_tags( $description ) );
449 691 if ( count( $words_array ) > $words_count ) {
450 - $words_array[ $words_count ] = '</span><span class="ayg-player-description-more">' . $words_array[ $words_count ];
692 + $words_array[ $words_count ] = '<span class="ayg-player-description-dots">...</span></span><span class="ayg-player-description-more">' . $words_array[ $words_count ];
451 693
452 694 $description = '<span class="ayg-player-description-less">' . implode( ' ', $words_array ) . '</span>';
453 - $description .= '<span><a class="ayg-player-description-more-less-btn">' . __( 'Show More', 'automatic-youtube-gallery' ) . '</a></span>';
695 + $description .= '<a href="#" class="ayg-player-description-toggle-btn">[+] ' . __( 'Show More', 'automatic-youtube-gallery' ) . '</a>';
454 696 }
455 697
456 - return apply_filters( 'ayg_player_description', nl2br( $description ), $video, $attributes, $words_count );
457 -}
698 + $description = nl2br( $description );
699 + $description = make_clickable( $description );
458 700
459 -/**
460 - * Get YouTube player embed URL.
461 - *
462 - * @since 1.0.0
463 - * @param stdClass $video YouTube video object.
464 - * @param array $attributes Array of user attributes.
465 - * @return string YouTube video embed URL.
466 - */
467 -function ayg_get_player_embed_url( $video, $attributes ) {
468 - $url = "https://www.youtube-nocookie.com/embed/{$video->id}";
469 -
470 - if ( ! empty( $attributes['autoplay'] ) ) { // autoplay
471 - $url = add_query_arg( 'autoplay', 1, $url );
472 - }
473 -
474 - if ( ! empty( $attributes['loop'] ) ) { // loop
475 - $url = add_query_arg( 'loop', 1, $url );
476 - }
477 -
478 - if ( empty( $attributes['controls'] ) ) { // controls
479 - $url = add_query_arg( 'controls', 0, $url );
480 - }
481 -
482 - if ( ! empty( $attributes['modestbranding'] ) ) { // modestbranding
483 - $url = add_query_arg( 'modestbranding', 1, $url );
484 - }
485 -
486 - if ( ! empty( $attributes['cc_load_policy'] ) ) { // cc_load_policy
487 - $url = add_query_arg( 'cc_load_policy', 1, $url );
488 - }
489 -
490 - if ( empty( $attributes['iv_load_policy'] ) ) { // iv_load_policy
491 - $url = add_query_arg( 'iv_load_policy', 3, $url );
492 - }
493 -
494 - if ( ! empty( $attributes['hl'] ) ) { // hl
495 - $url = add_query_arg( 'hl', $attributes['hl'], $url );
496 - }
497 -
498 - if ( ! empty( $attributes['cc_lang_pref'] ) ) { // cc_lang_pref
499 - $url = add_query_arg( 'cc_lang_pref', $attributes['cc_lang_pref'], $url );
500 - }
501 -
502 - $url = add_query_arg( 'rel', 0, $url ); // rel
503 - $url = add_query_arg( 'playsinline', 1, $url ); // playsinline
504 - $url = add_query_arg( 'enablejsapi', 1, $url ); // enablejsapi
505 -
506 - return apply_filters( 'ayg_player_embed_url', $url, $video, $attributes );
701 + return apply_filters( 'ayg_player_description', $description, $video, $words_count );
507 702 }
508 703
509 704 /**
510 - * Get player ratio.
511 - *
512 - * @since 1.0.0
513 - * @param array $attributes Array of user attributes.
514 - * @return string Player ratio.
515 - */
516 -function ayg_get_player_ratio( $attributes ) {
517 - $ratio = ! empty( $attributes['player_ratio'] ) ? $attributes['player_ratio'] . '%' : '56.25%';
518 - return apply_filters( 'ayg_player_ratio', $ratio, $attributes );
519 -}
520 -
521 -/**
522 705 * Get player settings fields.
523 706 *
524 707 * @since 1.0.0
525 708 * @return array $fields Array of fields.
@@ -529,9 +712,10 @@
529 712
530 713 $fields = array(
531 714 array(
532 715 'name' => 'player_ratio',
533 - 'label' => __( 'Player Ratio', 'automatic-youtube-gallery' ),
716 + 'label' => __( 'Player Height (Ratio)', 'automatic-youtube-gallery' ),
717 + 'description' => __( 'Select the ratio value used to calculate the player height.', 'automatic-youtube-gallery' ),
534 718 'type' => 'radio',
535 719 'options' => array(
536 720 '56.25' => '16:9',
537 721 '75' => '4:3'
@@ -577,10 +761,18 @@
577 761 'description' => __( 'In the case of a single video player, plays the initial video again and again. In the case of a gallery, plays the entire list in the gallery and then starts again at the first video.', 'automatic-youtube-gallery' ),
578 762 'type' => 'checkbox',
579 763 'value' => $player_settings['loop'],
580 764 'sanitize_callback' => 'intval'
581 - ),
765 + ),
582 766 array(
767 + 'name' => 'muted',
768 + 'label' => __( 'Muted', 'automatic-youtube-gallery' ),
769 + 'description' => __( 'Check this option to turn OFF the audio output of the video by default.', 'automatic-youtube-gallery' ),
770 + 'type' => 'checkbox',
771 + 'value' => isset( $player_settings['muted'] ) ? $player_settings['muted'] : 0,
772 + 'sanitize_callback' => 'intval'
773 + ),
774 + array(
583 775 'name' => 'controls',
584 776 'label' => __( 'Show Player Controls', 'automatic-youtube-gallery' ),
585 777 'description' => __( 'Uncheck this option to hide the video player controls.', 'automatic-youtube-gallery' ),
586 778 'type' => 'checkbox',
@@ -631,37 +823,41 @@
631 823 ),
632 824 'type' => 'text',
633 825 'value' => $player_settings['cc_lang_pref'],
634 826 'sanitize_callback' => 'sanitize_text_field'
635 - )
827 + ),
828 + array(
829 + 'name' => 'privacy_enhanced_mode',
830 + 'label' => __( 'Privacy Enhanced Mode', 'automatic-youtube-gallery' ),
831 + 'description' => __( "Prevent YouTube from leaving tracking cookies on your visitor's browsers unless they actually play the videos. Please uncheck this option if you see errors while testing your playlist embeds or watching your videos on mobile.", 'automatic-youtube-gallery' ),
832 + 'type' => 'checkbox',
833 + 'value' => isset( $player_settings['privacy_enhanced_mode'] ) ? $player_settings['privacy_enhanced_mode'] : 0,
834 + 'sanitize_callback' => 'intval'
835 + ),
836 + array(
837 + 'name' => 'origin',
838 + 'label' => __( 'Extra Player Security', 'automatic-youtube-gallery' ),
839 + 'description' => __( 'Add site origin information with each embed code as an extra security measure. In YouTube\'s own words, checking this option "protects against malicious third-party JavaScript being injected into your page and hijacking control of your YouTube player."', 'automatic-youtube-gallery' ),
840 + 'type' => 'checkbox',
841 + 'value' => isset( $player_settings['origin'] ) ? $player_settings['origin'] : 0,
842 + 'sanitize_callback' => 'intval'
843 + ),
636 844 );
637 845
638 846 return $fields;
639 847 }
640 848
641 -/**
642 - * Get video title to show on bottom of the player.
643 - *
644 - * @since 1.0.0
645 - * @param stdClass $video YouTube video object.
646 - * @param array $attributes Array of user attributes.
647 - * @return string Video title.
648 - */
649 -function ayg_get_player_title( $video, $attributes ) {
650 - $title = ! empty( $attributes['player_title'] ) ? $video->title : '';
651 - return apply_filters( 'ayg_player_title', $title, $video, $attributes );
652 -}
653 849
654 850 /**
655 - * Get player width.
851 + * Get a single video page URL.
656 852 *
657 - * @since 1.0.0
658 - * @param array $attributes Array of user attributes.
659 - * @return string Player width.
853 + * @since 2.1.0
854 + * @param stdClass $video YouTube video object.
855 + * @param array $args An array of gallery options.
856 + * @return string Single video URL.
660 857 */
661 -function ayg_get_player_width( $attributes ) {
662 - $width = ! empty( $attributes['player_width'] ) ? $attributes['player_width'] . 'px' : '100%';
663 - return apply_filters( 'ayg_player_width', $width, $attributes );
858 +function ayg_get_single_video_url( $video, $attributes ) {
859 + return apply_filters( 'ayg_single_video_url', '', $video, $attributes );
664 860 }
665 861
666 862 /**
667 863 * Get filtered php template file path.
@@ -691,110 +887,115 @@
691 887 return uniqid() . ++$ayg_uniqid;
692 888 }
693 889
694 890 /**
695 - * Sanitize the integer inputs, accepts empty values.
891 + * Get YouTube domain.
696 892 *
697 - * @since 1.0.0
698 - * @param string|int $value Input value.
699 - * @return string|int Sanitized value.
893 + * @since 2.3.0
894 + * @return string YouTube embed domain.
700 895 */
701 -function ayg_sanitize_int( $value ) {
702 - $value = intval( $value );
703 - return ( 0 == $value ) ? '' : $value;
896 +function ayg_get_youtube_domain() {
897 + $player_settings = get_option( 'ayg_player_settings' );
898 +
899 + $domain = 'https://www.youtube.com';
900 + if ( isset( $player_settings['privacy_enhanced_mode'] ) && ! empty( $player_settings['privacy_enhanced_mode'] ) ) {
901 + $domain = 'https://www.youtube-nocookie.com';
902 + }
903 +
904 + return $domain;
704 905 }
705 906
706 907 /**
707 - * Gallery HTML output.
908 + * Inserts a new associative array after another associative array key.
708 909 *
709 - * @since 1.0.0
710 - * @param array $videos Array of YouTube video object.
711 - * @param array $attributes Array of user attributes.
712 - * @param int $active_id Current active/selected video ID in the gallery.
910 + * @since 2.1.0
911 + * @param string $key The associative array key to insert after.
912 + * @param array $array An array to insert in to.
913 + * @param array $new_array An array to insert.
914 + * @return array Updated array.
713 915 */
714 -function the_ayg_gallery( $videos, $attributes, $active_id = 0 ) {
715 - if ( 'video' != $attributes['type'] ) {
716 - include ayg_get_template( AYG_DIR . 'public/templates/gallery.php', $attributes['theme'] );
717 - }
916 +function ayg_insert_array_after( $key, $array, $new_array ) {
917 + if ( array_key_exists( $key, $array ) ) {
918 + $new = array();
919 +
920 + foreach ( $array as $k => $value ) {
921 + $new[ $k ] = $value;
922 +
923 + if ( $k === $key ) {
924 + foreach ( $new_array as $new_key => $new_value ) {
925 + $new[ $new_key ] = $new_value;
926 + }
927 + }
928 + }
929 +
930 + return $new;
931 + }
932 +
933 + return $array;
718 934 }
719 935
720 936 /**
721 - * Gallery HTML output.
937 + * Sanitize the integer inputs, accepts empty values.
722 938 *
723 939 * @since 1.0.0
724 - * @param array $video YouTube video object.
725 - * @param array $attributes Array of user attributes.
726 - * @param boolean $is_active True if active video item, false if not.
940 + * @param string|int $value Input value.
941 + * @return string|int Sanitized value.
727 942 */
728 -function the_ayg_gallery_thumbnail( $video, $attributes, $is_active = false ) {
729 - include ayg_get_template( AYG_DIR . 'public/templates/gallery-thumbnail.php', $attributes['theme'] );
943 +function ayg_sanitize_int( $value ) {
944 + $value = intval( $value );
945 + return ( 0 == $value ) ? '' : $value;
730 946 }
731 947
732 948 /**
733 - * Pagination HTML output.
949 + * Trims text to a certain number of characters.
734 950 *
735 - * @since 1.0.0
736 - * @param array $atts Array of user attributes.
951 + * @since 2.0.0
952 + * @param string $text Text to trim.
953 + * @param int $num_characters Number of characters.
954 + * @param string $append String to append to the end of the excerpt.
955 + * @return string Trimmed text.
737 956 */
738 -function the_ayg_pagination( $atts ) {
739 - if ( ! empty( $atts['pagination'] ) ) {
740 - // Build attributes
741 - $attributes = array();
957 +function ayg_trim_words( $text, $num_characters, $append = '...' ) {
958 + $num_characters++;
742 959
743 - $fields = ayg_get_editor_fields();
960 + $original_text = $text;
961 + $text = ( $num_characters > 1 ) ? wp_strip_all_tags( $original_text, true ) : nl2br( $original_text );
744 962
745 - foreach ( $fields['gallery']['fields'] as $field ) {
746 - $field_name = $field['name'];
963 + if ( $num_characters > 1 && mb_strlen( $text ) > $num_characters ) {
964 + $subex = mb_substr( $text, 0, $num_characters - 5 );
965 + $exwords = explode( ' ', $subex );
966 + $excut = - ( mb_strlen( $exwords[ count( $exwords ) - 1 ] ) );
747 967
748 - if ( ! in_array( $field_name, array( 'per_page', 'pagination', 'pagination_type' ) ) ) {
749 - $attributes[ $field_name ] = sanitize_text_field( $atts[ $field_name ] );
750 - }
968 + if ( $excut < 0 ) {
969 + $text = mb_substr( $subex, 0, $excut );
970 + } else {
971 + $text = $subex;
751 972 }
752 973
753 - $source_type = sanitize_text_field( $atts['type'] );
754 -
755 - $attributes = array_merge(
756 - $attributes,
757 - array(
758 - 'type' => $source_type,
759 - 'id' => sanitize_text_field( $atts[ $source_type ] ),
760 - 'order' => sanitize_text_field( $atts['order'] ), // works only when type=search
761 - 'per_page' => (int) $atts['per_page'],
762 - 'cache' => (int) $atts['cache'],
763 - 'num_pages' => 1,
764 - 'paged' => ! empty( $atts['paged'] ) ? (int) $atts['paged'] : 1,
765 - 'next_page_token' => ! empty( $atts['next_page_token'] ) ? sanitize_text_field( $atts['next_page_token'] ) : '',
766 - 'prev_page_token' => ! empty( $atts['prev_page_token'] ) ? sanitize_text_field( $atts['prev_page_token'] ) : '',
767 - 'player_description' => (int) $atts['player_description']
768 - )
769 - );
974 + $text .= $append;
975 + }
770 976
771 - // Find total number of pages
772 - $videos_found = ! empty( $atts['videos_found'] ) ? (int) $atts['videos_found'] : 0;
977 + return apply_filters( 'ayg_trim_words', $text, $original_text, $num_characters, $append );
978 +}
773 979
774 - if ( $videos_found > 0 ) {
775 - if ( 'search' == $source_type ) {
776 - $limit = min( (int) $atts['limit'], $videos_found );
777 - $attributes['num_pages'] = ceil( $limit / $attributes['per_page'] );
778 - } else {
779 - $attributes['num_pages'] = ceil( $videos_found / $attributes['per_page'] );
780 - }
781 - }
782 -
783 - // Process output
784 - if ( $attributes['num_pages'] > 1 ) {
785 - $pagination_type = ( 'pager' == $atts['pagination_type'] ) ? 'pager' : 'loadmore';
786 - include ayg_get_template( AYG_DIR . 'public/templates/pagination-' . $pagination_type. '.php', $attributes['theme'] );
787 - }
788 - }
980 +/**
981 + * Gallery HTML output.
982 + *
983 + * @since 1.0.0
984 + * @param array $video YouTube video object.
985 + * @param array $attributes Array of user attributes.
986 + */
987 +function the_ayg_gallery_thumbnail( $video, $attributes ) {
988 + include ayg_get_template( AYG_DIR . 'public/templates/thumbnail.php' );
789 989 }
790 990
791 991 /**
792 - * Player HTML output.
992 + * Pagination HTML output.
793 993 *
794 994 * @since 1.0.0
795 - * @param stdClass $video YouTube video object.
796 - * @param array $attributes Array of user attributes.
995 + * @param array $attributes Array of user attributes.
797 996 */
798 -function the_ayg_player( $video, $attributes ) {
799 - include ayg_get_template( AYG_DIR . 'public/templates/player.php', $attributes['theme'] );
800 -}
997 +function the_ayg_pagination( $attributes ) {
998 + if ( ! empty( $attributes['pagination'] ) ) {
999 + include ayg_get_template( AYG_DIR . 'public/templates/pagination.php' );
1000 + }
1001 +}