PluginProbe
Automatic YouTube Gallery – Embed Auto-Updating YouTube Video Galleries, Feeds, Playlists & Channels / 2.3.2
Automatic YouTube Gallery – Embed Auto-Updating YouTube Video Galleries, Feeds, Playlists & Channels v2.3.2
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 +507 -310 1.6.22.3.2 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,43 +55,99 @@
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 +
68 97 // Enqueue dependencies
69 98 wp_enqueue_style( AYG_SLUG . '-public' );
70 99 wp_enqueue_script( AYG_SLUG . '-public' );
71 100
72 101 // Gallery
73 - $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 + }
74 116
75 117 if ( isset( $response->videos ) ) {
76 - $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 + }
77 127 }
78 128
79 129 // Pagination
80 130 if ( isset( $response->page_info ) ) {
81 - $attributes = array_merge( $attributes, $response->page_info, $api_params );
131 + $attributes = array_merge( $attributes, $api_params, $response->page_info );
82 132 }
83 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 +
84 147 // Output
85 148 ob_start();
86 - 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'] );
87 150 return ob_get_clean();
88 151 } else {
89 152 return '<p class="ayg-error">' . $response->error_message . '</p>';
90 153 }
@@ -90,8 +153,260 @@
90 153 }
91 154 }
92 155
93 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 +/**
94 409 * Get editor fields.
95 410 *
96 411 * @since 1.0.0
97 412 * @return array Array of fields.
@@ -106,14 +421,15 @@
106 421 'label' => __( 'Source Type', 'automatic-youtube-gallery' ),
107 422 'description' => '',
108 423 'type' => 'select',
109 424 'options' => array(
110 - 'playlist' => __( 'Playlist', 'automatic-youtube-gallery' ),
111 - 'channel' => __( 'Channel', 'automatic-youtube-gallery' ),
112 - 'username' => __( 'Username', 'automatic-youtube-gallery' ),
113 - 'search' => __( 'Search Terms', 'automatic-youtube-gallery' ),
114 - 'videos' => __( 'Custom Videos List', 'automatic-youtube-gallery' ),
115 - 'video' => __( 'Single 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' )
116 432 ),
117 433 'value' => 'playlist',
118 434 'sanitize_callback' => 'sanitize_key'
119 435 ),
@@ -126,9 +442,9 @@
126 442 'sanitize_callback' => 'sanitize_text_field'
127 443 ),
128 444 array(
129 445 'name' => 'channel',
130 - 'label' => __( 'YouTube Channel ID (or) URL', 'automatic-youtube-gallery' ),
446 + 'label' => __( 'YouTube Channel ID (or) a YouTube Video URL from the Channel', 'automatic-youtube-gallery' ),
131 447 'description' => sprintf( '%s: https://www.youtube.com/channel/XXXXXXXXXX', __( 'Example', 'automatic-youtube-gallery' ) ),
132 448 'type' => 'url',
133 449 'value' => '',
134 450 'sanitize_callback' => 'sanitize_text_field'
@@ -142,13 +458,21 @@
142 458 'sanitize_callback' => 'sanitize_text_field'
143 459 ),
144 460 array(
145 461 'name' => 'search',
146 - 'label' => __( 'Search Terms', 'automatic-youtube-gallery' ),
462 + 'label' => __( 'Search Keywords', 'automatic-youtube-gallery' ),
147 463 'description' => sprintf( '%s: Cartoon (space:AND , -:NOT , |:OR)', __( 'Example', 'automatic-youtube-gallery' ) ),
148 464 'type' => 'text',
149 465 'value' => '',
150 466 'sanitize_callback' => 'sanitize_text_field'
467 + ),
468 + array(
469 + 'name' => 'video',
470 + 'label' => __( 'YouTube Video ID (or) URL', 'automatic-youtube-gallery' ),
471 + 'description' => sprintf( '%s: https://www.youtube.com/watch?v=XXXXXXXXXX', __( 'Example', 'automatic-youtube-gallery' ) ),
472 + 'type' => 'url',
473 + 'value' => '',
474 + 'sanitize_callback' => 'sanitize_text_field'
151 475 ),
152 476 array(
153 477 'name' => 'videos',
154 478 'label' => __( 'YouTube Video IDs (or) URLs', 'automatic-youtube-gallery' ),
@@ -156,18 +480,10 @@
156 480 'type' => 'textarea',
157 481 'placeholder' => __( 'Enter one video per line', 'automatic-youtube-gallery' ),
158 482 'value' => '',
159 483 'sanitize_callback' => 'sanitize_text_field'
160 - ),
484 + ),
161 485 array(
162 - 'name' => 'video',
163 - 'label' => __( 'YouTube Video ID (or) URL', 'automatic-youtube-gallery' ),
164 - 'description' => sprintf( '%s: https://www.youtube.com/watch?v=XXXXXXXXXX', __( 'Example', 'automatic-youtube-gallery' ) ),
165 - 'type' => 'url',
166 - 'value' => '',
167 - 'sanitize_callback' => 'sanitize_text_field'
168 - ),
169 - array(
170 486 'name' => 'order',
171 487 'label' => __( 'Order Videos by', 'automatic-youtube-gallery' ),
172 488 'description' => '',
173 489 'type' => 'select',
@@ -192,21 +508,20 @@
192 508 'sanitize_callback' => 'intval'
193 509 ),
194 510 array(
195 511 'name' => 'cache',
196 - 'label' => __( 'Refresh the data every (Cache time)', 'automatic-youtube-gallery' ),
197 - 'description' => __( 'IMPORTANT! Specifies how frequently the plugin should check your YouTube source for any new update. We recommend keeping this value as "Page load" when you test the gallery and strongly suggest to change this value as "Day" or to a greater value before pushing the gallery live.', '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' ),
198 514 'type' => 'select',
199 515 'options' => array(
200 - '0' => __( 'Page load', 'automatic-youtube-gallery' ),
201 - '900' => __( '15 minutes', 'automatic-youtube-gallery' ),
202 - '1800' => __( '30 minutes', 'automatic-youtube-gallery' ),
203 - '3600' => __( 'Hour', 'automatic-youtube-gallery' ),
204 - '86400' => __( 'Day', 'automatic-youtube-gallery' ),
205 - '604800' => __( 'Week', 'automatic-youtube-gallery' ),
206 - '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' )
207 522 ),
208 - 'value' => 0,
523 + 'value' => 86400,
209 524 'sanitize_callback' => 'intval'
210 525 )
211 526 )
212 527 ),
@@ -223,109 +538,8 @@
223 538 return apply_filters( 'ayg_editor_fields', $fields );
224 539 }
225 540
226 541 /**
227 - * Get gallery thumbnail video excerpt (short description).
228 - *
229 - * @since 1.0.0
230 - * @param stdClass $video YouTube video object.
231 - * @param array $attributes Array of user attributes.
232 - * @return string Video excerpt.
233 - */
234 -function ayg_get_gallery_thumb_excerpt( $video, $attributes ) {
235 - $char_length = (int) $attributes['thumb_excerpt_length'];
236 - $char_length++;
237 -
238 - $content = '';
239 - if ( ! empty( $attributes['thumb_excerpt'] ) ) {
240 - $content = ( $char_length > 1 ) ? wp_strip_all_tags( $video->description, true ) : nl2br( $video->description );
241 - }
242 -
243 - $excerpt = '';
244 -
245 - if ( $char_length > 1 && mb_strlen( $content ) > $char_length ) {
246 - $subex = mb_substr( $content, 0, $char_length - 5 );
247 - $exwords = explode( ' ', $subex );
248 - $excut = - ( mb_strlen( $exwords[ count( $exwords ) - 1 ] ) );
249 - if ( $excut < 0 ) {
250 - $excerpt = mb_substr( $subex, 0, $excut );
251 - } else {
252 - $excerpt = $subex;
253 - }
254 - $excerpt .= '[...]';
255 - } else {
256 - $excerpt = $content;
257 - }
258 -
259 - return apply_filters( 'ayg_gallery_thumb_excerpt', $excerpt, $video, $attributes );
260 -}
261 -
262 -/**
263 - * Get gallery thumbnail image.
264 - *
265 - * @since 1.0.0
266 - * @param stdClass $video YouTube video object.
267 - * @param array $attributes Array of user attributes.
268 - * @return string Video thumbnail image.
269 - */
270 -function ayg_get_gallery_thumb_image( $video, $attributes ) {
271 - $image = '';
272 -
273 - if ( isset( $video->thumbnails->default ) ) {
274 - $image = $video->thumbnails->default->url;
275 - }
276 -
277 - // 4:3 ( default - 120x90, high - 480x360, standard - 640x480 )
278 - if ( 75 == (int) $attributes['thumb_ratio'] ) {
279 - if ( isset( $video->thumbnails->high ) ) {
280 - $image = $video->thumbnails->high->url;
281 - }
282 - }
283 -
284 - // 16:9 ( medium - 320x180, maxres - 1280x720 )
285 - if ( 56.25 == (float) $attributes['thumb_ratio'] ) {
286 - if ( isset( $video->thumbnails->medium ) ) {
287 - $image = $video->thumbnails->medium->url;
288 - }
289 - }
290 -
291 - return apply_filters( 'ayg_gallery_thumb_image', $image, $video, $attributes );
292 -}
293 -
294 -/**
295 - * Get gallery thumbnail video title.
296 - *
297 - * @since 1.0.0
298 - * @param stdClass $video YouTube video object.
299 - * @param array $attributes Array of user attributes.
300 - * @return string Video title.
301 - */
302 -function ayg_get_gallery_thumb_title( $video, $attributes ) {
303 - $text = ! empty( $attributes['thumb_title'] ) ? $video->title : '';
304 -
305 - $char_length = (int) $attributes['thumb_title_length'];
306 - $char_length++;
307 -
308 - $title = '';
309 -
310 - if ( $char_length > 1 && mb_strlen( $text ) > $char_length ) {
311 - $subex = mb_substr( $text, 0, $char_length - 5 );
312 - $exwords = explode( ' ', $subex );
313 - $excut = - ( mb_strlen( $exwords[ count( $exwords ) - 1 ] ) );
314 - if ( $excut < 0 ) {
315 - $title = mb_substr( $subex, 0, $excut );
316 - } else {
317 - $title = $subex;
318 - }
319 - $title .= '[...]';
320 - } else {
321 - $title = $text;
322 - }
323 -
324 - return apply_filters( 'ayg_gallery_thumb_title', $title, $video, $attributes );
325 -}
326 -
327 -/**
328 542 * Get gallery settings fields.
329 543 *
330 544 * @since 1.0.0
331 545 * @return array $fields Array of fields.
@@ -335,10 +549,10 @@
335 549
336 550 $fields = array(
337 551 array(
338 552 'name' => 'theme',
339 - 'label' => __( 'Select Theme', 'automatic-youtube-gallery' ),
340 - '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() ) ) : '' ),
341 555 'type' => 'select',
342 556 'options' => array(
343 557 'classic' => __( 'Classic', 'automatic-youtube-gallery' )
344 558 ),
@@ -356,9 +570,9 @@
356 570 'sanitize_callback' => 'intval'
357 571 ),
358 572 array(
359 573 'name' => 'per_page',
360 - 'label' => __( 'Videos per page', 'automatic-youtube-gallery' ),
574 + 'label' => __( 'Videos per Page', 'automatic-youtube-gallery' ),
361 575 'description' => __( 'Enter the number of videos to show per page. Maximum of 50.', 'automatic-youtube-gallery' ),
362 576 'type' => 'number',
363 577 'min' => 0,
364 578 'max' => 50,
@@ -366,9 +580,10 @@
366 580 'sanitize_callback' => 'intval'
367 581 ),
368 582 array(
369 583 'name' => 'thumb_ratio',
370 - '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' ),
371 586 'type' => 'radio',
372 587 'options' => array(
373 588 '56.25' => '16:9',
374 589 '75' => '4:3'
@@ -424,13 +639,38 @@
424 639 'name' => 'pagination_type',
425 640 'label' => __( 'Pagination Type', 'automatic-youtube-gallery' ),
426 641 'type' => 'select',
427 642 'options' => array(
428 - 'pager' => __( 'Pager', 'automatic-youtube-gallery' ),
429 - 'load_more' => __( 'Load More', 'automatic-youtube-gallery' )
643 + 'more' => __( 'More Button', 'automatic-youtube-gallery' ),
644 + 'pager' => __( 'Pager', 'automatic-youtube-gallery' )
645 +
430 646 ),
431 647 'value' => $gallery_settings['pagination_type'],
432 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'
433 673 )
434 674 );
435 675
436 676 return apply_filters( 'ayg_gallery_settings_fields', $fields );
@@ -440,90 +680,29 @@
440 680 * Get video description to show on top of the player.
441 681 *
442 682 * @since 1.0.0
443 683 * @param stdClass $video YouTube video object.
444 - * @param array $attributes Array of user attributes.
445 684 * @param int $words_count Number of words to show by default.
446 685 * @return string Video description.
447 686 */
448 -function ayg_get_player_description( $video, $attributes, $words_count = 30 ) {
449 - $description = ! empty( $attributes['player_description'] ) ? $video->description : '';
687 +function ayg_get_player_description( $video, $words_count = 30 ) {
688 + $description = $video->description;
450 689
451 - $words_array = explode( ' ', strip_tags( $description ) );
452 -
690 + $words_array = explode( ' ', strip_tags( $description ) );
453 691 if ( count( $words_array ) > $words_count ) {
454 692 $words_array[ $words_count ] = '<span class="ayg-player-description-dots">...</span></span><span class="ayg-player-description-more">' . $words_array[ $words_count ];
455 693
456 694 $description = '<span class="ayg-player-description-less">' . implode( ' ', $words_array ) . '</span>';
457 - $description .= '<button type="button" class="ayg-player-description-toggle-btn">' . __( 'Show More', 'automatic-youtube-gallery' ) . '</button>';
695 + $description .= '<a href="#" class="ayg-player-description-toggle-btn">[+] ' . __( 'Show More', 'automatic-youtube-gallery' ) . '</a>';
458 696 }
459 697
460 - return apply_filters( 'ayg_player_description', nl2br( $description ), $video, $attributes, $words_count );
461 -}
698 + $description = nl2br( $description );
699 + $description = make_clickable( $description );
462 700
463 -/**
464 - * Get YouTube player embed URL.
465 - *
466 - * @since 1.0.0
467 - * @param stdClass $video YouTube video object.
468 - * @param array $attributes Array of user attributes.
469 - * @return string YouTube video embed URL.
470 - */
471 -function ayg_get_player_embed_url( $video, $attributes ) {
472 - $url = "https://www.youtube-nocookie.com/embed/{$video->id}";
473 -
474 - if ( ! empty( $attributes['autoplay'] ) ) { // autoplay
475 - $url = add_query_arg( 'autoplay', 1, $url );
476 - }
477 -
478 - if ( ! empty( $attributes['loop'] ) ) { // loop
479 - $url = add_query_arg( 'loop', 1, $url );
480 - }
481 -
482 - if ( empty( $attributes['controls'] ) ) { // controls
483 - $url = add_query_arg( 'controls', 0, $url );
484 - }
485 -
486 - if ( ! empty( $attributes['modestbranding'] ) ) { // modestbranding
487 - $url = add_query_arg( 'modestbranding', 1, $url );
488 - }
489 -
490 - if ( ! empty( $attributes['cc_load_policy'] ) ) { // cc_load_policy
491 - $url = add_query_arg( 'cc_load_policy', 1, $url );
492 - }
493 -
494 - if ( empty( $attributes['iv_load_policy'] ) ) { // iv_load_policy
495 - $url = add_query_arg( 'iv_load_policy', 3, $url );
496 - }
497 -
498 - if ( ! empty( $attributes['hl'] ) ) { // hl
499 - $url = add_query_arg( 'hl', $attributes['hl'], $url );
500 - }
501 -
502 - if ( ! empty( $attributes['cc_lang_pref'] ) ) { // cc_lang_pref
503 - $url = add_query_arg( 'cc_lang_pref', $attributes['cc_lang_pref'], $url );
504 - }
505 -
506 - $url = add_query_arg( 'rel', 0, $url ); // rel
507 - $url = add_query_arg( 'playsinline', 1, $url ); // playsinline
508 - $url = add_query_arg( 'enablejsapi', 1, $url ); // enablejsapi
509 -
510 - return apply_filters( 'ayg_player_embed_url', $url, $video, $attributes );
701 + return apply_filters( 'ayg_player_description', $description, $video, $words_count );
511 702 }
512 703
513 704 /**
514 - * Get player ratio.
515 - *
516 - * @since 1.0.0
517 - * @param array $attributes Array of user attributes.
518 - * @return string Player ratio.
519 - */
520 -function ayg_get_player_ratio( $attributes ) {
521 - $ratio = ! empty( $attributes['player_ratio'] ) ? $attributes['player_ratio'] . '%' : '56.25%';
522 - return apply_filters( 'ayg_player_ratio', $ratio, $attributes );
523 -}
524 -
525 -/**
526 705 * Get player settings fields.
527 706 *
528 707 * @since 1.0.0
529 708 * @return array $fields Array of fields.
@@ -533,9 +712,10 @@
533 712
534 713 $fields = array(
535 714 array(
536 715 'name' => 'player_ratio',
537 - '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' ),
538 718 'type' => 'radio',
539 719 'options' => array(
540 720 '56.25' => '16:9',
541 721 '75' => '4:3'
@@ -581,10 +761,18 @@
581 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' ),
582 762 'type' => 'checkbox',
583 763 'value' => $player_settings['loop'],
584 764 'sanitize_callback' => 'intval'
585 - ),
765 + ),
586 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(
587 775 'name' => 'controls',
588 776 'label' => __( 'Show Player Controls', 'automatic-youtube-gallery' ),
589 777 'description' => __( 'Uncheck this option to hide the video player controls.', 'automatic-youtube-gallery' ),
590 778 'type' => 'checkbox',
@@ -635,37 +823,41 @@
635 823 ),
636 824 'type' => 'text',
637 825 'value' => $player_settings['cc_lang_pref'],
638 826 'sanitize_callback' => 'sanitize_text_field'
639 - )
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 + ),
640 844 );
641 845
642 846 return $fields;
643 847 }
644 848
645 -/**
646 - * Get video title to show on bottom of the player.
647 - *
648 - * @since 1.0.0
649 - * @param stdClass $video YouTube video object.
650 - * @param array $attributes Array of user attributes.
651 - * @return string Video title.
652 - */
653 -function ayg_get_player_title( $video, $attributes ) {
654 - $title = ! empty( $attributes['player_title'] ) ? $video->title : '';
655 - return apply_filters( 'ayg_player_title', $title, $video, $attributes );
656 -}
657 849
658 850 /**
659 - * Get player width.
851 + * Get a single video page URL.
660 852 *
661 - * @since 1.0.0
662 - * @param array $attributes Array of user attributes.
663 - * @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.
664 857 */
665 -function ayg_get_player_width( $attributes ) {
666 - $width = ! empty( $attributes['player_width'] ) ? $attributes['player_width'] . 'px' : '100%';
667 - 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 );
668 860 }
669 861
670 862 /**
671 863 * Get filtered php template file path.
@@ -695,110 +887,115 @@
695 887 return uniqid() . ++$ayg_uniqid;
696 888 }
697 889
698 890 /**
699 - * Sanitize the integer inputs, accepts empty values.
891 + * Get YouTube domain.
700 892 *
701 - * @since 1.0.0
702 - * @param string|int $value Input value.
703 - * @return string|int Sanitized value.
893 + * @since 2.3.0
894 + * @return string YouTube embed domain.
704 895 */
705 -function ayg_sanitize_int( $value ) {
706 - $value = intval( $value );
707 - 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;
708 905 }
709 906
710 907 /**
711 - * Gallery HTML output.
908 + * Inserts a new associative array after another associative array key.
712 909 *
713 - * @since 1.0.0
714 - * @param array $videos Array of YouTube video object.
715 - * @param array $attributes Array of user attributes.
716 - * @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.
717 915 */
718 -function the_ayg_gallery( $videos, $attributes, $active_id = 0 ) {
719 - if ( 'video' != $attributes['type'] ) {
720 - include ayg_get_template( AYG_DIR . 'public/templates/gallery.php', $attributes['theme'] );
721 - }
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;
722 934 }
723 935
724 936 /**
725 - * Gallery HTML output.
937 + * Sanitize the integer inputs, accepts empty values.
726 938 *
727 939 * @since 1.0.0
728 - * @param array $video YouTube video object.
729 - * @param array $attributes Array of user attributes.
730 - * @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.
731 942 */
732 -function the_ayg_gallery_thumbnail( $video, $attributes, $is_active = false ) {
733 - 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;
734 946 }
735 947
736 948 /**
737 - * Pagination HTML output.
949 + * Trims text to a certain number of characters.
738 950 *
739 - * @since 1.0.0
740 - * @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.
741 956 */
742 -function the_ayg_pagination( $atts ) {
743 - if ( ! empty( $atts['pagination'] ) ) {
744 - // Build attributes
745 - $attributes = array();
957 +function ayg_trim_words( $text, $num_characters, $append = '...' ) {
958 + $num_characters++;
746 959
747 - $fields = ayg_get_editor_fields();
960 + $original_text = $text;
961 + $text = ( $num_characters > 1 ) ? wp_strip_all_tags( $original_text, true ) : nl2br( $original_text );
748 962
749 - foreach ( $fields['gallery']['fields'] as $field ) {
750 - $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 ] ) );
751 967
752 - if ( ! in_array( $field_name, array( 'per_page', 'pagination' ) ) ) {
753 - $attributes[ $field_name ] = sanitize_text_field( $atts[ $field_name ] );
754 - }
968 + if ( $excut < 0 ) {
969 + $text = mb_substr( $subex, 0, $excut );
970 + } else {
971 + $text = $subex;
755 972 }
756 973
757 - $source_type = sanitize_text_field( $atts['type'] );
758 -
759 - $attributes = array_merge(
760 - $attributes,
761 - array(
762 - 'type' => $source_type,
763 - 'id' => sanitize_text_field( $atts[ $source_type ] ),
764 - 'order' => sanitize_text_field( $atts['order'] ), // works only when type=search
765 - 'per_page' => (int) $atts['per_page'],
766 - 'cache' => (int) $atts['cache'],
767 - 'player_description' => ! empty( $atts['player_description'] ) ? (int) $atts['player_description'] : 0,
768 - 'num_pages' => 1,
769 - 'paged' => ! empty( $atts['paged'] ) ? (int) $atts['paged'] : 1,
770 - 'next_page_token' => ! empty( $atts['next_page_token'] ) ? sanitize_text_field( $atts['next_page_token'] ) : '',
771 - 'prev_page_token' => ! empty( $atts['prev_page_token'] ) ? sanitize_text_field( $atts['prev_page_token'] ) : ''
772 - )
773 - );
974 + $text .= $append;
975 + }
774 976
775 - // Find total number of pages
776 - $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 +}
777 979
778 - if ( $videos_found > 0 ) {
779 - if ( 'search' == $source_type ) {
780 - $limit = min( (int) $atts['limit'], $videos_found );
781 - $attributes['num_pages'] = ceil( $limit / $attributes['per_page'] );
782 - } else {
783 - $attributes['num_pages'] = ceil( $videos_found / $attributes['per_page'] );
784 - }
785 - }
786 -
787 - // Process output
788 - if ( $attributes['num_pages'] > 1 ) {
789 - $pagination_type = ( 'pager' == $atts['pagination_type'] ) ? 'pager' : 'loadmore';
790 - include ayg_get_template( AYG_DIR . 'public/templates/pagination-' . $pagination_type. '.php', $attributes['theme'] );
791 - }
792 - }
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' );
793 989 }
794 990
795 991 /**
796 - * Player HTML output.
992 + * Pagination HTML output.
797 993 *
798 994 * @since 1.0.0
799 - * @param stdClass $video YouTube video object.
800 - * @param array $attributes Array of user attributes.
995 + * @param array $attributes Array of user attributes.
801 996 */
802 -function the_ayg_player( $video, $attributes ) {
803 - include ayg_get_template( AYG_DIR . 'public/templates/player.php', $attributes['theme'] );
804 -}
997 +function the_ayg_pagination( $attributes ) {
998 + if ( ! empty( $attributes['pagination'] ) ) {
999 + include ayg_get_template( AYG_DIR . 'public/templates/pagination.php' );
1000 + }
1001 +}