Completed
Push — feature/sync-sal ( 733243...7b442c )
by
unknown
26:41 queued 16:08
created

SAL_Site   D

Complexity

Total Complexity 99

Size/Duplication

Total Lines 534
Duplicated Lines 11.24 %

Coupling/Cohesion

Components 2
Dependencies 2

Importance

Changes 0
Metric Value
dl 60
loc 534
rs 4.8717
c 0
b 0
f 0
wmc 99
lcom 2
cbo 2

83 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A get_id() 0 3 1
A get_name() 0 3 1
A get_description() 0 3 1
A get_url() 0 3 1
A get_post_count() 0 3 1
has_videopress() 0 1 ?
upgraded_filetypes_enabled() 0 1 ?
is_mapped_domain() 0 1 ?
is_redirect() 0 1 ?
is_headstart_fresh() 0 1 ?
featured_images_enabled() 0 1 ?
has_wordads() 0 1 ?
get_frame_nonce() 0 1 ?
allowed_file_types() 0 1 ?
get_post_formats() 0 1 ?
is_private() 0 1 ?
is_following() 0 1 ?
get_subscribers_count() 0 1 ?
get_locale() 0 1 ?
is_jetpack() 0 1 ?
get_jetpack_modules() 0 1 ?
is_vip() 0 1 ?
is_multisite() 0 1 ?
is_single_user_site() 0 1 ?
get_plan() 0 1 ?
get_ak_vp_bundle_enabled() 0 1 ?
get_podcasting_archive() 0 1 ?
get_jetpack_seo_front_page_description() 0 1 ?
get_jetpack_seo_title_formats() 0 1 ?
get_verification_services_codes() 0 1 ?
before_render() 0 1 ?
after_render() 0 1 ?
after_render_options() 0 1 ?
wrap_post() 0 1 ?
is_a8c_publication() 0 1 ?
A is_automated_transfer() 0 3 1
A get_post_by_id() 0 12 2
C validate_access() 0 28 7
B current_user_can_access_post_type() 15 15 5
A get_post_type_object() 0 3 1
A is_post_type_allowed() 0 15 4
A get_whitelisted_post_types() 16 16 1
C user_can_view_post() 29 55 17
B get_post_id_by_name() 0 25 6
A get_post_by_name() 0 8 2
A user_can_manage() 0 3 1
A get_xmlrpc_url() 0 4 1
A get_registered_date() 0 10 3
A get_capabilities() 0 22 1
A is_visible() 0 16 3
B get_logo() 0 24 4
A get_timezone() 0 3 1
A get_gmt_offset() 0 3 1
A get_login_url() 0 3 1
A get_admin_url() 0 3 1
A get_unmapped_url() 0 3 1
A get_theme_slug() 0 3 1
A get_header_image() 0 3 1
A get_background_color() 0 3 1
A get_image_default_link_type() 0 3 1
A get_image_thumbnail_width() 0 3 1
A get_image_thumbnail_height() 0 3 1
A get_image_thumbnail_crop() 0 3 1
A get_image_medium_width() 0 3 1
A get_image_medium_height() 0 3 1
A get_image_large_width() 0 3 1
A get_image_large_height() 0 3 1
A get_permalink_structure() 0 3 1
A get_default_post_format() 0 3 1
A get_default_category() 0 3 1
A get_show_on_front() 0 3 1
A is_custom_front_page() 0 3 1
A get_default_likes_enabled() 0 3 1
A get_default_sharing_status() 0 9 2
A get_default_comment_status() 0 3 1
A default_ping_status() 0 3 1
A is_publicize_permanently_disabled() 0 7 2
A get_page_on_front() 0 3 1
A get_page_for_posts() 0 3 1
A is_headstart() 0 3 1
A get_wordpress_version() 0 4 1
A is_domain_only() 0 4 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like SAL_Site often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SAL_Site, and based on these observations, apply Extract Interface, too.

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