Completed
Push — update/dialogue-focus-on-conte... ( 9f1745...fa862f )
by
unknown
80:03 queued 71:18
created

class.wpcom-json-api-post-endpoint.php (8 issues)

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 ) {
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 );
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $blog_id.

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.

Loading history...
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 );
0 ignored issues
show
The call to WP_Error::__construct() has too many arguments starting with 'unknown_post'.

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.

Loading history...
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 );
0 ignored issues
show
The call to WP_Error::__construct() has too many arguments starting with 'unknown_post'.

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.

Loading history...
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 );
0 ignored issues
show
The call to WP_Error::__construct() has too many arguments starting with 'unauthorized'.

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.

Loading history...
133
			}
134
			break;
135
		case 'display' :
136
			break;
137
		default :
138
			return new WP_Error( 'invalid_context', 'Invalid API CONTEXT', 400 );
0 ignored issues
show
The call to WP_Error::__construct() has too many arguments starting with 'invalid_context'.

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.

Loading history...
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    = get_post_meta( $post->ID, 'switch_like_status', true );
266
				$post_likes_enabled = $post_likes_switched || ( $sitewide_likes_enabled && $post_likes_switched !== '0' );
267
				$response[$key] = (bool) $post_likes_enabled;
268
				break;
269
			case 'sharing_enabled' :
270
				$show = true;
271
				/** This filter is documented in modules/sharedaddy/sharing-service.php */
272
				$show = apply_filters( 'sharing_show', $show, $post );
0 ignored issues
show
The call to apply_filters() has too many arguments starting with $post.

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.

Loading history...
273
274
				$switched_status = get_post_meta( $post->ID, 'sharing_disabled', false );
275
276
				if ( !empty( $switched_status ) )
277
					$show = false;
278
				$response[$key] = (bool) $show;
279
				break;
280
			case 'comment_count' :
281
				$response[$key] = (int) $post->comment_count;
282
				break;
283
			case 'like_count' :
284
				$response[$key] = (int) $this->api->post_like_count( $blog_id, $post->ID );
285
				break;
286
			case 'i_like'     :
287
				$response[$key] = (bool) $this->api->is_liked( $blog_id, $post->ID );
288
				break;
289
			case 'is_reblogged':
290
				$response[$key] = (bool) $this->api->is_reblogged( $blog_id, $post->ID );
291
				break;
292
			case 'is_following':
293
				$response[$key] = (bool) $this->api->is_following( $blog_id );
294
				break;
295
			case 'global_ID':
296
				$response[$key] = (string) $this->api->add_global_ID( $blog_id, $post->ID );
297
				break;
298
			case 'featured_image' :
299
				if ( $is_jetpack && ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
300
					$response[ $key ] = get_post_meta( $post->ID, '_jetpack_featured_image', true );
301
				} else {
302
					$image_attributes = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'full' );
303
					if ( is_array( $image_attributes ) && isset( $image_attributes[0] ) ) {
304
						$response[ $key ] = (string) $image_attributes[0];
305
					} else {
306
						$response[ $key ] = '';
307
					}
308
				}
309
				break;
310
			case 'post_thumbnail' :
311
				$response[$key] = null;
312
313
				$thumb_id = get_post_thumbnail_id( $post->ID );
314 View Code Duplication
				if ( ! empty( $thumb_id ) ) {
315
					$attachment = get_post( $thumb_id );
316
					if ( ! empty( $attachment ) )
317
						$featured_image_object = $this->get_attachment( $attachment );
318
319
					if ( ! empty( $featured_image_object ) ) {
320
						$response[$key] = (object) $featured_image_object;
321
					}
322
				}
323
				break;
324
			case 'format' :
325
				$response[$key] = (string) get_post_format( $post->ID );
326
				if ( !$response[$key] ) {
327
					$response[$key] = 'standard';
328
				}
329
				break;
330
			case 'geo' : // (object|false)
