Completed
Push — fix/image-migration-script ( 1bd527...fdd408 )
by
unknown
09:39
created

class.wpcom-json-api-post-endpoint.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
4
	public $post_object_format = array(
5
		// explicitly document and cast all output
6
		'ID'        => '(int) The post ID.',
7
		'site_ID'		=> '(int) The site ID.',
8
		'author'    => '(object>author) The author of the post.',
9
		'date'      => "(ISO 8601 datetime) The post's creation time.",
10
		'modified'  => "(ISO 8601 datetime) The post's most recent update time.",
11
		'title'     => '(HTML) <code>context</code> dependent.',
12
		'URL'       => '(URL) The full permalink URL to the post.',
13
		'short_URL' => '(URL) The wp.me short URL.',
14
		'content'   => '(HTML) <code>context</code> dependent.',
15
		'excerpt'   => '(HTML) <code>context</code> dependent.',
16
		'slug'      => '(string) The name (slug) for the post, used in URLs.',
17
		'guid'      => '(string) The GUID for the post.',
18
		'status'    => array(
19
			'publish' => 'The post is published.',
20
			'draft'   => 'The post is saved as a draft.',
21
			'pending' => 'The post is pending editorial approval.',
22
			'private' => 'The post is published privately',
23
			'future'  => 'The post is scheduled for future publishing.',
24
			'trash'   => 'The post is in the trash.',
25
			'auto-draft' => 'The post is a placeholder for a new post.',
26
		),
27
		'sticky'   => '(bool) Is the post sticky?',
28
		'password' => '(string) The plaintext password protecting the post, or, more likely, the empty string if the post is not password protected.',
29
		'parent'   => "(object>post_reference|false) A reference to the post's parent, if it has one.",
30
		'type'     => "(string) The post's post_type. Post types besides post, page and revision need to be whitelisted using the <code>rest_api_allowed_post_types</code> filter.",
31
		'comments_open'  => '(bool) Is the post open for comments?',
32
		'pings_open'     => '(bool) Is the post open for pingbacks, trackbacks?',
33
		'likes_enabled' => "(bool) Is the post open to likes?",
34
		'sharing_enabled' => "(bool) Should sharing buttons show on this post?",
35
		'comment_count'  => '(int) The number of comments for this post.',
36
		'like_count'     => '(int) The number of likes for this post.',
37
		'i_like'         => '(bool) Does the current user like this post?',
38
		'is_reblogged'   => '(bool) Did the current user reblog this post?',
39
		'is_following'   => '(bool) Is the current user following this blog?',
40
		'global_ID'      => '(string) A unique WordPress.com-wide representation of a post.',
41
		'featured_image' => '(URL) The URL to the featured image for this post if it has one.',
42
		'post_thumbnail' => '(object>attachment) The attachment object for the featured image if it has one.',
43
		'format'         => array(), // see constructor
44
		'geo'            => '(object>geo|false)',
45
		'menu_order'     => '(int) (Pages Only) The order pages should appear in.',
46
		'publicize_URLs' => '(array:URL) Array of Twitter and Facebook URLs published by this post.',
47
		'tags'           => '(object:tag) Hash of tags (keyed by tag name) applied to the post.',
48
		'categories'     => '(object:category) Hash of categories (keyed by category name) applied to the post.',
49
		'attachments'	 => '(object:attachment) Hash of post attachments (keyed by attachment ID).',
50
		'metadata'	     => '(array) Array of post metadata keys and values. All unprotected meta keys are available by default for read requests. Both unprotected and protected meta keys are available for authenticated requests with access. Protected meta keys can be made available with the <code>rest_api_allowed_public_metadata</code> filter.',
51
		'meta'           => '(object) API result meta data',
52
		'current_user_can' => '(object) List of permissions. Note, deprecated in favor of `capabilities`',
53
		'capabilities'   => '(object) List of post-specific permissions for the user; publish_post, edit_post, delete_post',
54
	);
55
56
	// public $response_format =& $this->post_object_format;
