Completed
Push — add/carousel-for-single-image ( 56d26e...8186b5 )
by
unknown
15:49
created

Jetpack_Carousel::set_in_gallery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
Plugin Name: Jetpack Carousel
5
Plugin URL: https://wordpress.com/
6
Description: Transform your standard image galleries into an immersive full-screen experience.
7
Version: 0.1
8
Author: Automattic
9
10
Released under the GPL v.2 license.
11
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
*/
17
class Jetpack_Carousel {
18
19
	public $prebuilt_widths = array( 370, 700, 1000, 1200, 1400, 2000 );
20
21
	public $first_run = true;
22
23
	public $in_gallery = false;
24
25
	public $in_jetpack = true;
26
27
	public $single_image_gallery_enabled = false;
28
29
	function __construct() {
30
		add_action( 'init', array( $this, 'init' ) );
31
	}
32
33
	function init() {
34
		if ( $this->maybe_disable_jp_carousel() )
35
			return;
36
37
		$this->in_jetpack = ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'enable_module_configurable' ) ) ? true : false;
38
39
		$this->single_image_gallery_enabled =
40
			( 1 == $this->test_1or0_option( Jetpack_Options::get_option_and_ensure_autoload( 'carousel_single_image_display_gallery', true ) ) );
41
42
		if ( is_admin() ) {
43
			// Register the Carousel-related related settings
44
			add_action( 'admin_init', array( $this, 'register_settings' ), 5 );
45
			if ( ! $this->in_jetpack ) {
46
				if ( 0 == $this->test_1or0_option( get_option( 'carousel_enable_it' ), true ) )
47
					return; // Carousel disabled, abort early, but still register setting so user can switch it back on
48
			}
49
			// If in admin, register the ajax endpoints.
50
			add_action( 'wp_ajax_get_attachment_comments', array( $this, 'get_attachment_comments' ) );
51
			add_action( 'wp_ajax_nopriv_get_attachment_comments', array( $this, 'get_attachment_comments' ) );
52
			add_action( 'wp_ajax_post_attachment_comment', array( $this, 'post_attachment_comment' ) );
53
			add_action( 'wp_ajax_nopriv_post_attachment_comment', array( $this, 'post_attachment_comment' ) );
54
		} else {
55
			if ( ! $this->in_jetpack ) {
56
				if ( 0 == $this->test_1or0_option( get_option( 'carousel_enable_it' ), true ) )
57
					return; // Carousel disabled, abort early
58
			}
59
			// If on front-end, do the Carousel thang.
60
			/**
61
			 * Filter the array of default prebuilt widths used in Carousel.
62
			 *
63
			 * @module carousel
64
			 *
65
			 * @since 1.6.0
66
			 *
67
			 * @param array $this->prebuilt_widths Array of default widths.
68
			 */
69
			$this->prebuilt_widths = apply_filters( 'jp_carousel_widths', $this->prebuilt_widths );
70
			add_filter( 'post_gallery', array( $this, 'enqueue_assets' ), 1000, 2 ); // load later than other callbacks hooked it
71
			add_filter( 'post_gallery', array( $this, 'set_in_gallery' ), -1000 );
72
			add_filter( 'gallery_style', array( $this, 'add_data_to_container' ) );
73
			add_filter( 'wp_get_attachment_image_attributes', array( $this, 'add_data_to_images' ), 10, 2 );
74
			if ( $this->single_image_gallery_enabled ) {
75
				add_filter( 'the_content', array( $this, 'add_data_to_single_images' ) );
76
			}
77
		}
78
79
		if ( $this->in_jetpack && method_exists( 'Jetpack', 'module_configuration_load' ) ) {
80
			Jetpack::enable_module_configurable( dirname( dirname( __FILE__ ) ) . '/carousel.php' );
81
			Jetpack::module_configuration_load( dirname( dirname( __FILE__ ) ) . '/carousel.php', array( $this, 'jetpack_configuration_load' ) );
82
		}
83
	}
84
85
	function maybe_disable_jp_carousel() {
86
		/**
87
		 * Allow third-party plugins or themes to disable Carousel.
88
		 *
89
		 * @module carousel
90
		 *
91
		 * @since 1.6.0
92
		 *
93
		 * @param bool false Should Carousel be disabled? Default to false.
94
		 */
95
		return apply_filters( 'jp_carousel_maybe_disable', false );
96
	}