331
				if ( !$geo ) {
332
					$response[$key] = false;
333
				} else {
334
					$geo_data       = $geo->get_geo( 'post', $post->ID );
335
					$response[$key] = false;
336
					if ( $geo_data ) {
337
						$geo_data = array_intersect_key( $geo_data, array( 'latitude' => true, 'longitude' => true, 'address' => true, 'public' => true ) );
338
						if ( $geo_data ) {
339
							$response[$key] = (object) array(
340
								'latitude'  => isset( $geo_data['latitude']  ) ? (float)  $geo_data['latitude']  : 0,
341
								'longitude' => isset( $geo_data['longitude'] ) ? (float)  $geo_data['longitude'] : 0,
342
								'address'   => isset( $geo_data['address'] )   ? (string) $geo_data['address']   : '',
343
							);
344
						} else {
345
							$response[$key] = false;
346
						}
347
						// Private
348
						if ( !isset( $geo_data['public'] ) || !$geo_data['public'] ) {
349
							if ( 'edit' !== $context || ! $capabilities['edit_post'] ) {
350
								// user can't access
351
								$response[$key] = false;
352
							}
353
						}
354
					}
355
				}
356
				break;
357
			case 'menu_order':
358
				$response[$key] = (int) $post->menu_order;
359
				break;
360
			case 'publicize_URLs' :
361
				$publicize_URLs = array();
362
				$publicize      = get_post_meta( $post->ID, 'publicize_results', true );
363 View Code Duplication
				if ( $publicize ) {
364
					foreach ( $publicize as $service => $data ) {
365
						switch ( $service ) {
366
						case 'twitter' :
367
							foreach ( $data as $datum ) {
368
								$publicize_URLs[] = esc_url_raw( "https://twitter.com/{$datum['user_id']}/status/{$datum['post_id']}" );
369
							}
370
							break;
371
						case 'fb' :
372
							foreach ( $data as $datum ) {
373
								$publicize_URLs[] = esc_url_raw( "https://www.facebook.com/permalink.php?story_fbid={$datum['post_id']}&id={$datum['user_id']}" );
374
							}
375
							break;
376
						}
377
					}
378
				}
379
				$response[$key] = (array) $publicize_URLs;
380
				break;
381
			case 'tags' :
382
				$response[$key] = array();
383
				$terms = wp_get_post_tags( $post->ID );
384
				foreach ( $terms as $term ) {
385
					if ( !empty( $term->name ) ) {
386
						$response[$key][$term->name] = $this->format_taxonomy( $term, 'post_tag', 'display' );
387
					}
388
				}
389
				$response[$key] = (object) $response[$key];
390
				break;
391
			case 'categories':
392
				$response[$key] = array();
393
				$terms = wp_get_object_terms( $post->ID, 'category', array( 'fields' => 'all' ) );
394 View Code Duplication
				foreach ( $terms as $term ) {
395
					if ( !empty( $term->name ) ) {
396
						$response[$key][$term->name] = $this->format_taxonomy( $term, 'category', 'display' );
397
					}
398
				}
399
				$response[$key] = (object) $response[$key];
400
				break;
401
			case 'attachments':
402
				$response[$key] = array();
403
				$_attachments = get_posts( array( 'post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'posts_per_page' => 100 ) );
404
				foreach ( $_attachments as $attachment ) {
405
					$response[$key][$attachment->ID] = $this->get_attachment( $attachment );
406
				}
407
				$response[$key] = (object) $response[$key];
408
				break;
409
			case 'metadata' : // (array|false)
410
				$metadata = array();
411
				foreach ( (array) has_meta( $post_id ) as $meta ) {
412
					// Don't expose protected fields.
413
					$show = false;
414
					if ( WPCOM_JSON_API_Metadata::is_public( $meta['meta_key'] ) )
415
						$show = true;
416
					if ( current_user_can( 'edit_post_meta', $post_id , $meta['meta_key'] ) )
417
						$show = true;
418
419
					// Only business plan subscribers can view custom meta description.
420
					if ( Jetpack_SEO_Posts::DESCRIPTION_META_KEY === $meta['meta_key'] && ! Jetpack_SEO_Utils::is_enabled_jetpack_seo() ) {
421
						$show = false;
422
					}
423
424
					if ( !$show )
425
						continue;
426
427
					$metadata[] = array(
428
						'id'    => $meta['meta_id'],
429
						'key'   => $meta['meta_key'],
430
						'value' => maybe_unserialize( $meta['meta_value'] ),
431
					);
432
				}
433
434
				if ( ! empty( $metadata ) ) {
435
					$response[$key] = $metadata;
436
				} else {
437
					$response[$key] = false;
438
				}
439
				break;
440
			case 'meta' :
441
				$response[$key] = (object) array(
442
					'links' => (object) array(
443
						'self'    => (string) $this->links->get_post_link( $this->api->get_blog_id_for_output(), $post->ID ),
444
						'help'    => (string) $this->links->get_post_link( $this->api->get_blog_id_for_output(), $post->ID, 'help' ),
445
						'site'    => (string) $this->links->get_site_link( $this->api->get_blog_id_for_output() ),
446
						'replies' => (string) $this->links->get_post_link( $this->api->get_blog_id_for_output(), $post->ID, 'replies/' ),
447
						'likes'   => (string) $this->links->get_post_link( $this->api->get_blog_id_for_output(), $post->ID, 'likes/' ),
448
					),
449
				);
450
				break;
451
			case 'current_user_can' :
452
				$response[$key] = $capabilities;
453
				break;
454
			case 'capabilities' :
455
				$response[$key] = $capabilities;
456
				break;
457
458
			}
459
		}
