Completed
Push — sync/aerych/r157602-wpcom-1496... ( 203b6b )
by
unknown
15:47 queued 04:27
created

SAL_Site::get_post_id_by_name()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 14
nc 4
nop 1
dl 0
loc 25
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
require_once dirname( __FILE__ ) . '/class.json-api-date.php';
4
require_once dirname( __FILE__ ) . '/class.json-api-post-base.php';
5
6
/**
7
 * Base class for the Site Abstraction Layer (SAL)
8
 * Note that this is the site "as seen by user $user_id with token $token", which
9
 * is why we pass the token to the platform; these site instances are value objects
10
 * to be used in the context of a single request for a single user.
11
 * Also note that at present this class _assumes_ you've "switched to"
12
 * the site in question, and functions like `get_bloginfo( 'name' )` will
13
 * therefore return the correct value
14
 **/
15
abstract class SAL_Site {
16
	public $blog_id;
17
	public $platform;
18
19
	public function __construct( $blog_id, $platform ) {
20
		$this->blog_id = $blog_id;
21
		$this->platform = $platform;
22
	}
23
24
	public function get_id() {
25
		return $this->blog_id;
26
	}
27
28
	public function get_name() {
29
		return (string) htmlspecialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
30
	}
31
32
	public function get_description() {
33
		return (string) htmlspecialchars_decode( get_bloginfo( 'description' ), ENT_QUOTES );
34
	}
35
36
	public function get_url() {
37
		return (string) home_url();
38
	}
39
40
	public function get_post_count() {
41
		return (int) wp_count_posts( 'post' )->publish;
42
	}
43
44
	public function get_quota() {
45
		return null;
46
	}
47
48
	abstract public function has_videopress();
49
50
	abstract public function upgraded_filetypes_enabled();
51
52
	abstract public function is_mapped_domain();
53
54
	abstract public function is_redirect();
55
56
	abstract public function is_headstart_fresh();
57
58
	abstract public function featured_images_enabled();
59
60
	abstract public function has_wordads();
61
62
	abstract public function get_frame_nonce();
63
64
	abstract public function allowed_file_types();
65
66
	abstract public function get_post_formats();
67
68
	abstract public function is_private();
69
70
	abstract public function is_following();
71
72
	abstract public function get_subscribers_count();
73
74
	abstract public function get_locale();
75
76
	abstract public function is_jetpack();
77
78
	abstract public function get_jetpack_modules();
79
80
	abstract public function is_vip();
81
82
	abstract public function is_multisite();
83
84
	abstract public function is_single_user_site();
85
86
	abstract public function get_plan();
87
88
	abstract public function get_ak_vp_bundle_enabled();
89
90
	abstract public function get_podcasting_archive();
91
92
	abstract public function get_jetpack_seo_front_page_description();
93
94
	abstract public function get_jetpack_seo_title_formats();
95
96
	abstract public function get_verification_services_codes();
97
98
	abstract public function before_render();
99
100
	abstract public function after_render( &$response );
101
102
	// TODO - factor this out? Seems an odd thing to have on a site
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
103
	abstract public function after_render_options( &$options );
104
105
	// wrap a WP_Post object with SAL methods
106
	abstract public function wrap_post( $post, $context );
107
108
	abstract protected function is_a8c_publication( $post_id );
109
110
	public function is_automated_transfer() {
111
		return false;
112
	}
113
114
	public function get_post_by_id( $post_id, $context ) {
115
		$post = get_post( $post_id, OBJECT, $context );
116
117
		if ( ! $post ) {
118
			return new WP_Error( 'unknown_post', 'Unknown post', 404 );
119
		}
120
121
		$wrapped_post = $this->wrap_post( $post, $context );
122
123
		// validate access
124
		return $this->validate_access( $wrapped_post );
125
	}
126
127
	/**
128
	 * Validate current user can access the post
129
	 *
130
	 * @return WP_Error or post
131
	 */
132
	private function validate_access( $post ) {
133
		$context = $post->context;
134
135
		if (
136
			! $this->is_post_type_allowed( $post->post_type )
137
			&& ! $this->is_a8c_publication( $post->ID )
138
		) {
139
			return new WP_Error( 'unknown_post', 'Unknown post', 404 );
140
		}
141
142
		switch ( $context ) {
143
		case 'edit' :
144
			if ( ! current_user_can( 'edit_post', $post ) ) {
145
				return new WP_Error( 'unauthorized', 'User cannot edit post', 403 );
146
			}
147
			break;
148
		case 'display' :
149
			$can_view = $this->user_can_view_post( $post );
150
			if ( is_wp_error( $can_view ) ) {
151
				return $can_view;
152
			}
153
			break;
154
		default :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
155
			return new WP_Error( 'invalid_context', 'Invalid API CONTEXT', 400 );
156
		}
157
158
		return $post;
159
	}
160
161 View Code Duplication
	public function current_user_can_access_post_type( $post_type, $context ) {
162
		$post_type_object = $this->get_post_type_object( $post_type );
163
		if ( ! $post_type_object ) {
164
			return false;
165
		}
166
167
		switch( $context ) {
168
			case 'edit':
169
				return current_user_can( $post_type_object->cap->edit_posts );
170
			case 'display':
171
				return $post_type_object->public || current_user_can( $post_type_object->cap->read_private_posts );
172
			default:
173
				return false;
174
		}
175
	}
176
177
	protected function get_post_type_object( $post_type ) {
178
		return get_post_type_object( $post_type );
179
	}
180
181
	// copied from class.json-api-endpoints.php
182
	public function is_post_type_allowed( $post_type ) {
183
		// if the post type is empty, that's fine, WordPress will default to post
184
		if ( empty( $post_type ) )
185
			return true;
186
187
		// allow special 'any' type
188
		if ( 'any' == $post_type )
189
			return true;
190
191
		// check for allowed types
192
		if ( in_array( $post_type, $this->get_whitelisted_post_types() ) )
193
			return true;
194
195
		return false;
196
	}
197
198
	// copied from class.json-api-endpoints.php
199
	/**
200
	 * Gets the whitelisted post types that JP should allow access to.
201
	 *
202
	 * @return array Whitelisted post types.
203
	 */
204 View Code Duplication
	public function get_whitelisted_post_types() {
205
		$allowed_types = array( 'post', 'page', 'revision' );
206
207
		/**
208
		 * Filter the post types Jetpack has access to, and can synchronize with WordPress.com.
209
		 *
210
		 * @module json-api
211
		 *
212
		 * @since 2.2.3
213
		 *
214
		 * @param array $allowed_types Array of whitelisted post types. Default to `array( 'post', 'page', 'revision' )`.
215
		 */
216
		$allowed_types = apply_filters( 'rest_api_allowed_post_types', $allowed_types );
217
218
		return array_unique( $allowed_types );
219
	}
220
221
	// copied and modified a little from class.json-api-endpoints.php
222
	private function user_can_view_post( $post ) {
223
		if ( !$post || is_wp_error( $post ) ) {
224
			return false;
225
		}
226
227 View Code Duplication
		if ( 'inherit' === $post->post_status ) {
228
			$parent_post = get_post( $post->post_parent );
229
			$post_status_obj = get_post_status_object( $parent_post->post_status );
230
		} else {
231
			$post_status_obj = get_post_status_object( $post->post_status );
232
		}
233
234
		$authorized = (
235
			$post_status_obj->public ||
236
			( is_user_logged_in() &&
237
				(
238
					( $post_status_obj->protected    && current_user_can( 'edit_post', $post->ID ) ) ||
239
					( $post_status_obj->private      && current_user_can( 'read_post', $post->ID ) ) ||
240
					( 'trash' === $post->post_status && current_user_can( 'edit_post', $post->ID ) ) ||
241
					'auto-draft' === $post->post_status
242
				)
243
			)
244
		);
245
246
		if ( ! $authorized ) {
247
			return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
248
		}
249
250 View Code Duplication
		if (
251
			-1 == get_option( 'blog_public' ) &&
252
			/**
253
			 * Filter access to a specific post.
254
			 *
255
			 * @module json-api
256
			 *
257
			 * @since 3.4.0
258
			 *
259
			 * @param bool current_user_can( 'read_post', $post->ID ) Can the current user access the post.
260
			 * @param WP_Post $post Post data.
261
			 */
262
			! apply_filters(
263
				'wpcom_json_api_user_can_view_post',
264
				current_user_can( 'read_post', $post->ID ),
265
				$post
266
			)
267
		) {
268
			return new WP_Error( 'unauthorized', 'User cannot view post', array( 'status_code' => 403, 'error' => 'private_blog' ) );
269
		}
270
271 View Code Duplication
		if ( strlen( $post->post_password ) && !current_user_can( 'edit_post', $post->ID ) ) {
272
			return new WP_Error( 'unauthorized', 'User cannot view password protected post', array( 'status_code' => 403, 'error' => 'password_protected' ) );
273
		}
274
275
		return true;
276
	}
277
278
	/**
279
	 * Get post ID by name
280
	 *
281
	 * Attempts to match name on post title and page path
282
	 *
283
	 * @param string $name
284
	 *
285
	 * @return int|object Post ID on success, WP_Error object on failure
286
	 */
287
	public function get_post_id_by_name( $name ) {
288
		$name = sanitize_title( $name );
289
290
		if ( ! $name ) {
291
			return new WP_Error( 'invalid_post', 'Invalid post', 400 );
292
		}
293
294
		$posts = get_posts( array(
295
			'name' => $name,
296
			'numberposts' => 1,
297
			'post_type' => $this->get_whitelisted_post_types(),
298
		) );
299
300
		if ( ! $posts || ! isset( $posts[0]->ID ) || ! $posts[0]->ID ) {
301
			$page = get_page_by_path( $name );
302
303
			if ( ! $page ) {
304
				return new WP_Error( 'unknown_post', 'Unknown post', 404 );
305
			}
306
307
			return $page->ID;
308
		}
309
310
		return (int) $posts[0]->ID;
311
	}
312
313
	/**
314
	 * Get post by name
315
	 *
316
	 * Attempts to match name on post title and page path
317
	 *
318
	 * @param string $name
319
	 * @param string $context (display or edit)
320
	 *
321
	 * @return object Post object on success, WP_Error object on failure
322
	 **/
323
	public function get_post_by_name( $name, $context ) {
324
		$post_id = $this->get_post_id_by_name( $name );
325
		if ( is_wp_error( $post_id ) ) {
326
			return $post_id;
327
		}
328
329
		return $this->get_post_by_id( $post_id, $context );
330
	}
331
332
	function user_can_manage() {
333
		current_user_can( 'manage_options' );
334
	}
335
336
	function get_xmlrpc_url() {
337
		$xmlrpc_scheme = apply_filters( 'wpcom_json_api_xmlrpc_scheme', parse_url( get_option( 'home' ), PHP_URL_SCHEME ) );
338
		return site_url( 'xmlrpc.php', $xmlrpc_scheme );
339
	}
340
341
	function get_registered_date() {
342
		if ( function_exists( 'get_blog_details' ) ) {
343
			$blog_details = get_blog_details();
344
			if ( ! empty( $blog_details->registered ) ) {
345
				return WPCOM_JSON_API_Date::format_date( $blog_details->registered );
346
			}
347
		}
348
349
		return '0000-00-00T00:00:00+00:00';
350
	}
351
352
	function get_capabilities() {
353
		return array(
354
			'edit_pages'          => current_user_can( 'edit_pages' ),
355
			'edit_posts'          => current_user_can( 'edit_posts' ),
356
			'edit_others_posts'   => current_user_can( 'edit_others_posts' ),
357
			'edit_others_pages'   => current_user_can( 'edit_others_pages' ),
358
			'delete_posts'        => current_user_can( 'delete_posts' ),
359
			'delete_others_posts' => current_user_can( 'delete_others_posts' ),
360
			'edit_theme_options'  => current_user_can( 'edit_theme_options' ),
361
			'edit_users'          => current_user_can( 'edit_users' ),
362
			'list_users'          => current_user_can( 'list_users' ),
363
			'manage_categories'   => current_user_can( 'manage_categories' ),
364
			'manage_options'      => current_user_can( 'manage_options' ),
365
			'activate_wordads'    => wpcom_get_blog_owner() === (int) get_current_user_id(),
366
			'promote_users'       => current_user_can( 'promote_users' ),
367
			'publish_posts'       => current_user_can( 'publish_posts' ),
368
			'upload_files'        => current_user_can( 'upload_files' ),
369
			'delete_users'        => current_user_can( 'delete_users' ),
370
			'remove_users'        => current_user_can( 'remove_users' ),
371
			'view_stats'          => stats_is_blog_user( $this->blog_id )
372
		);
373
	}
374
375
	function is_visible() {
376
		if ( is_user_logged_in() ) {
377
			$current_user = wp_get_current_user();
378
			$visible      = (array) get_user_meta( $current_user->ID, 'blog_visibility', true );
379
380
			$is_visible = true;
381
			if ( isset( $visible[ $this->blog_id ] ) ) {
382
				$is_visible = (bool) $visible[ $this->blog_id ];
383
			}
384
385
			// null and true are visible
386
			return $is_visible;
387
		}
388
389
		return null;
390
	}
391
392
	function get_logo() {
393
394
		// Set an empty response array.
395
		$logo_setting = array(
396
			'id'    => (int) 0,
397
			'sizes' => array(),
398
			'url'   => '',
399
		);
400
401
		// Get current site logo values.
402
		$logo = get_option( 'site_logo' );
403
404
		// Update the response array if there's a site logo currenty active.
405
		if ( $logo && 0 != $logo['id'] ) {
406
			$logo_setting['id']  = $logo['id'];
407
			$logo_setting['url'] = $logo['url'];
408
409
			foreach ( $logo['sizes'] as $size => $properties ) {
410
				$logo_setting['sizes'][ $size ] = $properties;
411
			}
412
		}
413
414
		return $logo_setting;
415
	}
416
417
	function get_timezone() {
418
		return (string) get_option( 'timezone_string' );
419
	}
420
421
	function get_gmt_offset() {
422
		return (float) get_option( 'gmt_offset' );
423
	}
424
425
	function get_login_url() {
426
		return wp_login_url();
427
	}
428
429
	function get_admin_url() {
430
		return get_admin_url();
431
	}
432
433
	function get_unmapped_url() {
434
		return get_site_url( get_current_blog_id() );
435
	}
436
437
	function get_theme_slug() {
438
		return get_option( 'stylesheet' );
439
	}
440
441
	function get_header_image() {
442
		return get_theme_mod( 'header_image_data' );
443
	}
444
445
	function get_background_color() {
446
		return get_theme_mod( 'background_color' );
447
	}
448
449
	function get_image_default_link_type() {
450
		return get_option( 'image_default_link_type' );
451
	}
452
453
	function get_image_thumbnail_width() {
454
		return (int) get_option( 'thumbnail_size_w' );
455
	}
456
457
	function get_image_thumbnail_height() {
458
		return (int) get_option( 'thumbnail_size_h' );
459
	}
460
461
	function get_image_thumbnail_crop() {
462
		return get_option( 'thumbnail_crop' );
463
	}
464
465
	function get_image_medium_width() {
466
		return (int) get_option( 'medium_size_w' );
467
	}
468
469
	function get_image_medium_height() {
470
		return (int) get_option( 'medium_size_h' );
471
	}
472
473
	function get_image_large_width() {
474
		return (int) get_option( 'large_size_w' );
475
	}
476
477
	function get_image_large_height() {
478
		return (int) get_option( 'large_size_h' );
479
	}
480
481
	function get_permalink_structure() {
482
		return get_option( 'permalink_structure' );
483
	}
484
485
	function get_default_post_format() {
486
		return get_option( 'default_post_format' );
487
	}
488
489
	function get_default_category() {
490
		return (int) get_option( 'default_category' );
491
	}
492
493
	function get_show_on_front() {
494
		return get_option( 'show_on_front' );
495
	}
496
497
	function is_custom_front_page() {
498
		return ( 'page' === $this->get_show_on_front() );
499
	}
500
501
	function get_default_likes_enabled() {
502
		return (bool) apply_filters( 'wpl_is_enabled_sitewide', ! get_option( 'disabled_likes' ) );
503
	}
504
505
	function get_default_sharing_status() {
506
		$default_sharing_status = false;
507
		if ( class_exists( 'Sharing_Service' ) ) {
508
			$ss                     = new Sharing_Service();
509
			$blog_services          = $ss->get_blog_services();
510
			$default_sharing_status = ! empty( $blog_services['visible'] );
511
		}
512
		return (bool) $default_sharing_status;
513
	}
514
515
	function get_default_comment_status() {
516
		return 'closed' !== get_option( 'default_comment_status' );
517
	}
518
519
	function default_ping_status() {
520
		return 'closed' !== get_option( 'default_ping_status' );
521
	}
522
523
	function is_publicize_permanently_disabled() {
524
		$publicize_permanently_disabled = false;
525
		if ( function_exists( 'is_publicize_permanently_disabled' ) ) {
526
			$publicize_permanently_disabled = is_publicize_permanently_disabled( $this->blog_id );
527
		}
528
		return $publicize_permanently_disabled;
529
	}
530
531
	function get_page_on_front() {
532
		return (int) get_option( 'page_on_front' );
533
	}
534
535
	function get_page_for_posts() {
536
		return (int) get_option( 'page_for_posts' );
537
	}
538
539
	function is_headstart() {
540
		return get_option( 'headstart' );
541
	}
542
543
	function get_wordpress_version() {
544
		global $wp_version;
545
		return $wp_version;
546
	}
547
548
	function is_domain_only() {
549
		$options = get_option( 'options' );
550
		return ! empty ( $options['is_domain_only'] ) ? (bool) $options['is_domain_only'] : false;
551
	}
552
553
	function get_blog_public() {
554
		return (int) get_option( 'blog_public' );
555
	}
556
}
557