97
98
	function jetpack_configuration_load() {
99
		wp_safe_redirect( admin_url( 'options-media.php#carousel_background_color' ) );
100
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method jetpack_configuration_load() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
101
	}
102
103
	function asset_version( $version ) {
104
		/**
105
		 * Filter the version string used when enqueuing Carousel assets.
106
		 *
107
		 * @module carousel
108
		 *
109
		 * @since 1.6.0
110
		 *
111
		 * @param string $version Asset version.
112
		 */
113
		return apply_filters( 'jp_carousel_asset_version', $version );
114
	}
115
116
	function display_bail_message( $output= '' ) {
117
		// Displays a message on top of gallery if carousel has bailed
118
		$message = '<div class="jp-carousel-msg"><p>';
119
		$message .= __( 'Jetpack\'s Carousel has been disabled, because another plugin or your theme is overriding the [gallery] shortcode.', 'jetpack' );
120
		$message .= '</p></div>';
121
		// put before gallery output
122
		$output = $message . $output;
123
		return $output;
124
	}
125
126
	function enqueue_assets( $output ) {
127
		if (
128
			! empty( $output ) &&
129
			/**
130
			 * Allow third-party plugins or themes to force-enable Carousel.
131
			 *
132
			 * @module carousel
133
			 *
134
			 * @since 1.9.0
135
			 *
136
			 * @param bool false Should we force enable Carousel? Default to false.
137
			 */
138
			! apply_filters( 'jp_carousel_force_enable', false )
139
		) {
140
			// Bail because someone is overriding the [gallery] shortcode.
141
			remove_filter( 'gallery_style', array( $this, 'add_data_to_container' ) );
142
			remove_filter( 'wp_get_attachment_image_attributes', array( $this, 'add_data_to_images' ) );
143
			// Display message that carousel has bailed, if user is super_admin, and if we're not on WordPress.com.
144
			if (
145
				is_super_admin() &&
146
				! ( defined( 'IS_WPCOM' ) && IS_WPCOM )
147
			) {
148
				add_filter( 'post_gallery', array( $this, 'display_bail_message' ) );
149
			}
150
			return $output;
151
		}
152
153
		/**
154
		 * Fires when thumbnails are shown in Carousel.
155
		 *
156
		 * @module carousel
157
		 *
158
		 * @since 1.6.0
159
		 **/
160
		do_action( 'jp_carousel_thumbnails_shown' );
161
162
		if ( $this->first_run ) {
163
			wp_enqueue_script( 'jetpack-carousel', plugins_url( 'jetpack-carousel.js', __FILE__ ), array( 'jquery.spin' ), $this->asset_version( '20160325' ), true );
164
165
			// Note: using  home_url() instead of admin_url() for ajaxurl to be sure  to get same domain on wpcom when using mapped domains (also works on self-hosted)
166
			// Also: not hardcoding path since there is no guarantee site is running on site root in self-hosted context.
167
			$is_logged_in = is_user_logged_in();
168
			$current_user = wp_get_current_user();
169
			$comment_registration = intval( get_option( 'comment_registration' ) );
170
			$require_name_email   = intval( get_option( 'require_name_email' ) );
171
			$localize_strings = array(
172
				'widths'               => $this->prebuilt_widths,
173
				'is_logged_in'         => $is_logged_in,
174
				'lang'                 => strtolower( substr( get_locale(), 0, 2 ) ),
175
				'ajaxurl'              => set_url_scheme( admin_url( 'admin-ajax.php' ) ),
176
				'nonce'                => wp_create_nonce( 'carousel_nonce' ),
177
				'display_exif'         => $this->test_1or0_option( Jetpack_Options::get_option_and_ensure_autoload( 'carousel_display_exif', true ) ),
178
				'display_geo'          => $this->test_1or0_option( Jetpack_Options::get_option_and_ensure_autoload( 'carousel_display_geo', true ) ),
179
				'single_image_gallery' => $this->single_image_gallery_enabled,
180
				'background_color'     => $this->carousel_background_color_sanitize( Jetpack_Options::get_option_and_ensure_autoload( 'carousel_background_color', '' ) ),
181
				'comment'              => __( 'Comment', 'jetpack' ),
182
				'post_comment'         => __( 'Post Comment', 'jetpack' ),
183
				'write_comment'        => __( 'Write a Comment...', 'jetpack' ),
184
				'loading_comments'     => __( 'Loading Comments...', 'jetpack' ),
185
				'download_original'    => sprintf( __( 'View full size <span class="photo-size">%1$s<span class="photo-size-times">&times;</span>%2$s</span>', 'jetpack' ), '{0}', '{1}' ),
186
				'no_comment_text'      => __( 'Please be sure to submit some text with your comment.', 'jetpack' ),
187
				'no_comment_email'     => __( 'Please provide an email address to comment.', 'jetpack' ),
188
				'no_comment_author'    => __( 'Please provide your name to comment.', 'jetpack' ),
189
				'comment_post_error'   => __( 'Sorry, but there was an error posting your comment. Please try again later.', 'jetpack' ),
190
				'comment_approved'     => __( 'Your comment was approved.', 'jetpack' ),
191
				'comment_unapproved'   => __( 'Your comment is in moderation.', 'jetpack' ),
192
				'camera'               => __( 'Camera', 'jetpack' ),
193
				'aperture'             => __( 'Aperture', 'jetpack' ),
194
				'shutter_speed'        => __( 'Shutter Speed', 'jetpack' ),
195
				'focal_length'         => __( 'Focal Length', 'jetpack' ),
196
				'comment_registration' => $comment_registration,
197
				'require_name_email'   => $require_name_email,
198
				/** This action is documented in core/src/wp-includes/link-template.php */
199
				'login_url'            => wp_login_url( apply_filters( 'the_permalink', get_permalink() ) ),
200
			);
201
202
			if ( ! isset( $localize_strings['jetpack_comments_iframe_src'] ) || empty( $localize_strings['jetpack_comments_iframe_src'] ) ) {
203
				// We're not using Comments after all, so fallback to standard local comments.
204
205
				if ( $is_logged_in ) {
206
					$localize_strings['local_comments_commenting_as'] = '<p id="jp-carousel-commenting-as">' . sprintf( __( 'Commenting as %s', 'jetpack' ), $current_user->data->display_name ) . '</p>';
207
				} else {
208
					if ( $comment_registration ) {
209
						$localize_strings['local_comments_commenting_as'] = '<p id="jp-carousel-commenting-as">' . __( 'You must be <a href="#" class="jp-carousel-comment-login">logged in</a> to post a comment.', 'jetpack' ) . '</p>';
210
					} else {
211
						$required = ( $require_name_email ) ? __( '%s (Required)', 'jetpack' ) : '%s';
212
						$localize_strings['local_comments_commenting_as'] = ''
213
							. '<fieldset><label for="email">' . sprintf( $required, __( 'Email', 'jetpack' ) ) . '</label> '
214
							. '<input type="text" name="email" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-email-field" /></fieldset>'
215
							. '<fieldset><label for="author">' . sprintf( $required, __( 'Name', 'jetpack' ) ) . '</label> '
216
							. '<input type="text" name="author" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-author-field" /></fieldset>'
217
							. '<fieldset><label for="url">' . __( 'Website', 'jetpack' ) . '</label> '
218
							. '<input type="text" name="url" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-url-field" /></fieldset>';
219
						}
220
				}
221
			}
222
223
			/**
224
			 * Handle WP stats for images in full-screen.
225
			 * Build string with tracking info.
226
			 */
227
228
			/**
229
			 * Filter if Jetpack should enable stats collection on carousel views
230
			 *
231
			 * @module carousel
232
			 *
233
			 * @since 4.3.2
234
			 *
235
			 * @param bool Enable Jetpack Carousel stat collection. Default false.
236
			 */
237
			if ( apply_filters( 'jetpack_enable_carousel_stats', false ) && in_array( 'stats', Jetpack::get_active_modules() ) && ! Jetpack::is_development_mode() ) {
238
				$localize_strings['stats'] = 'blog=' . Jetpack_Options::get_option( 'id' ) . '&host=' . parse_url( get_option( 'home' ), PHP_URL_HOST ) . '&v=ext&j=' . JETPACK__API_VERSION . ':' . JETPACK__VERSION;
239
240
				// Set the stats as empty if user is logged in but logged-in users shouldn't be tracked.
241 View Code Duplication
				if ( is_user_logged_in() && function_exists( 'stats_get_options' ) ) {
242
					$stats_options = stats_get_options();
243
					$track_loggedin_users = isset( $stats_options['reg_users'] ) ? (bool) $stats_options['reg_users'] : false;
244
245
					if ( ! $track_loggedin_users ) {
246
						$localize_strings['stats'] = '';
247
					}
248
				}
249
			}
250
251
			/**
252
			 * Filter the strings passed to the Carousel's js file.
253
			 *
254
			 * @module carousel
255
			 *
256
			 * @since 1.6.0
257
			 *
258
			 * @param array $localize_strings Array of strings passed to the Jetpack js file.
259
			 */
260
			$localize_strings = apply_filters( 'jp_carousel_localize_strings', $localize_strings );
261
			wp_localize_script( 'jetpack-carousel', 'jetpackCarouselStrings', $localize_strings );
262
			if( is_rtl() ) {
263
				wp_enqueue_style( 'jetpack-carousel', plugins_url( '/rtl/jetpack-carousel-rtl.css', __FILE__ ), array(), $this->asset_version( '20120629' ) );
264
			} else {
265
				wp_enqueue_style( 'jetpack-carousel', plugins_url( 'jetpack-carousel.css', __FILE__ ), array(), $this->asset_version( '20120629' ) );
266
			}
267
268
			wp_register_style( 'jetpack-carousel-ie8fix', plugins_url( 'jetpack-carousel-ie8fix.css', __FILE__ ), array(), $this->asset_version( '20121024' ) );
269
			$GLOBALS['wp_styles']->add_data( 'jetpack-carousel-ie8fix', 'conditional', 'lte IE 8' );
270
			wp_enqueue_style( 'jetpack-carousel-ie8fix' );
271
272
			/**
273
			 * Fires after carousel assets are enqueued for the first time.
274
			 * Allows for adding additional assets to the carousel page.
275
			 *
276
			 * @module carousel
277
			 *
278
			 * @since 1.6.0
279
			 *
280
			 * @param bool $first_run First load if Carousel on the page.
281
			 * @param array $localized_strings Array of strings passed to the Jetpack js file.
282
			 */
283
			do_action( 'jp_carousel_enqueue_assets', $this->first_run, $localize_strings );
284
285
			$this->first_run = false;
286
		}
287
288
		return $output;
289
	}