460
461
		// WPCOM_JSON_API_Post_Endpoint::find_featured_worthy_media( $post );
462
		// $response['featured_media'] = self::find_featured_media( $response );
463
464
		unset( $GLOBALS['post'] );
465
		return $response;
466
	}
467
468
	// No Blog ID parameter.  No Post ID parameter.  Depends on globals.
469
	// Expects setup_postdata() to already have been run
470 View Code Duplication
	function get_the_post_content_for_display() {
471
		global $pages, $page;
472
473
		$old_pages = $pages;
474
		$old_page  = $page;
475
476
		$content = join( "\n\n", $pages );
477
		$content = preg_replace( '/<!--more(.*?)?-->/', '', $content );
478
		$pages   = array( $content );
479
		$page    = 1;
480
481
		ob_start();
482
		the_content();
483
		$return = ob_get_clean();
484
485
		$pages = $old_pages;
486
		$page  = $old_page;
487
488
		return $return;
489
	}
490
491 View Code Duplication
	function get_blog_post( $blog_id, $post_id, $context = 'display' ) {
492
		$blog_id = $this->api->get_blog_id( $blog_id );
493
		if ( !$blog_id || is_wp_error( $blog_id ) ) {
494
			return $blog_id;
495
		}
496
		switch_to_blog( $blog_id );
497
		$post = $this->get_post_by( 'ID', $post_id, $context );
498
		restore_current_blog();
499
		return $post;
500
	}
501
502
	/**
503
	 * Supporting featured media in post endpoints. Currently on for wpcom blogs
504
	 * since it's calling WPCOM_JSON_API_Read_Endpoint methods which presently
505
	 * rely on wpcom specific functionality.
506
	 *
507
	 * @param WP_Post $post
508
	 * @return object list of featured media
509
	 */
510
	public static function find_featured_media( &$post ) {
511
512
		if ( class_exists( 'WPCOM_JSON_API_Read_Endpoint' ) ) {
513
			return WPCOM_JSON_API_Read_Endpoint::find_featured_worthy_media( (array) $post );
514
		} else {
515
			return (object) array();
516
		}
517
518
	}
