Completed
Push — prepare/4.1 ( 0b4dc2...26fe0a )
by Jeremy
279:11 queued 269:16
created

SAL_Site::get_xmlrpc_url()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
/*
4
 * WARNING: This file is distributed verbatim in Jetpack.
5
 * There should be nothing WordPress.com specific in this file.
6
 *
7
 * @hide-in-jetpack
8
 */
9
10
require_once dirname( __FILE__ ) . '/class.json-api-date.php';
11
require_once dirname( __FILE__ ) . '/class.json-api-post-base.php';
12
13
/**
14
 * Base class for the Site Abstraction Layer (SAL)
15
 * Note that this is the site "as seen by user $user_id with token $token", which
16
 * is why we pass the token to the platform; these site instances are value objects
17
 * to be used in the context of a single request for a single user.
18
 * Also note that at present this class _assumes_ you've "switched to"
19
 * the site in question, and functions like `get_bloginfo( 'name' )` will
20
 * therefore return the correct value
21
 **/
22
abstract class SAL_Site {
23
	public $blog_id;
24
	public $platform;
25
26
	public function __construct( $blog_id, $platform ) {
27
		$this->blog_id = $blog_id;
28
		$this->platform = $platform;
29
	}
30
31
	public function get_id() {
32
		return $this->blog_id;
33
	}
34
35
	public function get_name() {
36
		return (string) htmlspecialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
37
	}
38
39
	public function get_description() {
40
		return (string) htmlspecialchars_decode( get_bloginfo( 'description' ), ENT_QUOTES );
41
	}
42
43
	public function get_url() {
44
		return (string) home_url();
45
	}
46
47
	public function get_post_count() {
48
		return (int) wp_count_posts( 'post' )->publish;
49
	}
50
51
	abstract public function has_videopress();
52
53
	abstract public function upgraded_filetypes_enabled();
54
55
	abstract public function is_mapped_domain();
56
57
	abstract public function is_redirect();
58
59
	abstract public function featured_images_enabled();
60
61
	abstract public function has_wordads();
62
63
	abstract public function get_frame_nonce();
64
65
	abstract public function allowed_file_types();
66
67
	abstract public function get_post_formats();
68
69
	abstract public function is_private();
70
71
	abstract public function is_following();
72
73
	abstract public function get_subscribers_count();
74
75
	abstract public function get_locale();
76
77
	abstract public function is_jetpack();
78
79
	abstract public function get_jetpack_modules();
80
81
	abstract public function is_vip();
82
83
	abstract public function is_multisite();
84
85
	abstract public function is_single_user_site();
86
87
	abstract public function get_plan();
88
89
	abstract public function get_ak_vp_bundle_enabled();
90
91
	abstract public function before_render();
92
93
	abstract public function after_render( &$response );
94
95
	// 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...
96
	abstract public function after_render_options( &$options );
97
98
	// wrap a WP_Post object with SAL methods
99
	abstract public function wrap_post( $post, $context );
100
101
102
	public function get_post_by_id( $post_id, $context ) {
103
		$post = get_post( $post_id, OBJECT, $context );
104
105
		if ( ! $post ) {
106
			return new WP_Error( 'unknown_post', 'Unknown post', 404 );
107
		}
108
109
		$wrapped_post = $this->wrap_post( $post, $context );
110
111
		// validate access
112
		return $this->validate_access( $wrapped_post );
113
	}
114
115
	/**
116
	 * Validate current user can access the post
117
	 * 
118
	 * @return WP_Error or post
119
	 */
120
	private function validate_access( $post ) {
121
		$context = $post->context;
122
123 View Code Duplication
		if ( ! $this->is_post_type_allowed( $post->post_type ) 
124
			&& 
125
			( ! function_exists( 'is_post_freshly_pressed' ) || ! is_post_freshly_pressed( $post->ID ) ) ) {
126
			return new WP_Error( 'unknown_post', 'Unknown post', 404 );
127
		}
128
129
		switch ( $context ) {
130
		case 'edit' :
131
			if ( ! current_user_can( 'edit_post', $post ) ) {
132
				return new WP_Error( 'unauthorized', 'User cannot edit post', 403 );
133
			}
134
			break;
135
		case 'display' :
136
			$can_view = $this->user_can_view_post( $post );
137
			if ( is_wp_error( $can_view ) ) {
138
				return $can_view;
139
			}
140
			break;
141
		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...
142
			return new WP_Error( 'invalid_context', 'Invalid API CONTEXT', 400 );
143
		}
144
145
		return $post;
146
	}
147
148
	// copied from class.json-api-endpoints.php
149 View Code Duplication
	private function is_post_type_allowed( $post_type ) {
150
		// if the post type is empty, that's fine, WordPress will default to post
151
		if ( empty( $post_type ) )
152
			return true;
153
154
		// allow special 'any' type
155
		if ( 'any' == $post_type )
156
			return true;
157
158
		// check for allowed types
159
		if ( in_array( $post_type, $this->_get_whitelisted_post_types() ) )
160
			return true;
161
162
		return false;
163
	}
164
165
	// copied from class.json-api-endpoints.php
166
	/**
167
	 * Gets the whitelisted post types that JP should allow access to.
168
	 *
169
	 * @return array Whitelisted post types.
170
	 */
171 View Code Duplication
	private function _get_whitelisted_post_types() {
172
		$allowed_types = array( 'post', 'page', 'revision' );
173
174
		/**
175
		 * Filter the post types Jetpack has access to, and can synchronize with WordPress.com.
176
		 *
177
		 * @module json-api
178
		 *
179
		 * @since 2.2.3
180
		 *
181
		 * @param array $allowed_types Array of whitelisted post types. Default to `array( 'post', 'page', 'revision' )`.
182
		 */
183
		$allowed_types = apply_filters( 'rest_api_allowed_post_types', $allowed_types );
184
185
		return array_unique( $allowed_types );
186
	}
187
188
	// copied and modified a little from class.json-api-endpoints.php
189
	private function user_can_view_post( $post ) {
190
		if ( !$post || is_wp_error( $post ) ) {
191
			return false;
192
		}
193
194 View Code Duplication
		if ( 'inherit' === $post->post_status ) {
195
			$parent_post = get_post( $post->post_parent );
196
			$post_status_obj = get_post_status_object( $parent_post->post_status );
197
		} else {
198
			$post_status_obj = get_post_status_object( $post->post_status );
199
		}
200
201
		$authorized = (
202
			$post_status_obj->public ||
203
			( is_user_logged_in() && 
204
				(
205
					( $post_status_obj->protected    && current_user_can( 'edit_post', $post->ID ) ) ||
206
					( $post_status_obj->private      && current_user_can( 'read_post', $post->ID ) ) ||
207
					( 'trash' === $post->post_status && current_user_can( 'edit_post', $post->ID ) ) ||
208
					'auto-draft' === $post->post_status
209
				) 
210
			) 
211
		);
212
213
		if ( ! $authorized ) {
214
			return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
215
		}
216
217 View Code Duplication
		if (
218
			-1 == get_option( 'blog_public' ) &&
219
			/**
220
			 * Filter access to a specific post.
221
			 *
222
			 * @module json-api
223
			 *
224
			 * @since 3.4.0
225
			 *
226
			 * @param bool current_user_can( 'read_post', $post->ID ) Can the current user access the post.
227
			 * @param WP_Post $post Post data.
228
			 */
229
			! apply_filters(
230
				'wpcom_json_api_user_can_view_post',
231
				current_user_can( 'read_post', $post->ID ),
232
				$post
233
			)
234
		) {
235
			return new WP_Error( 'unauthorized', 'User cannot view post', array( 'status_code' => 403, 'error' => 'private_blog' ) );
236
		}
237
238 View Code Duplication
		if ( strlen( $post->post_password ) && !current_user_can( 'edit_post', $post->ID ) ) {
239
			return new WP_Error( 'unauthorized', 'User cannot view password protected post', array( 'status_code' => 403, 'error' => 'password_protected' ) );
240
		}
241
242
		return true;
243
	}
244
245
	/**
246
	 * Get post ID by name
247
	 *
248
	 * Attempts to match name on post title and page path
249
	 *
250
	 * @param string $name
251
	 *
252
	 * @return int|object Post ID on success, WP_Error object on failure
253
	 */
254
	public function get_post_id_by_name( $name ) {
255
		$name = sanitize_title( $name );
256
257
		if ( ! $name ) {
258
			return new WP_Error( 'invalid_post', 'Invalid post', 400 );
259
		}
260
261
		$posts = get_posts( array(
262
			'name' => $name,
263
			'numberposts' => 1,
264
			'post_type' => $this->_get_whitelisted_post_types(),
265
		) );
266
267
		if ( ! $posts || ! isset( $posts[0]->ID ) || ! $posts[0]->ID ) {
268
			$page = get_page_by_path( $name );
269
270
			if ( ! $page ) {
271
				return new WP_Error( 'unknown_post', 'Unknown post', 404 );
272
			}
273
274
			return $page->ID;
275
		}
276
277
		return (int) $posts[0]->ID;
278
	}
279
280
	/**
281
	 * Get post by name
282
	 *
283
	 * Attempts to match name on post title and page path
284
	 *
285
	 * @param string $name
286
	 * @param string $context (display or edit)
287
	 *
288
	 * @return object Post object on success, WP_Error object on failure
289
	 **/
290
	public function get_post_by_name( $name, $context ) {
291
		$post_id = $this->get_post_id_by_name( $name );
292
		if ( is_wp_error( $post_id ) ) {
293
			return $post_id;
294
		}
295
296
		return $this->get_post_by_id( $post_id, $context );
297
	}
298
299
	function user_can_manage() {
300
		current_user_can( 'manage_options' );
301
	}
302
303
	function get_xmlrpc_url() {
304
		$xmlrpc_scheme = apply_filters( 'wpcom_json_api_xmlrpc_scheme', parse_url( get_option( 'home' ), PHP_URL_SCHEME ) );
305
		return site_url( 'xmlrpc.php', $xmlrpc_scheme );
306
	}
307
308
	function get_registered_date() {
309
		if ( function_exists( 'get_blog_details' ) ) {
310
			$blog_details = get_blog_details();
311
			if ( ! empty( $blog_details->registered ) ) {
312
				return WPCOM_JSON_API_Date::format_date( $blog_details->registered );
313
			}
314
		}
315
316
		return '0000-00-00T00:00:00+00:00';
317
	}
318
319
	function get_capabilities() {
320
		return array(
321
			'edit_pages'          => current_user_can( 'edit_pages' ),
322
			'edit_posts'          => current_user_can( 'edit_posts' ),
323
			'edit_others_posts'   => current_user_can( 'edit_others_posts' ),
324
			'edit_others_pages'   => current_user_can( 'edit_others_pages' ),
325
			'delete_posts'        => current_user_can( 'delete_posts' ),
326
			'delete_others_posts' => current_user_can( 'delete_others_posts' ),
327
			'edit_theme_options'  => current_user_can( 'edit_theme_options' ),
328
			'edit_users'          => current_user_can( 'edit_users' ),
329
			'list_users'          => current_user_can( 'list_users' ),
330
			'manage_categories'   => current_user_can( 'manage_categories' ),
331
			'manage_options'      => current_user_can( 'manage_options' ),
332
			'promote_users'       => current_user_can( 'promote_users' ),
333
			'publish_posts'       => current_user_can( 'publish_posts' ),
334
			'upload_files'        => current_user_can( 'upload_files' ),
335
			'view_stats'          => stats_is_blog_user( $this->blog_id )
336
		);
337
	}
338
339
	function is_visible() {
340
		if ( is_user_logged_in() ) {
341
			$current_user = wp_get_current_user();
342
			$visible      = (array) get_user_meta( $current_user->ID, 'blog_visibility', true );
343
344
			$is_visible = true;
345
			if ( isset( $visible[ $this->blog_id ] ) ) {
346
				$is_visible = (bool) $visible[ $this->blog_id ];
347
			}
348
349
			// null and true are visible
350
			return $is_visible;
351
		}
352
353
		return null;
354
	}
355
356
	function get_logo() {
357
358
		// Set an empty response array.
359
		$logo_setting = array(
360
			'id'    => (int) 0,
361
			'sizes' => array(),
362
			'url'   => '',
363
		);
364
365
		// Get current site logo values.
366
		$logo = get_option( 'site_logo' );
367
368
		// Update the response array if there's a site logo currenty active.
369
		if ( $logo && 0 != $logo['id'] ) {
370
			$logo_setting['id']  = $logo['id'];
371
			$logo_setting['url'] = $logo['url'];
372
373
			foreach ( $logo['sizes'] as $size => $properties ) {
374
				$logo_setting['sizes'][ $size ] = $properties;
375
			}
376
		}
377
378
		return $logo_setting;
379
	}
380
381
	function get_timezone() {
382
		return (string) get_option( 'timezone_string' );
383
	}
384
385
	function get_gmt_offset() {
386
		return (float) get_option( 'gmt_offset' );
387
	}
388
389
	function get_login_url() {
390
		return wp_login_url();
391
	}
392
393
	function get_admin_url() {
394
		return get_admin_url();
395
	}
396
397
	function get_unmapped_url() {
398
		return get_site_url( $this->blog_id );
399
	}
400
401
	function get_theme_slug() {
402
		return get_option( 'stylesheet' );
403
	}
404
405
	function get_header_image() {
406
		return get_theme_mod( 'header_image_data' );
407
	}
408
409
	function get_background_color() {
410
		return get_theme_mod( 'background_color' );
411
	}
412
413
	function get_image_default_link_type() {
414
		return get_option( 'image_default_link_type' );
415
	}
416
417
	function get_image_thumbnail_width() {
418
		return (int) get_option( 'thumbnail_size_w' );	
419
	}
420
421
	function get_image_thumbnail_height() {
422
		return (int) get_option( 'thumbnail_size_h' );
423
	}	
424
425
	function get_image_thumbnail_crop() {
426
		return get_option( 'thumbnail_crop' );
427
	}
428
429
	function get_image_medium_width() {
430
		return (int) get_option( 'medium_size_w' );
431
	}
432
433
	function get_image_medium_height() {
434
		return (int) get_option( 'medium_size_h' );	
435
	}
436
437
	function get_image_large_width() {
438
		return (int) get_option( 'large_size_w' );
439
	}
440
441
	function get_image_large_height() {
442
		return (int) get_option( 'large_size_h' );
443
	}
444
445
	function get_permalink_structure() {
446
		return get_option( 'permalink_structure' );
447
	}
448
449
	function get_default_post_format() {
450
		return get_option( 'default_post_format' );	
451
	}
452
	
453
	function get_default_category() {
454
		return (int) get_option( 'default_category' );
455
	}
456
457
	function get_show_on_front() {
458
		return get_option( 'show_on_front' );
459
	}
460
461
	function is_custom_front_page() {
462
		return ( 'page' === $this->get_show_on_front() );
463
	}
464
465
	function get_default_likes_enabled() {
466
		return (bool) apply_filters( 'wpl_is_enabled_sitewide', ! get_option( 'disabled_likes' ) );
467
	}
468
469
	function get_default_sharing_status() {
470
		$default_sharing_status = false;
471
		if ( class_exists( 'Sharing_Service' ) ) {
472
			$ss                     = new Sharing_Service();
473
			$blog_services          = $ss->get_blog_services();
474
			$default_sharing_status = ! empty( $blog_services['visible'] );
475
		}
476
		return (bool) $default_sharing_status;
477
	}
478
479
	function get_default_comment_status() {
480
		return 'closed' !== get_option( 'default_comment_status' );
481
	}
482
483
	function default_ping_status() {
484
		return 'closed' !== get_option( 'default_ping_status' );	
485
	}
486
487
	function is_publicize_permanently_disabled() {
488
		$publicize_permanently_disabled = false;
489
		if ( function_exists( 'is_publicize_permanently_disabled' ) ) {
490
			$publicize_permanently_disabled = is_publicize_permanently_disabled( $this->blog_id );
491
		}
492
		return $publicize_permanently_disabled;	
493
	}
494
	
495
	function get_page_on_front() {
496
		return (int) get_option( 'page_on_front' );
497
	}
498
499
	function get_page_for_posts() {
500
		return (int) get_option( 'page_for_posts' );
501
	}
502
503
	function is_headstart() {
504
		return get_option( 'headstart' );
505
	}
506
507
	function get_wordpress_version() {
508
		global $wp_version;
509
		return $wp_version;
510
	}
511
}
512