290
291
	function set_in_gallery( $output ) {
292
		$this->in_gallery = true;
293
		return $output;
294
	}
295
296
	/**
297
	 * Adds data-* attributes required by carousel to img tags in post HTML
298
	 * content. To be used by 'the_content' filter.
299
	 *
300
	 * @see add_data_to_images()
301
	 * @see wp_make_content_images_responsive() in wp-includes/media.php
302
	 *
303
	 * @param string $content HTML content of the post
304
	 * @return string Modified HTML content of the post
305
	 */
306
	function add_data_to_single_images( $content ) {
307
		if ( ! preg_match_all( '/<img [^>]+>/', $content, $matches ) ) {
308
			return $content;
309
		}
310
		$selected_images = array();
311
312
		foreach( $matches[0] as $image_html ) {
313
			if ( preg_match( '/wp-image-([0-9]+)/i', $image_html, $class_id ) &&
314
				( $attachment_id = absint( $class_id[1] ) ) ) {
315
316
				/*
317
				 * If exactly the same image tag is used more than once, overwrite it.
318
				 * All identical tags will be replaced later with 'str_replace()'.
319
				 */
320
				$selected_images[ $attachment_id  ] = $image_html;
321
			}
322
		}
323
324
		foreach ( $selected_images as $attachment_id => $image_html ) {
325
			$attachment = WP_Post::get_instance( $attachment_id );
326
			$attributes = $this->add_data_to_images( array(), $attachment );
327
			$attributes_html = '';
328
			foreach( $attributes as $k => $v ) {
329
				$attributes_html .= esc_attr( $k ) . '="' . esc_attr( $v ) . '"';
330
			}
331
			$image_html_with_data = str_replace( '<img ', "<img $attributes_html", $image_html );
332
			$content = str_replace( $image_html, $image_html_with_data, $content );
333
		}
334
335
		return $content;
336
	}