519
520
521
522 View Code Duplication
	function win8_gallery_shortcode( $attr ) {
523
		global $post;
524
525
		static $instance = 0;
526
		$instance++;
527
528
		$output = '';
529
530
		// We're trusting author input, so let's at least make sure it looks like a valid orderby statement
531
		if ( isset( $attr['orderby'] ) ) {
532
			$attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
533
			if ( !$attr['orderby'] )
534
				unset( $attr['orderby'] );
535
		}
536
537
		extract( shortcode_atts( array(
538
			'order'     => 'ASC',
539
			'orderby'   => 'menu_order ID',
540
			'id'        => $post->ID,
541
			'include'   => '',
542
			'exclude'   => '',
543
			'slideshow' => false
544
		), $attr, 'gallery' ) );
545
546
		// Custom image size and always use it
547
		add_image_size( 'win8app-column', 480 );
548
		$size = 'win8app-column';
549
550
		$id = (int) $id;
551
		if ( 'RAND' === $order )
552
			$orderby = 'none';
553
554
		if ( !empty( $include ) ) {
555
			$include      = preg_replace( '/[^0-9,]+/', '', $include );
556
			$_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
557
			$attachments  = array();
558
			foreach ( $_attachments as $key => $val ) {
559
				$attachments[$val->ID] = $_attachments[$key];
560
			}
561
		} elseif ( !empty( $exclude ) ) {
562
			$exclude     = preg_replace( '/[^0-9,]+/', '', $exclude );
563
			$attachments = get_children( array( 'post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
564
		} else {
565
			$attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
566
		}
567
568
		if ( ! empty( $attachments ) ) {
569
			foreach ( $attachments as $id => $attachment ) {
570
				$link = isset( $attr['link'] ) && 'file' === $attr['link'] ? wp_get_attachment_link( $id, $size, false, false ) : wp_get_attachment_link( $id, $size, true, false );
571
572
				if ( $captiontag && trim($attachment->post_excerpt) ) {
573
					$output .= "<div class='wp-caption aligncenter'>$link
574
						<p class='wp-caption-text'>" . wptexturize($attachment->post_excerpt) . "</p>
575
						</div>";
576
				} else {
577
					$output .= $link . ' ';
578
				}
579
			}
580
		}
581
	}
582
583
	/**
584
	 * Returns attachment object.
585
	 *
586
	 * @param $attachment attachment row
587
	 *
588
	 * @return object
589
	 */
590 View Code Duplication
	function get_attachment( $attachment ) {
591
		$metadata = wp_get_attachment_metadata( $attachment->ID );
592
593
		$result = array(
594
			'ID'		=> (int) $attachment->ID,
595
			'URL'           => (string) wp_get_attachment_url( $attachment->ID ),
596
			'guid'		=> (string) $attachment->guid,
597
			'mime_type'	=> (string) $attachment->post_mime_type,
598
			'width'		=> (int) isset( $metadata['width']  ) ? $metadata['width']  : 0,
599
			'height'	=> (int) isset( $metadata['height'] ) ? $metadata['height'] : 0,
600
		);
601
602
		if ( isset( $metadata['duration'] ) ) {
603
			$result['duration'] = (int) $metadata['duration'];
604
		}
605
606
		return (object) apply_filters( 'get_attachment', $result );
607
	}
608
609
	/**
610
	 * Get post-specific user capabilities
611
	 * @param  WP_Post $post              post object
612
	 * @return array                     array of post-level permissions; 'publish_post', 'delete_post', 'edit_post'
613
	 */
614
	function get_current_user_capabilities( $post ) {
615
		return array(
616
			'publish_post' => current_user_can( 'publish_post', $post->ID ),
617
			'delete_post'  => current_user_can( 'delete_post', $post->ID ),
618
			'edit_post'    => current_user_can( 'edit_post', $post->ID )
619
		);
620
	}
621
622
	/**
623
	 * Get post ID by name
624
	 *
625
	 * Attempts to match name on post title and page path
626
	 *
627
	 * @param string $name
628
	 *
629
	 * @return int|object Post ID on success, WP_Error object on failure
630
	 **/
631
	protected function get_post_id_by_name( $name ) {
632
		$name = sanitize_title( $name );
633
634
		if ( ! $name ) {
635
			return new WP_Error( 'invalid_post', 'Invalid post', 400 );
0 ignored issues
show
The call to WP_Error::__construct() has too many arguments starting with 'invalid_post'.

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.

Loading history...
636
		}
637
638
		$posts = get_posts( array(
639
			'name' => $name,
640
			'numberposts' => 1,
641
			'post_type' => $this->_get_whitelisted_post_types(),
642
		) );
643
644
		if ( ! $posts || ! isset( $posts[0]->ID ) || ! $posts[0]->ID ) {
645
			$page = get_page_by_path( $name );
646
647
			if ( ! $page ) {
648
				return new WP_Error( 'unknown_post', 'Unknown post', 404 );
0 ignored issues
show
The call to WP_Error::__construct() has too many arguments starting with 'unknown_post'.

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.

Loading history...
649
			}
650
651
			$post_id = $page->ID;
652
		} else {
653
			$post_id = (int) $posts[0]->ID;
654
		}
655
656
		return $post_id;
657
	}
658
}
659