PluginProbe
Automatic YouTube Gallery – Embed Auto-Updating YouTube Video Galleries, Feeds, Playlists & Channels / 2.6.3
Automatic YouTube Gallery – Embed Auto-Updating YouTube Video Galleries, Feeds, Playlists & Channels v2.6.3
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 +638 -54 2.0.02.6.3 View file →
@@ -21,21 +21,35 @@
21 21 * @param array $args An array of gallery options.
22 22 * @return mixed
23 23 */
24 24 function ayg_build_gallery( $args ) {
25 + $general_settings = get_option( 'ayg_general_settings' );
26 + $strings_settings = get_option( 'ayg_strings_settings' );
27 +
28 + global $post;
29 +
25 30 // Vars
26 - $fields = ayg_get_editor_fields();
31 + $fields = ayg_get_editor_fields();
32 + $excluded_fields = array( 'popup' ); // Fields not part of attributes
27 33 $defaults = array();
28 34
29 35 foreach ( $fields as $key => $value ) {
30 36 foreach ( $value['fields'] as $field ) {
37 + if ( in_array( $field['name'], $excluded_fields ) ) {
38 + continue;
39 + }
40 +
31 41 $defaults[ $field['name'] ] = $field['value'];
32 42 }
33 43 }
34 44
35 - $attributes = shortcode_atts( $defaults, $args );
45 + $defaults = array_merge( $defaults, (array) $strings_settings );
46 + $attributes = shortcode_atts( $defaults, $args, 'automatic_youtube_gallery' );
36 47
37 - $attributes['uid'] = ayg_get_uniqid();
48 + $attributes['post_id'] = 0;
49 + if ( isset( $post->ID ) ) {
50 + $attributes['post_id'] = (int) $post->ID;
51 + }
38 52
39 53 $attributes['columns'] = min( 12, (int) $attributes['columns'] );
40 54 if ( empty( $attributes['columns'] ) ) {
41 55 $attributes['columns'] = 3;
@@ -55,13 +69,36 @@
55 69 if ( 'livestream' == $source_type ) {
56 70 $attributes['livestream'] = $attributes['channel'];
57 71 }
58 72
73 + $attributes['lazyload'] = 0;
74 + if ( ! empty( $general_settings['lazyload'] ) ) {
75 + $attributes['lazyload'] = 1;
76 + }
77 +
78 + $source_url = sanitize_text_field( $attributes[ $source_type ] );
79 +
80 + if ( isset( $args['uid'] ) && ! empty( $args['uid'] ) ) {
81 + $attributes['uid'] = sanitize_text_field( $args['uid'] );
82 + } else {
83 + $attributes['uid'] = md5( $source_type . $source_url );
84 + }
85 +
86 + $attributes['uid'] = apply_filters( 'ayg_gallery_id', $attributes['uid'], $args );
87 +
88 + // Deprecated since v2.5.8. Retained for backward compatibility.
89 + $deprecated_uid = md5( $source_type . $source_url . sanitize_text_field( $attributes['theme'] ) ); // Deprecated
90 + if ( isset( $args['deprecated_uid'] ) && ! empty( $args['deprecated_uid'] ) ) {
91 + $deprecated_uid = sanitize_text_field( $args['deprecated_uid'] );
92 + }
93 +
59 94 // Get Videos
60 95 $api_params = array(
96 + 'uid' => $attributes['uid'],
61 97 'type' => $source_type,
62 - 'src' => sanitize_text_field( $attributes[ $source_type ] ),
63 - 'order' => sanitize_text_field( $attributes['order'] ), // applicable only when type=search
98 + 'src' => $source_url,
99 + 'order' => sanitize_text_field( $attributes['order'] ), // Works only when type = "search".
100 + 'limit' => $attributes['limit'], // Works only when type = "search".
64 101 'maxResults' => $attributes['per_page'],
65 102 'cache' => (int) $attributes['cache']
66 103 );
67 104
@@ -71,17 +108,45 @@
71 108 $response = $youtube_api->query( $api_params );
72 109
73 110 // Process output
74 111 if ( ! isset( $response->error ) ) {
75 - // Enqueue dependencies
76 - wp_enqueue_style( AYG_SLUG . '-public' );
77 - wp_enqueue_script( AYG_SLUG . '-public' );
112 + // Store Gallery ID
113 + if ( $attributes['post_id'] > 0 && isset( $attributes['deeplinking'] ) && 1 == $attributes['deeplinking'] ) {
114 + $pages = get_option( 'ayg_gallery_page_ids', array() );
115 + $page_id = $attributes['post_id'];
116 +
117 + if ( ! in_array( $page_id, $pages ) ) {
118 + $pages[] = $page_id;
119 + update_option( 'ayg_gallery_page_ids', $pages );
120 + }
121 + }
78 122
79 123 // Gallery
80 - $videos = array();
124 + $videos = array();
125 +
126 + $gallery_id_from_url = get_query_var( 'ayg_gallery_id' );
127 + $video_id_from_url = get_query_var( 'ayg_video_id' );
128 +
129 + if ( $attributes['uid'] == $gallery_id_from_url || $deprecated_uid == $gallery_id_from_url ) {
130 + $video = ayg_db_get_video( $video_id_from_url );
131 +
132 + if ( $video ) {
133 + $videos[] = $video;
134 + } else {
135 + $video_id_from_url = '';
136 + }
137 + }
81 138
82 139 if ( isset( $response->videos ) ) {
83 - $videos = $response->videos;
140 + if ( ! empty( $video_id_from_url ) ) {
141 + foreach ( $response->videos as $video ) {
142 + if ( $video->id != $video_id_from_url ) {
143 + $videos[] = $video;
144 + }
145 + }
146 + } else {
147 + $videos = $response->videos;
148 + }
84 149 }
85 150
86 151 // Pagination
87 152 if ( isset( $response->page_info ) ) {
@@ -100,18 +165,301 @@
100 165 $theme = 'single';
101 166 }
102 167 }
103 168
169 + // Enqueue dependencies
170 + wp_enqueue_style( AYG_SLUG . '-public' );
171 +
172 + wp_enqueue_script( AYG_SLUG . '-public' );
173 + if ( $attributes['theme'] == $theme && 'classic' == $attributes['theme'] ) {
174 + wp_enqueue_script( AYG_SLUG . '-theme-classic' );
175 + }
176 +
104 177 // Output
105 178 ob_start();
106 179 include ayg_get_template( AYG_DIR . "public/templates/theme-{$theme}.php", $attributes['theme'] );
107 180 return ob_get_clean();
108 181 } else {
109 - return '<p class="ayg-error">' . $response->error_message . '</p>';
182 + return sprintf( '<div class="ayg ayg-error">%s</div>', wp_kses_post( $response->error_message ) );
110 183 }
111 184 }
112 185
113 186 /**
187 + * Combine video attributes as a string.
188 + *
189 + * @since 2.5.0
190 + * @param array $atts Array of video attributes.
191 + * @param string Combined attributes string.
192 + */
193 +function ayg_combine_video_attributes( $atts ) {
194 + $attributes = array();
195 +
196 + foreach ( $atts as $key => $value ) {
197 + if ( '' === $value ) {
198 + $attributes[] = $key;
199 + } else {
200 + $attributes[] = sprintf( '%s="%s"', $key, $value );
201 + }
202 + }
203 +
204 + return implode( ' ', $attributes );
205 +}
206 +
207 +/**
208 + * Create custom database tables
209 + *
210 + * @since 2.1.0
211 + */
212 +function ayg_db_create_custom_tables() {
213 + global $wpdb;
214 +
215 + require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
216 + $charset_collate = $wpdb->get_charset_collate();
217 +
218 + $videos_table = $wpdb->prefix . 'ayg_videos';
219 +
220 + // Check if the videos table exists
221 + $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $videos_table ) );
222 +
223 + if ( $wpdb->get_var( $query ) === $videos_table ) {
224 + // Find and remove duplicate video IDs
225 + $wpdb->query(
226 + "DELETE v1 FROM $videos_table v1
227 + INNER JOIN $videos_table v2
228 + ON v1.id = v2.id AND v1.NUM > v2.NUM"
229 + );
230 + }
231 +
232 + // Create the videos table
233 + $sql = "CREATE TABLE $videos_table (
234 + NUM bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
235 + id varchar(100) NOT NULL,
236 + title text NOT NULL,
237 + description text NOT NULL,
238 + thumbnails text NOT NULL,
239 + duration varchar(25) NOT NULL,
240 + status varchar(100) NOT NULL,
241 + published_at varchar(100) NOT NULL,
242 + published_at_datetime datetime NULL,
243 + PRIMARY KEY (NUM),
244 + UNIQUE KEY ayg_unique_video_id (id)
245 + ) $charset_collate;";
246 +
247 + dbDelta( $sql );
248 +
249 + // Add UNIQUE KEY if it is not added
250 + $existing_keys = $wpdb->get_results( "SHOW KEYS FROM $videos_table WHERE Key_name = 'ayg_unique_video_id'" );
251 +
252 + if ( empty( $existing_keys ) ) {
253 + $wpdb->query( "ALTER TABLE $videos_table ADD UNIQUE KEY ayg_unique_video_id (id)" );
254 + }
255 +
256 + // Create the galleries table
257 + $galleries_table = $wpdb->prefix . 'ayg_galleries';
258 +
259 + $sql = "CREATE TABLE $galleries_table (
260 + NUM bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
261 + video_id varchar(100) NOT NULL,
262 + gallery_id varchar(100) NOT NULL,
263 + PRIMARY KEY (NUM),
264 + UNIQUE KEY ayg_unique_video_gallery (video_id, gallery_id),
265 + INDEX ayg_idx_gallery_id (gallery_id)
266 + ) $charset_collate;";
267 +
268 + dbDelta( $sql );
269 +}
270 +
271 +/**
272 + * Store videos in our custom database table "{$wpdb->prefix}ayg_videos"
273 + *
274 + * @since 2.1.0
275 + * @param object $data YouTube API response object.
276 + * @param array $attributes Array of user attributes.
277 + */
278 +function ayg_db_store_videos( $data, $attributes = array() ) {
279 + if ( AYG_VERSION !== get_option( 'ayg_version' ) ) {
280 + return false;
281 + }
282 +
283 + if ( isset( $data->kind ) && 'youtube#channelListResponse' == $data->kind ) {
284 + return false;
285 + }
286 +
287 + if ( empty( $data->items ) || ! is_array( $data->items ) ) {
288 + return false;
289 + }
290 +
291 + global $wpdb;
292 +
293 + $items = $data->items;
294 +
295 + // Store Videos
296 + foreach ( $items as $item ) {
297 + $row = array();
298 +
299 + // Video ID
300 + $row['id'] = '';
301 +
302 + if ( isset( $item->snippet->resourceId ) && isset( $item->snippet->resourceId->videoId ) ) {
303 + $row['id'] = $item->snippet->resourceId->videoId;
304 + } elseif ( isset( $item->contentDetails ) && isset( $item->contentDetails->videoId ) ) {
305 + $row['id'] = $item->contentDetails->videoId;
306 + } elseif ( isset( $item->id ) && isset( $item->id->videoId ) ) {
307 + $row['id'] = $item->id->videoId;
308 + } elseif ( isset( $item->id ) ) {
309 + $row['id'] = $item->id;
310 + }
311 +
312 + if ( empty( $row['id'] ) ) {
313 + continue;
314 + }
315 +
316 + // Video title
317 + $row['title'] = $item->snippet->title;
318 +
319 + // Video description
320 + $row['description'] = $item->snippet->description;
321 +
322 + // Video thumbnails
323 + $row['thumbnails'] = '';
324 + if ( isset( $item->snippet->thumbnails ) ) {
325 + $row['thumbnails'] = serialize( $item->snippet->thumbnails );
326 + }
327 +
328 + // Video duration
329 + $row['duration'] = '';
330 + if ( isset( $item->contentDetails ) && isset( $item->contentDetails->duration ) ) {
331 + $row['duration'] = $item->contentDetails->duration;
332 + }
333 +
334 + // Video status
335 + $row['status'] = 'private';
336 +
337 + if ( isset( $item->status ) && ( 'public' == $item->status->privacyStatus || 'unlisted' == $item->status->privacyStatus ) ) {
338 + $row['status'] = 'public';
339 + }
340 +
341 + if ( isset( $item->snippet->status ) && ( 'public' == $item->snippet->status->privacyStatus || 'unlisted' == $item->snippet->status->privacyStatus ) ) {
342 + $row['status'] = 'public';
343 + }
344 +
345 + if ( 'youtube#searchResult' == $item->kind ) {
346 + $row['status'] = 'public';
347 + }
348 +
349 + // Video publish date
350 + $row['published_at'] = $item->snippet->publishedAt;
351 +
352 + $datetime = new DateTime( $item->snippet->publishedAt );
353 + $row['published_at_datetime'] = date_format( $datetime, 'Y-m-d H:i:s' );
354 +
355 + // Store the video
356 + $videos_table = $wpdb->prefix . 'ayg_videos';
357 +
358 + $query = $wpdb->prepare(
359 + "INSERT INTO $videos_table (id, title, description, thumbnails, duration, status, published_at, published_at_datetime)
360 + VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
361 + ON DUPLICATE KEY UPDATE
362 + title = VALUES(title),
363 + description = VALUES(description),
364 + thumbnails = VALUES(thumbnails),
365 + duration = VALUES(duration),
366 + status = VALUES(status),
367 + published_at = VALUES(published_at),
368 + published_at_datetime = VALUES(published_at_datetime)",
369 + $row['id'],
370 + $row['title'],
371 + $row['description'],
372 + $row['thumbnails'],
373 + $row['duration'],
374 + $row['status'],
375 + $row['published_at'],
376 + $row['published_at_datetime']
377 + );
378 +
379 + $wpdb->query( $query );
380 +
381 + // Store the gallery association
382 + $gallery_id = isset( $attributes['uid'] ) ? $attributes['uid'] : '';
383 + $source_type = isset( $attributes['type'] ) ? $attributes['type'] : 'videos';
384 +
385 + if ( ! empty( $gallery_id ) && ! in_array( $source_type, array( 'video', 'livestream' ) ) ) {
386 + $galleries_table = $wpdb->prefix . 'ayg_galleries';
387 +
388 + $query = $wpdb->prepare(
389 + "INSERT IGNORE INTO $galleries_table (video_id, gallery_id) VALUES (%s, %s)",
390 + $row['id'],
391 + $gallery_id
392 + );
393 +
394 + $wpdb->query( $query );
395 + }
396 + }
397 +}
398 +
399 +/**
400 + * Get a single video record from our custom database table "{$wpdb->prefix}ayg_videos"
401 + *
402 + * @since 2.1.0
403 + * @param string $video_id YouTube Video ID.
404 + * @return mixed
405 + */
406 +function ayg_db_get_video( $video_id ) {
407 + global $wpdb;
408 +
409 + $cache_key = 'ayg_'. $video_id;
410 + $row = wp_cache_get( $cache_key );
411 +
412 + if ( false === $row ) {
413 + $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}ayg_videos WHERE id = %s", $video_id );
414 + $row = $wpdb->get_row( $query );
415 +
416 + if ( $row ) {
417 + if ( ! empty( $row->thumbnails ) ) {
418 + $row->thumbnails = unserialize( $row->thumbnails );
419 + }
420 +
421 + wp_cache_set( $cache_key, $row );
422 + }
423 + }
424 +
425 + return $row;
426 +}
427 +
428 +/**
429 + * Dump our plugin transients.
430 + *
431 + * @since 2.1.0
432 + */
433 +function ayg_delete_cache() {
434 + delete_option( 'ayg_gallery_page_ids' );
435 +
436 + // Get the current list of transients
437 + $transient_keys = get_option( 'ayg_transient_keys', array() );
438 +
439 + // For each key, delete that transient
440 + foreach ( $transient_keys as $key ) {
441 + delete_transient( $key );
442 + }
443 +
444 + // Reset our DB value
445 + update_option( 'ayg_transient_keys', array() );
446 +}
447 +
448 +/**
449 + * Get current address bar URL.
450 + *
451 + * @since 2.1.0
452 + * @return string Current Page URL.
453 + */
454 +function ayg_get_current_url() {
455 + global $wp;
456 + $current_url = home_url( add_query_arg( array(), $wp->request ) );
457 +
458 + return $current_url;
459 +}
460 +
461 +/**
114 462 * Get default plugin settings.
115 463 *
116 464 * @since 1.6.4
117 465 * @return array $defaults Array of plugin settings.
@@ -119,43 +467,58 @@
119 467 function ayg_get_default_settings() {
120 468 $defaults = array(
121 469 'ayg_general_settings' => array(
122 470 'api_key' => '',
123 - 'development_mode' => 1
471 + 'lazyload' => 0,
472 + 'development_mode' => 0
124 473 ),
474 + 'ayg_strings_settings' => array(
475 + 'more_button_label' => __( 'Load More', 'automatic-youtube-gallery' ),
476 + 'previous_button_label' => __( 'Previous', 'automatic-youtube-gallery' ),
477 + 'next_button_label' => __( 'Next', 'automatic-youtube-gallery' ),
478 + 'show_more_label' => __( 'Show More', 'automatic-youtube-gallery' ),
479 + 'show_less_label' => __( 'Show Less', 'automatic-youtube-gallery' )
480 + ),
125 481 'ayg_gallery_settings' => array(
126 - 'theme' => 'classic',
127 - 'columns' => 3,
128 - 'per_page' => 12,
129 - 'thumb_ratio' => 56.25,
130 - 'thumb_title' => 1,
131 - 'thumb_title_length' => 0,
132 - 'thumb_excerpt' => 1,
133 - 'thumb_excerpt_length' => 75,
134 - 'pagination' => 1,
135 - 'pagination_type' => 'more'
482 + 'theme' => 'classic',
483 + 'columns' => 3,
484 + 'per_page' => 12,
485 + 'thumb_ratio' => 56.25,
486 + 'thumb_title' => 1,
487 + 'thumb_title_length' => 0,
488 + 'thumb_excerpt' => 1,
489 + 'thumb_excerpt_length' => 75,
490 + 'pagination' => 1,
491 + 'pagination_type' => 'more',
492 + 'scroll_top_offset' => 10
136 493 ),
137 494 'ayg_player_settings' => array(
138 - 'player_ratio' => 56.25,
139 - 'player_title' => 1,
140 - 'player_description' => 1,
141 - 'autoplay' => 0,
142 - 'autoadvance' => 1,
143 - 'loop' => 0,
144 - 'controls' => 1,
145 - 'modestbranding' => 1,
146 - 'cc_load_policy' => 0,
147 - 'iv_load_policy' => 0,
148 - 'hl' => '',
149 - 'cc_lang_pref' => ''
495 + 'player_type' => 'youtube',
496 + 'player_color' => '#00b3ff',
497 + 'player_width' => '',
498 + 'player_ratio' => 56.25,
499 + 'player_title' => 1,
500 + 'player_description' => 1,
501 + 'autoplay' => 0,
502 + 'autoadvance' => 1,
503 + 'loop' => 0,
504 + 'muted' => 0,
505 + 'controls' => 1,
506 + 'modestbranding' => 1,
507 + 'cc_load_policy' => 0,
508 + 'iv_load_policy' => 0,
509 + 'hl' => '',
510 + 'cc_lang_pref' => '',
511 + 'privacy_enhanced_mode' => 0,
512 + 'origin' => 0
150 513 ),
151 514 'ayg_livestream_settings' => array(
152 515 'fallback_message' => __( 'Sorry, but the channel is not currently streaming live content. Please check back later.', 'automatic-youtube-gallery' )
153 516 ),
154 - 'ayg_privacy_settings' => array(
155 - 'cookie_consent' => 0,
156 - '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' ),
157 - 'button_label' => __( 'Accept', 'automatic-youtube-gallery' )
517 + 'ayg_privacy_settings' => array(
518 + 'cookie_consent' => 0,
519 + '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' ),
520 + 'button_label' => __( 'Accept', 'automatic-youtube-gallery' )
158 521 )
159 522 );
160 523
161 524 return $defaults;
@@ -268,14 +631,15 @@
268 631 'label' => __( 'Cache Duration', 'automatic-youtube-gallery' ),
269 632 'description' => __( 'Specifies how frequently we should check your YouTube source for new videos/updates.', 'automatic-youtube-gallery' ),
270 633 'type' => 'select',
271 634 'options' => array(
272 - '900' => __( '15 minutes', 'automatic-youtube-gallery' ),
273 - '1800' => __( '30 minutes', 'automatic-youtube-gallery' ),
635 + '0' => '— '. __( 'No Caching', 'automatic-youtube-gallery' ) . ' —',
636 + '900' => __( '15 Minutes', 'automatic-youtube-gallery' ),
637 + '1800' => __( '30 Minutes', 'automatic-youtube-gallery' ),
274 638 '3600' => __( '1 Hour', 'automatic-youtube-gallery' ),
275 639 '86400' => __( '1 Day', 'automatic-youtube-gallery' ),
276 640 '604800' => __( '1 Week', 'automatic-youtube-gallery' ),
277 - '2419200' => __( ' 1Month', 'automatic-youtube-gallery' )
641 + '2419200' => __( '1 Month', 'automatic-youtube-gallery' )
278 642 ),
279 643 'value' => 86400,
280 644 'sanitize_callback' => 'intval'
281 645 )
@@ -287,8 +651,24 @@
287 651 ),
288 652 'player' => array(
289 653 'label' => __( 'Player (optional)', 'automatic-youtube-gallery' ),
290 654 'fields' => ayg_get_player_settings_fields()
655 + ),
656 + 'search' => array(
657 + 'label' => __( 'Search Form (optional)', 'automatic-youtube-gallery' ),
658 + 'fields' => array(
659 + array(
660 + 'name' => 'search_form',
661 + 'label' => __( 'Search Form', 'automatic-youtube-gallery' ),
662 + 'description' => sprintf(
663 + __( 'Check this option to enable the search form. Having issues? <a href="%s" target="_blank" rel="noopener noreferrer">Check here</a>.', 'automatic-youtube-gallery' ),
664 + 'https://plugins360.com/automatic-youtube-gallery/searchform/'
665 + ),
666 + 'type' => 'checkbox',
667 + 'value' => 0,
668 + 'sanitize_callback' => 'intval'
669 + )
670 + )
291 671 )
292 672 );
293 673
294 674 return apply_filters( 'ayg_editor_fields', $fields );
@@ -306,9 +686,9 @@
306 686 $fields = array(
307 687 array(
308 688 'name' => 'theme',
309 689 'label' => __( 'Select Theme (Layout)', 'automatic-youtube-gallery' ),
310 - 'description' => ( ayg_fs()->is_not_paying() ? sprintf( __( '<a href="%s">Upgrade Pro</a> for more themes (Inline, Popup, Slider, Playlist).', 'automatic-youtube-gallery' ), esc_url( ayg_fs()->get_upgrade_url() ) ) : '' ),
690 + '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() ) ) : '' ),
311 691 'type' => 'select',
312 692 'options' => array(
313 693 'classic' => __( 'Classic', 'automatic-youtube-gallery' )
314 694 ),
@@ -412,26 +792,28 @@
412 792 * Get video description to show on top of the player.
413 793 *
414 794 * @since 1.0.0
415 795 * @param stdClass $video YouTube video object.
796 + * @param array $attributes Array of user attributes.
416 797 * @param int $words_count Number of words to show by default.
417 798 * @return string Video description.
418 799 */
419 -function ayg_get_player_description( $video, $words_count = 30 ) {
800 +function ayg_get_player_description( $video, $attributes = array(), $words_count = 30 ) {
420 801 $description = $video->description;
421 802
422 803 $words_array = explode( ' ', strip_tags( $description ) );
423 804 if ( count( $words_array ) > $words_count ) {
805 + $show_more_label = ! empty( $attributes['show_more_label'] ) ? $attributes['show_more_label'] : __( 'Show More', 'automatic-youtube-gallery' );
424 806 $words_array[ $words_count ] = '<span class="ayg-player-description-dots">...</span></span><span class="ayg-player-description-more">' . $words_array[ $words_count ];
425 807
426 808 $description = '<span class="ayg-player-description-less">' . implode( ' ', $words_array ) . '</span>';
427 - $description .= '<a href="javascript:void(0);" class="ayg-player-description-toggle-btn">[+] ' . __( 'Show More', 'automatic-youtube-gallery' ) . '</a>';
809 + $description .= '<a href="#" class="ayg-player-description-toggle-btn">' . esc_html( $show_more_label ) . '</a>';
428 810 }
429 811
430 812 $description = nl2br( $description );
431 813 $description = make_clickable( $description );
432 814
433 - return apply_filters( 'ayg_player_description', $description, $video, $words_count );
815 + return apply_filters( 'ayg_player_description', $description, $video, $attributes, $words_count );
434 816 }
435 817
436 818 /**
437 819 * Get player settings fields.
@@ -443,8 +825,16 @@
443 825 $player_settings = get_option( 'ayg_player_settings' );
444 826
445 827 $fields = array(
446 828 array(
829 + 'name' => 'player_width',
830 + 'label' => __( 'Player Width', 'automatic-youtube-gallery' ),
831 + 'description' => __( 'In pixels. Maximum width of the player. Leave this field empty to scale 100% of its enclosing container/html element.', 'automatic-youtube-gallery' ),
832 + 'type' => 'text',
833 + 'value' => isset( $player_settings['player_width'] ) ? $player_settings['player_width'] : '',
834 + 'sanitize_callback' => 'ayg_sanitize_int'
835 + ),
836 + array(
447 837 'name' => 'player_ratio',
448 838 'label' => __( 'Player Height (Ratio)', 'automatic-youtube-gallery' ),
449 839 'description' => __( 'Select the ratio value used to calculate the player height.', 'automatic-youtube-gallery' ),
450 840 'type' => 'radio',
@@ -493,10 +883,18 @@
493 883 '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' ),
494 884 'type' => 'checkbox',
495 885 'value' => $player_settings['loop'],
496 886 'sanitize_callback' => 'intval'
497 - ),
887 + ),
498 888 array(
889 + 'name' => 'muted',
890 + 'label' => __( 'Muted', 'automatic-youtube-gallery' ),
891 + 'description' => __( 'Check this option to turn OFF the audio output of the video by default.', 'automatic-youtube-gallery' ),
892 + 'type' => 'checkbox',
893 + 'value' => isset( $player_settings['muted'] ) ? $player_settings['muted'] : 0,
894 + 'sanitize_callback' => 'intval'
895 + ),
896 + array(
499 897 'name' => 'controls',
500 898 'label' => __( 'Show Player Controls', 'automatic-youtube-gallery' ),
501 899 'description' => __( 'Uncheck this option to hide the video player controls.', 'automatic-youtube-gallery' ),
502 900 'type' => 'checkbox',
@@ -553,9 +951,22 @@
553 951
554 952 return $fields;
555 953 }
556 954
955 +
557 956 /**
957 + * Get a single video page URL.
958 + *
959 + * @since 2.1.0
960 + * @param stdClass $video YouTube video object.
961 + * @param array $args An array of gallery options.
962 + * @return string Single video URL.
963 + */
964 +function ayg_get_single_video_url( $video, $attributes ) {
965 + return apply_filters( 'ayg_single_video_url', '', $video, $attributes );
966 +}
967 +
968 +/**
558 969 * Get filtered php template file path.
559 970 *
560 971 * @since 1.0.0
561 972 * @param array $template PHP file path.
@@ -582,8 +993,157 @@
582 993 return uniqid() . ++$ayg_uniqid;
583 994 }
584 995
585 996 /**
997 + * Get YouTube domain.
998 + *
999 + * @since 2.3.0
1000 + * @return string YouTube embed domain.
1001 + */
1002 +function ayg_get_youtube_domain() {
1003 + $player_settings = get_option( 'ayg_player_settings' );
1004 +
1005 + $domain = 'https://www.youtube.com';
1006 + if ( isset( $player_settings['privacy_enhanced_mode'] ) && ! empty( $player_settings['privacy_enhanced_mode'] ) ) {
1007 + $domain = 'https://www.youtube-nocookie.com';
1008 + }
1009 +
1010 + return $domain;
1011 +}
1012 +
1013 +/**
1014 + * Get the YouTube embed URL.
1015 + *
1016 + * @since 2.5.0
1017 + * @param string $video_id YouTube video ID.
1018 + * @param array $attributes Array of user attributes.
1019 + * @return string Player embed URL.
1020 + */
1021 +function ayg_get_youtube_embed_url( $video_id, $attributes = array() ) {
1022 + $player_settings = get_option( 'ayg_player_settings' );
1023 +
1024 + $player_website = 'https://www.youtube.com';
1025 + if ( isset( $player_settings['privacy_enhanced_mode'] ) && ! empty( $player_settings['privacy_enhanced_mode'] ) ) {
1026 + $player_website = 'https://www.youtube-nocookie.com';
1027 + }
1028 +
1029 + if ( empty( $video_id ) ) {
1030 + return '';
1031 + }
1032 +
1033 + $url = $player_website . '/embed/' . $video_id . '?enablejsapi=1&playsinline=1&rel=0';
1034 +
1035 + if ( isset( $player_settings['origin'] ) && ! empty( $player_settings['origin'] ) ) {
1036 + $site_url_parts = parse_url( site_url() );
1037 + $origin = $site_url_parts['scheme'] . '://' . $site_url_parts['host'];
1038 +
1039 + $url = add_query_arg( 'origin', $origin, $url );
1040 + }
1041 +
1042 + if ( ! is_array( $attributes ) ) {
1043 + $attributes = (array) $attributes;
1044 + }
1045 +
1046 + $autoplay = isset( $attributes['autoplay'] ) ? (int) $attributes['autoplay'] : 0;
1047 + if ( 1 == $autoplay ) {
1048 + $url = add_query_arg( 'autoplay', 1, $url );
1049 + }
1050 +
1051 + $loop = isset( $attributes['loop'] ) ? (int) $attributes['loop'] : 0;
1052 + if ( 1 == $loop ) {
1053 + $url = add_query_arg( 'playlist', $video_id, $url );
1054 + $url = add_query_arg( 'loop', 1, $url );
1055 + }
1056 +
1057 + $muted = isset( $attributes['muted'] ) ? (int) $attributes['muted'] : 0;
1058 + if ( 1 == $muted ) {
1059 + $url = add_query_arg( 'mute', 1, $url );
1060 + }
1061 +
1062 + $controls = isset( $attributes['controls'] ) ? (int) $attributes['controls'] : 1;
1063 + if ( 0 == $controls ) {
1064 + $url = add_query_arg( 'controls', 0, $url );
1065 + }
1066 +
1067 + $modestbranding = isset( $attributes['modestbranding'] ) ? (int) $attributes['modestbranding'] : 0;
1068 + if ( 1 == $modestbranding ) {
1069 + $url = add_query_arg( 'modestbranding', 1, $url );
1070 + }
1071 +
1072 + $cc_load_policy = isset( $attributes['cc_load_policy'] ) ? (int) $attributes['cc_load_policy'] : 0;
1073 + if ( 1 == $cc_load_policy ) {
1074 + $url = add_query_arg( 'cc_load_policy', 1, $url );
1075 + }
1076 +
1077 + $iv_load_policy = isset( $attributes['iv_load_policy'] ) ? (int) $attributes['iv_load_policy'] : 0;
1078 + if ( 0 == $iv_load_policy ) {
1079 + $url = add_query_arg( 'iv_load_policy', 3, $url );
1080 + }
1081 +
1082 + if ( isset( $attributes['hl'] ) && ! empty( $attributes['hl'] ) ) {
1083 + $url = add_query_arg( 'hl', sanitize_text_field( $attributes['hl'] ), $url );
1084 + }
1085 +
1086 + if ( isset( $attributes['cc_lang_pref'] ) && ! empty( $attributes['cc_lang_pref'] ) ) {
1087 + $url = add_query_arg( 'cc_lang_pref', sanitize_text_field( $attributes['cc_lang_pref'] ), $url );
1088 + }
1089 +
1090 + return apply_filters( 'ayg_youtube_embed_url', $url, $video_id, $attributes );
1091 +}
1092 +
1093 +/**
1094 + * Inserts a new associative array after another associative array key.
1095 + *
1096 + * @since 2.1.0
1097 + * @param string $key The associative array key to insert after.
1098 + * @param array $array An array to insert in to.
1099 + * @param array $new_array An array to insert.
1100 + * @return array Updated array.
1101 + */
1102 +function ayg_insert_array_after( $key, $array, $new_array ) {
1103 + if ( array_key_exists( $key, $array ) ) {
1104 + $new = array();
1105 +
1106 + foreach ( $array as $k => $value ) {
1107 + $new[ $k ] = $value;
1108 +
1109 + if ( $k === $key ) {
1110 + foreach ( $new_array as $new_key => $new_value ) {
1111 + $new[ $new_key ] = $new_value;
1112 + }
1113 + }
1114 + }
1115 +
1116 + return $new;
1117 + }
1118 +
1119 + return $array;
1120 +}
1121 +
1122 +/**
1123 + * Detect if the client is using an iOS device (iPhone, iPad, or iPod).
1124 + *
1125 + * @return bool True if the user agent string suggests an iOS device, false otherwise.
1126 + */
1127 +function ayg_is_ios() {
1128 + if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
1129 + return false;
1130 + }
1131 +
1132 + $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1133 +
1134 + if (
1135 + strpos( $ua, 'iphone' ) !== false ||
1136 + strpos( $ua, 'ipad' ) !== false ||
1137 + strpos( $ua, 'ipod' ) !== false
1138 + ) {
1139 + return true;
1140 + }
1141 +
1142 + return false;
1143 +}
1144 +
1145 +/**
586 1146 * Sanitize the integer inputs, accepts empty values.
587 1147 *
588 1148 * @since 1.0.0
589 1149 * @param string|int $value Input value.
@@ -599,11 +1159,12 @@
599 1159 *
600 1160 * @since 2.0.0
601 1161 * @param string $text Text to trim.
602 1162 * @param int $num_characters Number of characters.
1163 + * @param string $append String to append to the end of the excerpt.
603 1164 * @return string Trimmed text.
604 1165 */
605 -function ayg_trim_words( $text, $num_characters ) {
1166 +function ayg_trim_words( $text, $num_characters, $append = '...' ) {
606 1167 $num_characters++;
607 1168
608 1169 $original_text = $text;
609 1170 $text = ( $num_characters > 1 ) ? wp_strip_all_tags( $original_text, true ) : nl2br( $original_text );
@@ -618,20 +1179,20 @@
618 1179 } else {
619 1180 $text = $subex;
620 1181 }
621 1182
622 - $text .= '...';
1183 + $text .= $append;
623 1184 }
624 1185
625 - return apply_filters( 'ayg_trim_words', $text, $original_text, $num_characters );
1186 + return apply_filters( 'ayg_trim_words', $text, $original_text, $num_characters, $append );
626 1187 }
627 1188
628 1189 /**
629 1190 * Gallery HTML output.
630 1191 *
631 - * @since 1.0.0
632 - * @param array $video YouTube video object.
633 - * @param array $attributes Array of user attributes.
1192 + * @since 1.0.0
1193 + * @param array $video YouTube video object.
1194 + * @param array $attributes Array of user attributes.
634 1195 */
635 1196 function the_ayg_gallery_thumbnail( $video, $attributes ) {
636 1197 include ayg_get_template( AYG_DIR . 'public/templates/thumbnail.php' );
637 1198 }
@@ -638,12 +1199,35 @@
638 1199
639 1200 /**
640 1201 * Pagination HTML output.
641 1202 *
642 - * @since 1.0.0
643 - * @param array $attributes Array of user attributes.
1203 + * @since 1.0.0
1204 + * @param array $attributes Array of user attributes.
644 1205 */
645 1206 function the_ayg_pagination( $attributes ) {
646 1207 if ( ! empty( $attributes['pagination'] ) ) {
647 1208 include ayg_get_template( AYG_DIR . 'public/templates/pagination.php' );
648 1209 }
1210 +}
1211 +
1212 +/**
1213 + * Search Form HTML output.
1214 + *
1215 + * @since 2.5.7
1216 + * @param array $attributes Array of user attributes.
1217 + */
1218 +function the_ayg_search_form( $attributes ) {
1219 + if ( ! empty( $attributes['search_form'] ) ) {
1220 + include ayg_get_template( AYG_DIR . 'public/templates/search-form.php' );
1221 + }
1222 +}
1223 +
1224 +/**
1225 + * Gallery HTML output.
1226 + *
1227 + * @since 2.5.0
1228 + * @param array $video YouTube video object.
1229 + * @param array $attributes Array of user attributes.
1230 + */
1231 +function the_ayg_player( $video, $attributes ) {
1232 + include ayg_get_template( AYG_DIR . 'public/templates/player.php' );
649 1233 }