337
338
	function add_data_to_images( $attr, $attachment = null ) {
339
		$attachment_id   = intval( $attachment->ID );
340
		$orig_file       = wp_get_attachment_image_src( $attachment_id, 'full' );
341
		$orig_file       = isset( $orig_file[0] ) ? $orig_file[0] : wp_get_attachment_url( $attachment_id );
342
		$meta            = wp_get_attachment_metadata( $attachment_id );
343
		$size            = isset( $meta['width'] ) ? intval( $meta['width'] ) . ',' . intval( $meta['height'] ) : '';
344
		$img_meta        = ( ! empty( $meta['image_meta'] ) ) ? (array) $meta['image_meta'] : array();
345
		$comments_opened = intval( comments_open( $attachment_id ) );
346
347
		 /*
348
		 * Note: Cannot generate a filename from the width and height wp_get_attachment_image_src() returns because
349
		 * it takes the $content_width global variable themes can set in consideration, therefore returning sizes
350
		 * which when used to generate a filename will likely result in a 404 on the image.
351
		 * $content_width has no filter we could temporarily de-register, run wp_get_attachment_image_src(), then
352
		 * re-register. So using returned file URL instead, which we can define the sizes from through filename
353
		 * parsing in the JS, as this is a failsafe file reference.
354
		 *
355
		 * EG with Twenty Eleven activated:
356
		 * array(4) { [0]=> string(82) "http://vanillawpinstall.blah/wp-content/uploads/2012/06/IMG_3534-1024x764.jpg" [1]=> int(584) [2]=> int(435) [3]=> bool(true) }
357
		 *
358
		 * EG with Twenty Ten activated:
359
		 * array(4) { [0]=> string(82) "http://vanillawpinstall.blah/wp-content/uploads/2012/06/IMG_3534-1024x764.jpg" [1]=> int(640) [2]=> int(477) [3]=> bool(true) }
360
		 */
361
362
		$medium_file_info = wp_get_attachment_image_src( $attachment_id, 'medium' );
363
		$medium_file      = isset( $medium_file_info[0] ) ? $medium_file_info[0] : '';
364
365
		$large_file_info  = wp_get_attachment_image_src( $attachment_id, 'large' );
366
		$large_file       = isset( $large_file_info[0] ) ? $large_file_info[0] : '';
367
368
		$attachment       = get_post( $attachment_id );
369
		$attachment_title = wptexturize( $attachment->post_title );
370
		$attachment_desc  = wpautop( wptexturize( $attachment->post_content ) );
371
372
		// Not yet providing geo-data, need to "fuzzify" for privacy
373 View Code Duplication
		if ( ! empty( $img_meta ) ) {
374
			foreach ( $img_meta as $k => $v ) {
375
				if ( 'latitude' == $k || 'longitude' == $k )
376
					unset( $img_meta[$k] );
377
			}
378
		}
379
380
		// See https://github.com/Automattic/jetpack/issues/2765
381
		if ( isset( $img_meta['keywords'] ) ) {
382
			unset( $img_meta['keywords'] );
383
		}
384
385
		$img_meta = json_encode( array_map( 'strval', $img_meta ) );
386
387
		$attr['data-attachment-id']     = $attachment_id;
388
		$attr['data-orig-file']         = esc_attr( $orig_file );
389
		$attr['data-orig-size']         = $size;
390
		$attr['data-comments-opened']   = $comments_opened;
391
		$attr['data-image-meta']        = esc_attr( $img_meta );
392
		$attr['data-image-title']       = esc_attr( $attachment_title );
393
		$attr['data-image-description'] = esc_attr( $attachment_desc );
394
		$attr['data-medium-file']       = esc_attr( $medium_file );
395
		$attr['data-large-file']        = esc_attr( $large_file );
396
397
		return $attr;
398
	}
