1
|
|
|
<?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName |
2
|
|
|
|
3
|
|
|
use Automattic\Jetpack\Assets; |
4
|
|
|
use Automattic\Jetpack\Extensions\Slideshow; |
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* Slideshow shortcode. |
8
|
|
|
* Adds a new "slideshow" gallery type when adding a gallery using the classic editor. |
9
|
|
|
* |
10
|
|
|
* @package Jetpack |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Slideshow shortcode usage: [gallery type="slideshow"] or the older [slideshow] |
15
|
|
|
*/ |
16
|
|
|
class Jetpack_Slideshow_Shortcode { |
17
|
|
|
/** |
18
|
|
|
* Number of slideshows on a page. |
19
|
|
|
* |
20
|
|
|
* @var int |
21
|
|
|
*/ |
22
|
|
|
public $instance_count = 0; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Constructor |
26
|
|
|
*/ |
27
|
|
|
public function __construct() { |
28
|
|
|
global $shortcode_tags; |
29
|
|
|
|
30
|
|
|
// Only if the slideshow shortcode has not already been defined. |
31
|
|
|
if ( ! array_key_exists( 'slideshow', $shortcode_tags ) ) { |
32
|
|
|
add_shortcode( 'slideshow', array( $this, 'shortcode_callback' ) ); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
// Only if the gallery shortcode has not been redefined. |
36
|
|
|
if ( isset( $shortcode_tags['gallery'] ) && 'gallery_shortcode' === $shortcode_tags['gallery'] ) { |
37
|
|
|
add_filter( 'post_gallery', array( $this, 'post_gallery' ), 1002, 2 ); |
38
|
|
|
add_filter( 'jetpack_gallery_types', array( $this, 'add_gallery_type' ), 10 ); |
39
|
|
|
} |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Responds to the [gallery] shortcode, but not an actual shortcode callback. |
44
|
|
|
* |
45
|
|
|
* @param string $value An empty string if nothing has modified the gallery output, the output html otherwise. |
46
|
|
|
* @param array $attr The shortcode attributes array. |
47
|
|
|
* |
48
|
|
|
* @return string The (un)modified $value |
49
|
|
|
*/ |
50
|
|
|
public function post_gallery( $value, $attr ) { |
51
|
|
|
// Bail if somebody else has done something. |
52
|
|
|
if ( ! empty( $value ) ) { |
53
|
|
|
return $value; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
// If [gallery type="slideshow"] have it behave just like [slideshow]. |
57
|
|
|
if ( ! empty( $attr['type'] ) && 'slideshow' === $attr['type'] ) { |
58
|
|
|
return $this->shortcode_callback( $attr ); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
return $value; |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* Add the Slideshow type to gallery settings |
66
|
|
|
* |
67
|
|
|
* @see Jetpack_Tiled_Gallery::media_ui_print_templates |
68
|
|
|
* |
69
|
|
|
* @param array $types An array of types where the key is the value, and the value is the caption. |
70
|
|
|
* |
71
|
|
|
* @return array |
72
|
|
|
*/ |
73
|
|
|
public function add_gallery_type( $types = array() ) { |
74
|
|
|
$types['slideshow'] = esc_html__( 'Slideshow', 'jetpack' ); |
75
|
|
|
|
76
|
|
|
return $types; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Display shortcode. |
81
|
|
|
* |
82
|
|
|
* @param array $attr Shortcode attributes. |
83
|
|
|
*/ |
84
|
|
|
public function shortcode_callback( $attr ) { |
85
|
|
|
$post_id = get_the_ID(); |
86
|
|
|
|
87
|
|
|
$attr = shortcode_atts( |
88
|
|
|
array( |
89
|
|
|
'trans' => 'fade', |
90
|
|
|
'order' => 'ASC', |
91
|
|
|
'orderby' => 'menu_order ID', |
92
|
|
|
'id' => $post_id, |
93
|
|
|
'include' => '', |
94
|
|
|
'exclude' => '', |
95
|
|
|
'autostart' => true, |
96
|
|
|
'size' => '', |
97
|
|
|
), |
98
|
|
|
$attr, |
99
|
|
|
'slideshow' |
100
|
|
|
); |
101
|
|
|
|
102
|
|
|
if ( 'rand' === strtolower( $attr['order'] ) ) { |
103
|
|
|
$attr['orderby'] = 'none'; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
$attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] ); |
107
|
|
|
if ( ! $attr['orderby'] ) { |
108
|
|
|
$attr['orderby'] = 'menu_order ID'; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
if ( ! $attr['size'] ) { |
112
|
|
|
$attr['size'] = 'full'; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
// Don't restrict to the current post if include. |
116
|
|
|
$post_parent = ( empty( $attr['include'] ) ) ? intval( $attr['id'] ) : null; |
117
|
|
|
|
118
|
|
|
$attachments = get_posts( |
119
|
|
|
array( |
120
|
|
|
'post_status' => 'inherit', |
121
|
|
|
'post_type' => 'attachment', |
122
|
|
|
'post_mime_type' => 'image', |
123
|
|
|
'posts_per_page' => - 1, |
124
|
|
|
'post_parent' => $post_parent, |
125
|
|
|
'order' => $attr['order'], |
126
|
|
|
'orderby' => $attr['orderby'], |
127
|
|
|
'include' => $attr['include'], |
128
|
|
|
'exclude' => $attr['exclude'], |
129
|
|
|
'suppress_filters' => false, |
130
|
|
|
) |
131
|
|
|
); |
132
|
|
|
|
133
|
|
|
if ( count( $attachments ) < 1 ) { |
134
|
|
|
return false; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
$gallery_instance = sprintf( 'gallery-%d-%d', $attr['id'], ++$this->instance_count ); |
138
|
|
|
|
139
|
|
|
$gallery = array(); |
140
|
|
|
foreach ( $attachments as $attachment ) { |
141
|
|
|
$attachment_image_src = wp_get_attachment_image_src( $attachment->ID, $attr['size'] ); |
142
|
|
|
$attachment_image_src = $attachment_image_src[0]; // [url, width, height]. |
143
|
|
|
$attachment_image_title = get_the_title( $attachment->ID ); |
144
|
|
|
$attachment_image_alt = get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ); |
145
|
|
|
/** |
146
|
|
|
* Filters the Slideshow slide caption. |
147
|
|
|
* |
148
|
|
|
* @module shortcodes |
149
|
|
|
* |
150
|
|
|
* @since 2.3.0 |
151
|
|
|
* |
152
|
|
|
* @param string wptexturize( strip_tags( $attachment->post_excerpt ) ) Post excerpt. |
153
|
|
|
* @param string $attachment ->ID Attachment ID. |
154
|
|
|
*/ |
155
|
|
|
$caption = apply_filters( 'jetpack_slideshow_slide_caption', wptexturize( wp_strip_all_tags( $attachment->post_excerpt ) ), $attachment->ID ); |
|
|
|
|
156
|
|
|
|
157
|
|
|
$gallery[] = (object) array( |
158
|
|
|
'src' => (string) esc_url_raw( $attachment_image_src ), |
159
|
|
|
'id' => (string) $attachment->ID, |
160
|
|
|
'title' => (string) esc_attr( $attachment_image_title ), |
161
|
|
|
'alt' => (string) esc_attr( $attachment_image_alt ), |
162
|
|
|
'caption' => (string) $caption, |
163
|
|
|
'itemprop' => 'image', |
164
|
|
|
); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
$color = Jetpack_Options::get_option( 'slideshow_background_color', 'black' ); |
168
|
|
|
$autostart = $attr['autostart'] ? $attr['autostart'] : 'true'; |
169
|
|
|
$js_attr = array( |
170
|
|
|
'gallery' => $gallery, |
171
|
|
|
'selector' => $gallery_instance, |
172
|
|
|
'trans' => $attr['trans'] ? $attr['trans'] : 'fade', |
173
|
|
|
'autostart' => $autostart, |
174
|
|
|
'color' => $color, |
175
|
|
|
); |
176
|
|
|
|
177
|
|
|
// Show a link to the gallery in feeds. |
178
|
|
|
if ( is_feed() ) { |
179
|
|
|
return sprintf( |
180
|
|
|
'<a href="%s">%s</a>', |
181
|
|
|
esc_url( get_permalink( $post_id ) . '#' . $gallery_instance . '-slideshow' ), |
182
|
|
|
esc_html__( 'Click to view slideshow.', 'jetpack' ) |
183
|
|
|
); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) { |
187
|
|
|
// Load the styles and use the rendering method from the Slideshow block. |
188
|
|
|
Jetpack_Gutenberg::load_styles_as_required( 'slideshow' ); |
189
|
|
|
|
190
|
|
|
$amp_args = array( |
191
|
|
|
'ids' => wp_list_pluck( $gallery, 'id' ), |
192
|
|
|
); |
193
|
|
|
|
194
|
|
|
if ( 'true' == $autostart ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison -- attribute can be stored as boolean or string. |
195
|
|
|
$amp_args['autoplay'] = true; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
return Slideshow\render_amp( $amp_args ); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
return $this->slideshow_js( $js_attr ); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Render the slideshow js |
206
|
|
|
* |
207
|
|
|
* Returns the necessary markup and js to fire a slideshow. |
208
|
|
|
* |
209
|
|
|
* @param array $attr Attributes for the slideshow. |
210
|
|
|
* |
211
|
|
|
* @uses $this->enqueue_scripts() |
212
|
|
|
* |
213
|
|
|
* @return string HTML output. |
214
|
|
|
*/ |
215
|
|
|
public function slideshow_js( $attr ) { |
216
|
|
|
// Enqueue scripts. |
217
|
|
|
$this->enqueue_scripts(); |
218
|
|
|
|
219
|
|
|
$output = ''; |
220
|
|
|
|
221
|
|
|
if ( defined( 'JSON_HEX_AMP' ) ) { |
222
|
|
|
// This is nice to have, but not strictly necessary since we use _wp_specialchars() below. |
223
|
|
|
$gallery = wp_json_encode( $attr['gallery'], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ); // phpcs:ignore PHPCompatibility |
224
|
|
|
} else { |
225
|
|
|
$gallery = wp_json_encode( $attr['gallery'] ); |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
$output .= '<p class="jetpack-slideshow-noscript robots-nocontent">' . esc_html__( 'This slideshow requires JavaScript.', 'jetpack' ) . '</p>'; |
229
|
|
|
|
230
|
|
|
/* |
231
|
|
|
* The input to json_encode() above can contain '"'. |
232
|
|
|
* |
233
|
|
|
* For calls to json_encode() lacking the JSON_HEX_AMP option, |
234
|
|
|
* that '"' is left unaltered. Running '"' through esc_attr() |
235
|
|
|
* also leaves it unaltered since esc_attr() does not double-encode. |
236
|
|
|
* |
237
|
|
|
* This means we end up with an attribute like |
238
|
|
|
* `data-gallery="{"foo":"""}"`, |
239
|
|
|
* which is interpreted by the browser as `{"foo":"""}`, |
240
|
|
|
* which cannot be JSON decoded. |
241
|
|
|
* |
242
|
|
|
* The preferred workaround is to include the JSON_HEX_AMP (and friends) |
243
|
|
|
* options, but these are not available until 5.3.0. |
244
|
|
|
* Alternatively, we can use _wp_specialchars( , , , true ) instead of |
245
|
|
|
* esc_attr(), which will double-encode. |
246
|
|
|
* |
247
|
|
|
* Since we can't rely on JSON_HEX_AMP, we do both. |
248
|
|
|
* |
249
|
|
|
* @todo Update when minimum is PHP 5.3+ |
250
|
|
|
*/ |
251
|
|
|
$gallery_attributes = _wp_specialchars( wp_check_invalid_utf8( $gallery ), ENT_QUOTES, false, true ); |
252
|
|
|
|
253
|
|
|
$output .= sprintf( |
254
|
|
|
'<div id="%s" class="slideshow-window jetpack-slideshow slideshow-%s" data-trans="%s" data-autostart="%s" data-gallery="%s" itemscope itemtype="https://schema.org/ImageGallery"></div>', |
255
|
|
|
esc_attr( $attr['selector'] . '-slideshow' ), |
256
|
|
|
esc_attr( $attr['color'] ), |
257
|
|
|
esc_attr( $attr['trans'] ), |
258
|
|
|
esc_attr( $attr['autostart'] ), |
259
|
|
|
$gallery_attributes |
260
|
|
|
); |
261
|
|
|
|
262
|
|
|
return $output; |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* Actually enqueues the scripts and styles. |
267
|
|
|
*/ |
268
|
|
|
public function enqueue_scripts() { |
269
|
|
|
|
270
|
|
|
wp_enqueue_script( 'jquery-cycle', plugins_url( '/js/jquery.cycle.min.js', __FILE__ ), array( 'jquery' ), '20161231', true ); |
271
|
|
|
wp_enqueue_script( |
272
|
|
|
'jetpack-slideshow', |
273
|
|
|
Assets::get_file_url_for_environment( '_inc/build/shortcodes/js/slideshow-shortcode.min.js', 'modules/shortcodes/js/slideshow-shortcode.js' ), |
274
|
|
|
array( 'jquery-cycle' ), |
275
|
|
|
'20160119.1', |
276
|
|
|
true |
277
|
|
|
); |
278
|
|
|
wp_enqueue_style( |
279
|
|
|
'jetpack-slideshow', |
280
|
|
|
plugins_url( '/css/slideshow-shortcode.css', __FILE__ ), |
281
|
|
|
array(), |
282
|
|
|
JETPACK__VERSION |
283
|
|
|
); |
284
|
|
|
wp_style_add_data( 'jetpack-slideshow', 'rtl', 'replace' ); |
285
|
|
|
|
286
|
|
|
wp_localize_script( |
287
|
|
|
'jetpack-slideshow', |
288
|
|
|
'jetpackSlideshowSettings', |
289
|
|
|
/** |
290
|
|
|
* Filters the slideshow JavaScript spinner. |
291
|
|
|
* |
292
|
|
|
* @module shortcodes |
293
|
|
|
* |
294
|
|
|
* @since 2.1.0 |
295
|
|
|
* @since 4.7.0 Added the `speed` option to the array of options. |
296
|
|
|
* |
297
|
|
|
* @param array $args |
298
|
|
|
* - string - spinner - URL of the spinner image. |
299
|
|
|
* - string - speed - Speed of the slideshow. Defaults to 4000. |
300
|
|
|
* - string - label_prev - Aria label for slideshow's previous button |
301
|
|
|
* - string - label_stop - Aria label for slideshow's pause button |
302
|
|
|
* - string - label_next - Aria label for slideshow's next button |
303
|
|
|
*/ |
304
|
|
|
apply_filters( |
305
|
|
|
'jetpack_js_slideshow_settings', |
306
|
|
|
array( |
307
|
|
|
'spinner' => plugins_url( '/img/slideshow-loader.gif', __FILE__ ), |
308
|
|
|
'speed' => '4000', |
309
|
|
|
'label_prev' => __( 'Previous Slide', 'jetpack' ), |
310
|
|
|
'label_stop' => __( 'Pause Slideshow', 'jetpack' ), |
311
|
|
|
'label_next' => __( 'Next Slide', 'jetpack' ), |
312
|
|
|
) |
313
|
|
|
) |
314
|
|
|
); |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* Instantiate shortcode. |
319
|
|
|
*/ |
320
|
|
|
public static function init() { |
321
|
|
|
new Jetpack_Slideshow_Shortcode(); |
322
|
|
|
} |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
Jetpack_Slideshow_Shortcode::init(); |
326
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.