57
58 View Code Duplication
	function __construct( $args ) {
59
		if ( is_array( $this->post_object_format ) && isset( $this->post_object_format['format'] ) ) {
60
			$this->post_object_format['format'] = get_post_format_strings();
61
		}
62
		if ( !$this->response_format ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->response_format of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
63
			$this->response_format =& $this->post_object_format;
64
		}
65
		parent::__construct( $args );
66
	}
67
68
	function the_password_form() {
69
		return __( 'This post is password protected.', 'jetpack' );
70
	}
71
72
	/**
73
	 * Get a post by a specified field and value
74
	 *
75
	 * @param string $field
76
	 * @param string $field_value
77
	 * @param string $context Post use context (e.g. 'display')
78
	 * @return array Post
79
	 **/
80
	function get_post_by( $field, $field_value, $context = 'display' ) {
81
		global $blog_id;
82
83
		/** This filter is documented in class.json-api-endpoints.php */
84
		$is_jetpack = true === apply_filters( 'is_jetpack_site', false, $blog_id );
85
86
		if ( defined( 'GEO_LOCATION__CLASS' ) && class_exists( GEO_LOCATION__CLASS ) ) {
87
			$geo = call_user_func( array( GEO_LOCATION__CLASS, 'init' ) );
88
		} else {
89
			$geo = false;
90
		}
91
92 View Code Duplication
		if ( 'display' === $context ) {
93
			$args = $this->query_args();
94
			if ( isset( $args['content_width'] ) && $args['content_width'] ) {
95
				$GLOBALS['content_width'] = (int) $args['content_width'];
96
			}
97
		}
98
99 View Code Duplication
		if ( strpos( $_SERVER['HTTP_USER_AGENT'], 'wp-windows8' ) ) {
100
			remove_shortcode( 'gallery', 'gallery_shortcode' );
101
			add_shortcode( 'gallery', array( &$this, 'win8_gallery_shortcode' ) );
102
		}
103
104
		switch ( $field ) {
105
		case 'name' :
106
			$post_id = $this->get_post_id_by_name( $field_value );
107
			if ( is_wp_error( $post_id ) ) {
108
				return $post_id;
109
			}
110
			break;
111
		default :
112
			$post_id = (int) $field_value;
113
			break;
114
		}
115
116
		$post = get_post( $post_id, OBJECT, $context );
117
118
		if ( !$post || is_wp_error( $post ) ) {
119
			return new WP_Error( 'unknown_post', 'Unknown post', 404 );
120
		}
121
122
		if ( ! $this->is_post_type_allowed( $post->post_type ) && ( ! function_exists( 'is_post_freshly_pressed' ) || ! is_post_freshly_pressed( $post->ID ) ) ) {
123
			return new WP_Error( 'unknown_post', 'Unknown post', 404 );
124
		}
125
126
		// Permissions
127
		$capabilities = $this->get_current_user_capabilities( $post );
128
129
		switch ( $context ) {
130
		case 'edit' :
131
			if ( ! $capabilities['edit_post'] ) {
132
				return new WP_Error( 'unauthorized', 'User cannot edit post', 403 );
133
			}
134
			break;
135
		case 'display' :
136
			break;
137
		default :
138
			return new WP_Error( 'invalid_context', 'Invalid API CONTEXT', 400 );
139
		}
140
141
		$can_view = $this->user_can_view_post( $post->ID );
142
		if ( !$can_view || is_wp_error( $can_view ) ) {
143
			return $can_view;
144
		}
145
146
		$GLOBALS['post'] = $post;
147
148
		if ( 'display' === $context ) {
149
			setup_postdata( $post );
150
		}
151
152
		$response = array();
153
154
		$fields = null;
155
		if ( 'display' === $context && ! empty( $this->api->query['fields'] )  ) {
156
			$fields = array_fill_keys( array_map( 'trim', explode( ',', $this->api->query['fields'] ) ), true );
157
		}
158
159
		foreach ( array_keys( $this->post_object_format ) as $key ) {
160
			if ( $fields !== null && ! isset( $fields[$key] ) ) {
161
				continue;
162
			}
163
			switch ( $key ) {
164
			case 'ID' :
165
				// explicitly cast all output
166
				$response[$key] = (int) $post->ID;
167
				break;
168
			case 'site_ID' :
169
				$response[$key] = (int) $this->api->get_blog_id_for_output();
170
				break;
171
			case 'author' :
172
				$response[$key] = (object) $this->get_author( $post, 'edit' === $context && $capabilities['edit_post'] );
173
				break;
174
			case 'date' :
175
				$response[$key] = (string) $this->format_date( $post->post_date_gmt, $post->post_date );
176
				break;
177
			case 'modified' :
178
				$response[$key] = (string) $this->format_date( $post->post_modified_gmt, $post->post_modified );
179
				break;
180
			case 'title' :
181 View Code Duplication
				if ( 'display' === $context ) {
182
					$response[$key] = (string) get_the_title( $post->ID );
183
				} else {
184
					$response[$key] = (string) htmlspecialchars_decode( $post->post_title, ENT_QUOTES );
185
				}
186
				break;
187
			case 'URL' :
188
				if ( 'revision' === $post->post_type ) {
189
					$response[$key] = (string) esc_url_raw( get_permalink( $post->post_parent ) );
190
				} else {
191
					$response[$key] = (string) esc_url_raw( get_permalink( $post->ID ) );
192
				}
193
				break;
194
			case 'short_URL' :
195
				$response[$key] = (string) esc_url_raw( wp_get_shortlink( $post->ID ) );
196
				break;
197
			case 'content' :
198
				if ( 'display' === $context ) {
199
					add_filter( 'the_password_form', array( $this, 'the_password_form' ) );
200
					$response[$key] = (string) $this->get_the_post_content_for_display();
201
					remove_filter( 'the_password_form', array( $this, 'the_password_form' ) );
202
				} else {
203
					$response[$key] = (string) $post->post_content;
204
				}
205
				break;
206
			case 'excerpt' :
207
				if ( 'display' === $context ) {
208
					add_filter( 'the_password_form', array( $this, 'the_password_form' ) );
209
					ob_start();
210
					the_excerpt();
211
					$response[$key] = (string) ob_get_clean();
212
					remove_filter( 'the_password_form', array( $this, 'the_password_form' ) );
213
				} else {
214
					$response[$key] = htmlspecialchars_decode( (string) $post->post_excerpt, ENT_QUOTES );
215
				}
216
				break;
217
			case 'status' :
218
				$response[$key] = (string) get_post_status( $post->ID );
219
				break;
220
			case 'sticky' :
221
				$response[$key] = (bool) is_sticky( $post->ID );
222
				break;
223
			case 'slug' :
224
				$response[$key] = (string) $post->post_name;
225
				break;
226
			case 'guid' :
227
				$response[$key] = (string) $post->guid;
228
				break;
229
			case 'password' :
230
				$response[$key] = (string) $post->post_password;
231
				if ( 'edit' === $context ) {
232
					$response[$key] = htmlspecialchars_decode( (string) $response[$key], ENT_QUOTES );
233
				}
234
				break;
235
			case 'parent' : // (object|false)
236
				if ( $post->post_parent ) {
237
					$parent         = get_post( $post->post_parent );
238 View Code Duplication
					if ( 'display' === $context ) {
239
						$parent_title = (string) get_the_title( $parent->ID );
240
					} else {
241
						$parent_title = (string) htmlspecialchars_decode( $post->post_title, ENT_QUOTES );
242
					}
243
					$response[$key] = (object) array(
244
						'ID'   => (int) $parent->ID,
245
						'type' => (string) $parent->post_type,
246
						'link' => (string) $this->links->get_post_link( $this->api->get_blog_id_for_output(), $parent->ID ),
247
						'title' => $parent_title,
248
					);
249
				} else {
250
					$response[$key] = false;
251
				}
252
				break;
253
			case 'type' :
254
				$response[$key] = (string) $post->post_type;
255
				break;
256
			case 'comments_open' :
257
				$response[$key] = (bool) comments_open( $post->ID );
258
				break;
259
			case 'pings_open' :
260
				$response[$key] = (bool) pings_open( $post->ID );
261
				break;
262
			case 'likes_enabled' :
263
				/** This filter is documented in modules/likes.php */
264
				$sitewide_likes_enabled = (bool) apply_filters( 'wpl_is_enabled_sitewide', ! get_option( 'disabled_likes' ) );
265
				$post_likes_switched    = (bool) get_post_meta( $post->ID, 'switch_like_status', true );
266
				$post_likes_enabled = $sitewide_likes_enabled;
267
				if ( $post_likes_switched ) {
268
					$post_likes_enabled = ! $post_likes_enabled;
269
				}
270
				$response[$key] = (bool) $post_likes_enabled;
271
				break;
272
			case 'sharing_enabled' :
273
				$show = true;
274
				/** This filter is documented in modules/sharedaddy/sharing-service.php */
275
				$show = apply_filters( 'sharing_show', $show, $post );
276
277
				$switched_status = get_post_meta( $post->ID, 'sharing_disabled', false );
278
279
				if ( !empty( $switched_status ) )
280
					$show = false;
281
				$response[$key] = (bool) $show;
282
				break;
283
			case 'comment_count' :
284
				$response[$key] = (int) $post->comment_count;
285
				break;
286
			case 'like_count' :
287
				$response[$key] = (int) $this->api->post_like_count( $blog_id, $post->ID );
288
				break;
289
			case 'i_like'     :
290
				$response[$key] = (bool) $this->api->is_liked( $blog_id, $post->ID );
291
				break;
292
			case 'is_reblogged':
293
				$response[$key] = (bool) $this->api->is_reblogged( $blog_id, $post->ID );
294
				break;
295
			case 'is_following':
296
				$response[$key] = (bool) $this->api->is_following( $blog_id );
297
				break;
298
			case 'global_ID':
299
				$response[$key] = (string) $this->api->add_global_ID( $blog_id, $post->ID );
300
				break;
301
			case 'featured_image' :
302
				if ( $is_jetpack && ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
303
					$response[ $key ] = get_post_meta( $post->ID, '_jetpack_featured_image', true );
304
				} else {
305
					$image_attributes = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'full' );
306
					if ( is_array( $image_attributes ) && isset( $image_attributes[0] ) ) {
307
						$response[ $key ] = (string) $image_attributes[0];
308
					} else {
309
						$response[ $key ] = '';
310
					}
311
				}
312
				break;
313
			case 'post_thumbnail' :
314
				$response[$key] = null;
315
316
				$thumb_id = get_post_thumbnail_id( $post->ID );
317 View Code Duplication
				if ( ! empty( $thumb_id ) ) {
318
					$attachment = get_post( $thumb_id );
319
					if ( ! empty( $attachment ) )
320
						$featured_image_object = $this->get_attachment( $attachment );
321
322
					if ( ! empty( $featured_image_object ) ) {
323
						$response[$key] = (object) $featured_image_object;
324
					}
325
				}
326
				break;
327
			case 'format' :
328
				$response[$key] = (string) get_post_format( $post->ID );
329
				if ( !$response[$key] ) {
330
					$response[$key] = 'standard';
331
				}
332
				break;
333
			case 'geo' : // (object|false)
334
				if ( !$geo ) {
335
					$response[$key] = false;
336
				} else {
337
					$geo_data       = $geo->get_geo( 'post', $post->ID );
338
					$response[$key] = false;
339
					if ( $geo_data ) {
340
						$geo_data = array_intersect_key( $geo_data, array( 'latitude' => true, 'longitude' => true, 'address' => true, 'public' => true ) );
341
						if ( $geo_data ) {
342
							$response[$key] = (object) array(
343
								'latitude'  => isset( $geo_data['latitude']  ) ? (float)  $geo_data['latitude']  : 0,
344
								'longitude' => isset( $geo_data['longitude'] ) ? (float)  $geo_data['longitude'] : 0,
345
								'address'   => isset( $geo_data['address'] )   ? (string) $geo_data['address']   : '',
346
							);
347
						} else {
348
							$response[$key] = false;
349
						}
350
						// Private
351
						if ( !isset( $geo_data['public'] ) || !$geo_data['public'] ) {
352
							if ( 'edit' !== $context || ! $capabilities['edit_post'] ) {
353
								// user can't access
354
								$response[$key] = false;
355
							}
356
						}
357
					}
358
				}
359
				break;
360
			case 'menu_order':
361
				$response[$key] = (int) $post->menu_order;
362
				break;
363
			case 'publicize_URLs' :
364
				$publicize_URLs = array();
365
				$publicize      = get_post_meta( $post->ID, 'publicize_results', true );
366 View Code Duplication
				if ( $publicize ) {
367
					foreach ( $publicize as $service => $data ) {
368
						switch ( $service ) {
369
						case 'twitter' :
370
							foreach ( $data as $datum ) {
371
								$publicize_URLs[] = esc_url_raw( "https://twitter.com/{$datum['user_id']}/status/{$datum['post_id']}" );
372
							}
373
							break;
374
						case 'fb' :
375
							foreach ( $data as $datum ) {
376
								$publicize_URLs[] = esc_url_raw( "https://www.facebook.com/permalink.php?story_fbid={$datum['post_id']}&id={$datum['user_id']}" );
377
							}
378
							break;
379
						}
380
					}
381
				}
382
				$response[$key] = (array) $publicize_URLs;
383
				break;
384
			case 'tags' :
385
				$response[$key] = array();
386
				$terms = wp_get_post_tags( $post->ID );
387
				foreach ( $terms as $term ) {
388
					if ( !empty( $term->name ) ) {
389
						$response[$key][$term->name] = $this->format_taxonomy( $term, 'post_tag', 'display' );
390
					}
391
				}
392
				$response[$key] = (object) $response[$key];
393
				break;
394
			case 'categories':
395
				$response[$key] = array();
396
				$terms = wp_get_object_terms( $post->ID, 'category', array( 'fields' => 'all' ) );
397 View Code Duplication
				foreach ( $terms as $term ) {
398
					if ( !empty( $term->name ) ) {
399
						$response[$key][$term->name] = $this->format_taxonomy( $term, 'category', 'display' );
400
					}
401
				}
402
				$response[$key] = (object) $response[$key];
403
				break;
404
			case 'attachments':
405
				$response[$key] = array();
406
				$_attachments = get_posts( array( 'post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'posts_per_page' => 100 ) );
407
				foreach ( $_attachments as $attachment ) {
408
					$response[$key][$attachment->ID] = $this->get_attachment( $attachment );
409
				}
410
				$response[$key] = (object) $response[$key];
411
				break;
412
			case 'metadata' : // (array|false)
413
				$metadata = array();
414
				foreach ( (array) has_meta( $post_id ) as $meta ) {
415
					// Don't expose protected fields.
416
					$show = false;
417
					if ( WPCOM_JSON_API_Metadata::is_public( $meta['meta_key'] ) )
418
						$show = true;
419
					if ( current_user_can( 'edit_post_meta', $post_id , $meta['meta_key'] ) )
420
						$show = true;
421
422
					// Only business plan subscribers can view custom meta description.
423
					if ( Jetpack_SEO_Posts::DESCRIPTION_META_KEY === $meta['meta_key'] && ! Jetpack_SEO_Utils::is_enabled_jetpack_seo() ) {
424
						$show = false;
425
					}
426
427
					if ( !$show )
428
						continue;
429
430
					$metadata[] = array(
431
						'id'    => $meta['meta_id'],
432
						'key'   => $meta['meta_key'],
433
						'value' => maybe_unserialize( $meta['meta_value'] ),
434
					);
435
				}
436
437
				if ( ! empty( $metadata ) ) {
438
					$response[$key] = $metadata;
439
				} else {
440
					$response[$key] = false;
441
				}
442
				break;
443
			case 'meta' :
444
				$response[$key] = (object) array(
445
					'links' => (object) array(
446
						'self'    => (string) $this->links->get_post_link( $this->api->get_blog_id_for_output(), $post->ID ),
447
						'help'    => (string) $this->links->get_post_link( $this->api->get_blog_id_for_output(), $post->ID, 'help' ),
448
						'site'    => (string) $this->links->get_site_link( $this->api->get_blog_id_for_output() ),
449
						'replies' => (string) $this->links->get_post_link( $this->api->get_blog_id_for_output(), $post->ID, 'replies/' ),
450
						'likes'   => (string) $this->links->get_post_link( $this->api->get_blog_id_for_output(), $post->ID, 'likes/' ),
451
					),
452
				);
453
				break;
454
			case 'current_user_can' :
455
				$response[$key] = $capabilities;
456
				break;
457
			case 'capabilities' :
458
				$response[$key] = $capabilities;
459
				break;
460
461
			}
462
		}
463
464
		// WPCOM_JSON_API_Post_Endpoint::find_featured_worthy_media( $post );
465
		// $response['featured_media'] = self::find_featured_media( $response );
466
467
		unset( $GLOBALS['post'] );
468
		return $response;
469
	}
470
471
	// No Blog ID parameter.  No Post ID parameter.  Depends on globals.
472
	// Expects setup_postdata() to already have been run
473 View Code Duplication
	function get_the_post_content_for_display() {
474
		global $pages, $page;
475
476
		$old_pages = $pages;
477
		$old_page  = $page;
478
479
		$content = join( "\n\n", $pages );
480
		$content = preg_replace( '/<!--more(.*?)?-->/', '', $content );
481
		$pages   = array( $content );
482
		$page    = 1;
483
484
		ob_start();
485
		the_content();
486
		$return = ob_get_clean();
487
488
		$pages = $old_pages;
489
		$page  = $old_page;
490
491
		return $return;
492
	}
493
494 View Code Duplication
	function get_blog_post( $blog_id, $post_id, $context = 'display' ) {
495
		$blog_id = $this->api->get_blog_id( $blog_id );
496
		if ( !$blog_id || is_wp_error( $blog_id ) ) {
497
			return $blog_id;
498
		}
499
		switch_to_blog( $blog_id );
500
		$post = $this->get_post_by( 'ID', $post_id, $context );
501
		restore_current_blog();
502
		return $post;
503
	}
504
505
	/**
506
	 * Supporting featured media in post endpoints. Currently on for wpcom blogs
507
	 * since it's calling WPCOM_JSON_API_Read_Endpoint methods which presently
508
	 * rely on wpcom specific functionality.
509
	 *
510
	 * @param WP_Post $post
511
	 * @return object list of featured media
512
	 */
513
	public static function find_featured_media( &$post ) {
514
515
		if ( class_exists( 'WPCOM_JSON_API_Read_Endpoint' ) ) {
516
			return WPCOM_JSON_API_Read_Endpoint::find_featured_worthy_media( (array) $post );
517
		} else {
518
			return (object) array();
519
		}
520
521
	}
522
523
524
525 View Code Duplication
	function win8_gallery_shortcode( $attr ) {
526
		global $post;
527
528
		static $instance = 0;
529
		$instance++;
530
531
		$output = '';
532
533
		// We're trusting author input, so let's at least make sure it looks like a valid orderby statement
534
		if ( isset( $attr['orderby'] ) ) {
535
			$attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
536
			if ( !$attr['orderby'] )
537
				unset( $attr['orderby'] );
538
		}
539
540
		extract( shortcode_atts( array(
541
			'order'     => 'ASC',
542
			'orderby'   => 'menu_order ID',
543
			'id'        => $post->ID,
544
			'include'   => '',
545
			'exclude'   => '',
546
			'slideshow' => false
547
		), $attr, 'gallery' ) );
548
549
		// Custom image size and always use it
550
		add_image_size( 'win8app-column', 480 );
551
		$size = 'win8app-column';
552
553
		$id = intval( $id );
554
		if ( 'RAND' === $order )
555
			$orderby = 'none';
556
557
		if ( !empty( $include ) ) {
558
			$include      = preg_replace( '/[^0-9,]+/', '', $include );
559
			$_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
560
			$attachments  = array();
561
			foreach ( $_attachments as $key => $val ) {
562
				$attachments[$val->ID] = $_attachments[$key];
563
			}
564
		} elseif ( !empty( $exclude ) ) {
565
			$exclude     = preg_replace( '/[^0-9,]+/', '', $exclude );
566
			$attachments = get_children( array( 'post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
567
		} else {
568
			$attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
569
		}
570
571
		if ( ! empty( $attachments ) ) {
572
			foreach ( $attachments as $id => $attachment ) {
573
				$link = isset( $attr['link'] ) && 'file' === $attr['link'] ? wp_get_attachment_link( $id, $size, false, false ) : wp_get_attachment_link( $id, $size, true, false );
574
575
				if ( $captiontag && trim($attachment->post_excerpt) ) {
576
					$output .= "<div class='wp-caption aligncenter'>$link
577
						<p class='wp-caption-text'>" . wptexturize($attachment->post_excerpt) . "</p>
578
						</div>";
579
				} else {
580
					$output .= $link . ' ';
581
				}
582
			}
583
		}
584
	}
585
586
	/**
587
	 * Returns attachment object.
588
	 *
589
	 * @param $attachment attachment row
590
	 *
591
	 * @return (object)
592
	 */
593 View Code Duplication
	function get_attachment( $attachment ) {
594
		$metadata = wp_get_attachment_metadata( $attachment->ID );
595
596
		$result = array(
597
			'ID'		=> (int) $attachment->ID,
598
			'URL'           => (string) wp_get_attachment_url( $attachment->ID ),
599
			'guid'		=> (string) $attachment->guid,
600
			'mime_type'	=> (string) $attachment->post_mime_type,
601
			'width'		=> (int) isset( $metadata['width']  ) ? $metadata['width']  : 0,
602
			'height'	=> (int) isset( $metadata['height'] ) ? $metadata['height'] : 0,
603
		);
604
605
		if ( isset( $metadata['duration'] ) ) {
606
			$result['duration'] = (int) $metadata['duration'];
607
		}
608
609
		return (object) apply_filters( 'get_attachment', $result );
610
	}
611
612
	/**
613
	 * Get post-specific user capabilities
614
	 * @param  WP_Post $post              post object
615
	 * @return array                     array of post-level permissions; 'publish_post', 'delete_post', 'edit_post'
616
	 */
617
	function get_current_user_capabilities( $post ) {
618
		return array(
619
			'publish_post' => current_user_can( 'publish_post', $post ),
620
			'delete_post'  => current_user_can( 'delete_post', $post ),
621
			'edit_post'    => current_user_can( 'edit_post', $post )
622
		);
623
	}
624
625
	/**
626
	 * Get post ID by name
627
	 *
628
	 * Attempts to match name on post title and page path
629
	 *
630
	 * @param string $name
631
	 *
632
	 * @return int|object Post ID on success, WP_Error object on failure
633
	 **/
634
	protected function get_post_id_by_name( $name ) {
635
		$name = sanitize_title( $name );
636
637
		if ( ! $name ) {
638
			return new WP_Error( 'invalid_post', 'Invalid post', 400 );
639
		}
640
641
		$posts = get_posts( array(
642
			'name' => $name,
643
			'numberposts' => 1,
644
			'post_type' => $this->_get_whitelisted_post_types(),
645
		) );
646
647
		if ( ! $posts || ! isset( $posts[0]->ID ) || ! $posts[0]->ID ) {
648
			$page = get_page_by_path( $name );
649
650
			if ( ! $page ) {
651
				return new WP_Error( 'unknown_post', 'Unknown post', 404 );
652
			}
653
654
			$post_id = $page->ID;
655
		} else {
656
			$post_id = (int) $posts[0]->ID;
657
		}
658
659
		return $post_id;
660
	}
661
}
662