399
400
	function add_data_to_container( $html ) {
401
		global $post;
402
403
		if ( isset( $post ) ) {
404
			$blog_id = (int) get_current_blog_id();
405
406
			$extra_data = array(
407
				'data-carousel-extra' => array(
408
					'blog_id' => $blog_id,
409
					'permalink' => get_permalink( $post->ID ),
410
					)
411
				);
412
413
			/**
414
			 * Filter the data added to the Gallery container.
415
			 *
416
			 * @module carousel
417
			 *
418
			 * @since 1.6.0
419
			 *
420
			 * @param array $extra_data Array of data about the site and the post.
421
			 */
422
			$extra_data = apply_filters( 'jp_carousel_add_data_to_container', $extra_data );
423
			foreach ( (array) $extra_data as $data_key => $data_values ) {
424
				$html = str_replace( '<div ', '<div ' . esc_attr( $data_key ) . "='" . json_encode( $data_values ) . "' ", $html );
425
			}
426
		}
427
428
		return $html;
429
	}
430
431
	function get_attachment_comments() {
432
		if ( ! headers_sent() )
433
			header('Content-type: text/javascript');
434
435
		/**
436
		 * Allows for the checking of privileges of the blog user before comments
437
		 * are packaged as JSON and sent back from the get_attachment_comments
438
		 * AJAX endpoint
439
		 *
440
		 * @module carousel
441
		 *
442
		 * @since 1.6.0
443
		 */
444
		do_action('jp_carousel_check_blog_user_privileges');
445
446
		$attachment_id = ( isset( $_REQUEST['id'] ) ) ? (int) $_REQUEST['id'] : 0;
447
		$offset        = ( isset( $_REQUEST['offset'] ) ) ? (int) $_REQUEST['offset'] : 0;
448
449
		if ( ! $attachment_id ) {
450
			echo json_encode( __( 'Missing attachment ID.', 'jetpack' ) );
451
			die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method get_attachment_comments() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
452
		}
453
454
		if ( $offset < 1 )
455
			$offset = 0;
456
457
		$comments = get_comments( array(
458
			'status'  => 'approve',
459
			'order'   => ( 'asc' == get_option('comment_order') ) ? 'ASC' : 'DESC',
460
			'number'  => 10,
461
			'offset'  => $offset,
462
			'post_id' => $attachment_id,
463
		) );
464
465
		$out      = array();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 6 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
466
467
		// Can't just send the results, they contain the commenter's email address.
468
		foreach ( $comments as $comment ) {
469
			$avatar = get_avatar( $comment->comment_author_email, 64 );
470
			if( ! $avatar )
471
				$avatar = '';
472
			$out[] = array(
473
				'id'              => $comment->comment_ID,
474
				'parent_id'       => $comment->comment_parent,
475
				'author_markup'   => get_comment_author_link( $comment->comment_ID ),
476
				'gravatar_markup' => $avatar,
477
				'date_gmt'        => $comment->comment_date_gmt,
478
				'content'         => wpautop($comment->comment_content),
479
			);
480
		}
481
482
		die( json_encode( $out ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method get_attachment_comments() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
483
	}
484
485
	function post_attachment_comment() {
486
		if ( ! headers_sent() )
487
			header('Content-type: text/javascript');
488
489
		if ( empty( $_POST['nonce'] ) || ! wp_verify_nonce($_POST['nonce'], 'carousel_nonce') )
490
			die( json_encode( array( 'error' => __( 'Nonce verification failed.', 'jetpack' ) ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
491
492
		$_blog_id = (int) $_POST['blog_id'];
493
		$_post_id = (int) $_POST['id'];
494
		$comment = $_POST['comment'];
495
496
		if ( empty( $_blog_id ) )
497
			die( json_encode( array( 'error' => __( 'Missing target blog ID.', 'jetpack' ) ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
498
499
		if ( empty( $_post_id ) )
500
			die( json_encode( array( 'error' => __( 'Missing target post ID.', 'jetpack' ) ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
501
502
		if ( empty( $comment ) )
503
			die( json_encode( array( 'error' => __( 'No comment text was submitted.', 'jetpack' ) ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
504
505
		// Used in context like NewDash
506
		$switched = false;
507
		if ( is_multisite() && $_blog_id != get_current_blog_id() ) {
508
			switch_to_blog( $_blog_id );
509
			$switched = true;
510
		}
511
512
		/** This action is documented in modules/carousel/jetpack-carousel.php */
513
		do_action('jp_carousel_check_blog_user_privileges');
514
515
		if ( ! comments_open( $_post_id ) )
516
			die( json_encode( array( 'error' => __( 'Comments on this post are closed.', 'jetpack' ) ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
517
518
		if ( is_user_logged_in() ) {
519
			$user         = wp_get_current_user();
520
			$user_id      = $user->ID;
521
			$display_name = $user->display_name;
522
			$email        = $user->user_email;
523
			$url          = $user->user_url;
524
525
			if ( empty( $user_id ) )
526
				die( json_encode( array( 'error' => __( 'Sorry, but we could not authenticate your request.', 'jetpack' ) ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
527
		} else {
528
			$user_id      = 0;
529
			$display_name = $_POST['author'];
530
			$email        = $_POST['email'];
531
			$url          = $_POST['url'];
532
533
			if ( get_option( 'require_name_email' ) ) {
534
				if ( empty( $display_name ) )
535
					die( json_encode( array( 'error' => __( 'Please provide your name.', 'jetpack' ) ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
536
537
				if ( empty( $email ) )
538
					die( json_encode( array( 'error' => __( 'Please provide an email address.', 'jetpack' ) ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
539
540
				if ( ! is_email( $email ) )
541
					die( json_encode( array( 'error' => __( 'Please provide a valid email address.', 'jetpack' ) ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
542
			}
543
		}
544
545
		$comment_data =  array(
546
			'comment_content'      => $comment,
547
			'comment_post_ID'      => $_post_id,
548
			'comment_author'       => $display_name,
549
			'comment_author_email' => $email,
550
			'comment_author_url'   => $url,
551
			'comment_approved'     => 0,
552
			'comment_type'         => '',
553
		);
554
555
		if ( ! empty( $user_id ) )
556
			$comment_data['user_id'] = $user_id;
557
558
		// Note: wp_new_comment() sanitizes and validates the values (too).
559
		$comment_id = wp_new_comment( $comment_data );
560
561
		/**
562
		 * Fires before adding a new comment to the database via the get_attachment_comments ajax endpoint.
563
		 *
564
		 * @module carousel
565
		 *
566
		 * @since 1.6.0
567
		 */
568
		do_action( 'jp_carousel_post_attachment_comment' );
569
		$comment_status = wp_get_comment_status( $comment_id );
570
571
		if ( true == $switched )
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
572
			restore_current_blog();
573
574
		die( json_encode( array( 'comment_id' => $comment_id, 'comment_status' => $comment_status ) ) );
0 ignored issues
show
Coding Style Compatibility introduced by
The method post_attachment_comment() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
575
	}
576
577
	function register_settings() {
578
		add_settings_section('carousel_section', __( 'Image Gallery Carousel', 'jetpack' ), array( $this, 'carousel_section_callback' ), 'media');
579
580
		if ( ! $this->in_jetpack ) {
581
			add_settings_field('carousel_enable_it', __( 'Enable carousel', 'jetpack' ), array( $this, 'carousel_enable_it_callback' ), 'media', 'carousel_section' );
582
			register_setting( 'media', 'carousel_enable_it', array( $this, 'carousel_enable_it_sanitize' ) );
583
		}
584
585
		add_settings_field('carousel_background_color', __( 'Background color', 'jetpack' ), array( $this, 'carousel_background_color_callback' ), 'media', 'carousel_section' );
586
		register_setting( 'media', 'carousel_background_color', array( $this, 'carousel_background_color_sanitize' ) );
587
588
		add_settings_field('carousel_display_exif', __( 'Metadata', 'jetpack'), array( $this, 'carousel_display_exif_callback' ), 'media', 'carousel_section' );
589
		register_setting( 'media', 'carousel_display_exif', array( $this, 'carousel_display_exif_sanitize' ) );
590
591
		add_settings_field('carousel_single_image_display_gallery', __( 'Single image', 'jetpack'), array( $this, 'carousel_single_image_display_gallery_callback' ), 'media', 'carousel_section' );
592
		register_setting( 'media', 'carousel_single_image_display_gallery', array( $this, 'carousel_single_image_display_gallery_sanitize' ) );
593
594
		// No geo setting yet, need to "fuzzify" data first, for privacy
595
		// add_settings_field('carousel_display_geo', __( 'Geolocation', 'jetpack' ), array( $this, 'carousel_display_geo_callback' ), 'media', 'carousel_section' );
596
		// register_setting( 'media', 'carousel_display_geo', array( $this, 'carousel_display_geo_sanitize' ) );
597
	}
598
599
	// Fulfill the settings section callback requirement by returning nothing
600
	function carousel_section_callback() {
601
		return;
602
	}
603
604
	function test_1or0_option( $value, $default_to_1 = true ) {
605
		if ( true == $default_to_1 ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
606
			// Binary false (===) of $value means it has not yet been set, in which case we do want to default sites to 1
607
			if ( false === $value )
608
				$value = 1;
609
		}
610
		return ( 1 == $value ) ? 1 : 0;
611
	}
612
613
	function sanitize_1or0_option( $value ) {
614
		return ( 1 == $value ) ? 1 : 0;
615
	}
616
617
	function settings_checkbox($name, $label_text, $extra_text = '', $default_to_checked = true) {
618
		if ( empty( $name ) )
619
			return;
620
		$option = $this->test_1or0_option( get_option( $name ), $default_to_checked );
621
		echo '<fieldset>';
622
		echo '<input type="checkbox" name="'.esc_attr($name).'" id="'.esc_attr($name).'" value="1" ';
623
		checked( '1', $option );
624
		echo '/> <label for="'.esc_attr($name).'">'.$label_text.'</label>';
625
		if ( ! empty( $extra_text ) )
626
			echo '<p class="description">'.$extra_text.'</p>';
627
		echo '</fieldset>';
628
	}
629
630
	function settings_select($name, $values, $extra_text = '') {
631
		if ( empty( $name ) || ! is_array( $values ) || empty( $values ) )
632
			return;
633
		$option = get_option( $name );
634
		echo '<fieldset>';
635
		echo '<select name="'.esc_attr($name).'" id="'.esc_attr($name).'">';
636
		foreach( $values as $key => $value ) {
637
			echo '<option value="'.esc_attr($key).'" ';
638
			selected( $key, $option );
639
			echo '>'.esc_html($value).'</option>';
640
		}
641
		echo '</select>';
642
		if ( ! empty( $extra_text ) )
643
			echo '<p class="description">'.$extra_text.'</p>';
644
		echo '</fieldset>';
645
	}
646
647
	function carousel_display_exif_callback() {
648
		$this->settings_checkbox( 'carousel_display_exif', __( 'Show photo metadata (<a href="http://en.wikipedia.org/wiki/Exchangeable_image_file_format" target="_blank">Exif</a>) in carousel, when available.', 'jetpack' ) );
649
	}
650
651
	function carousel_display_exif_sanitize( $value ) {
652
		return $this->sanitize_1or0_option( $value );
653
	}
654
655
	function carousel_display_geo_callback() {
656
		$this->settings_checkbox( 'carousel_display_geo', __( 'Show map of photo location in carousel, when available.', 'jetpack' ) );
657
	}
658
659
	function carousel_display_geo_sanitize( $value ) {
660
		return $this->sanitize_1or0_option( $value );
661
	}
662
663
	function carousel_background_color_callback() {
664
		$this->settings_select( 'carousel_background_color', array( 'black' => __( 'Black', 'jetpack' ), 'white' => __( 'White', 'jetpack', 'jetpack' ) ) );
665
	}
666
667
	function carousel_background_color_sanitize( $value ) {
668
		return ( 'white' == $value ) ? 'white' : 'black';
669
	}
670
671
	function carousel_single_image_display_gallery_callback() {
672
		$this->settings_checkbox( 'carousel_single_image_display_gallery', __( 'When linking to \'Attachment Page\' open in Carousel Lightbox.', 'jetpack' ) );
673
	}
674
675
	function carousel_single_image_display_gallery_sanitize( $value ) {
676
		return $this->sanitize_1or0_option( $value );
677
	}
678
679
	function carousel_enable_it_callback() {
680
		$this->settings_checkbox( 'carousel_enable_it', __( 'Display images in full-size carousel slideshow.', 'jetpack' ) );
681
	}
682
683
	function carousel_enable_it_sanitize( $value ) {
684
		return $this->sanitize_1or0_option( $value );
685
	}
686
}
687
688
new Jetpack_Carousel;
689