Completed
Push — master ( bc6754...ed64c2 )
by
unknown
07:19
created

Post   C

Complexity

Total Complexity 61

Size/Duplication

Total Lines 477
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 477
rs 6.018
wmc 61
lcom 2
cbo 4

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 3
A init() 0 7 2
A get_object() 0 5 1
A can_edit() 0 10 3
A get_edit_url() 0 7 2
A get_attached_images() 0 20 2
A attached_images() 0 16 3
A get_first_attached_image_id() 0 22 2
A first_attached_image() 0 10 2
A thumbnail() 0 13 3
A get_title() 0 3 1
A title() 0 3 1
B get_content() 0 21 5
A content() 0 3 1
A get_post_type() 0 3 1
A get_permalink() 0 9 2
A permalink() 0 3 1
F get_preview() 0 79 22
B get_comments() 0 31 4

How to fix   Complexity   

Complex Class

Complex classes like Post 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 Post, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Classy\Models;
4
5
use Classy\Basis;
6
use Classy\Comment;
7
use Classy\Helper;
8
9
/**
10
 * Wrapper for WP_Post.
11
 */
12
class Post extends Basis {
13
14
	/**
15
	 * Current post id.
16
	 *
17
	 * @var int
18
	 */
19
	public $ID;
20
21
	/**
22
	 * Stores current post object.
23
	 *
24
	 * @var \WP_Post
25
	 */
26
	protected $object;
27
28
	/**
29
	 * Post title.
30
	 *
31
	 * @var string
32
	 */
33
	public $post_title;
34
35
	/**
36
	 * Post name.
37
	 *
38
	 * @var string
39
	 */
40
	public $post_name;
41
42
	/**
43
	 * Post content (raw).
44
	 *
45
	 * @var string
46
	 */
47
	public $post_content;
48
49
	/**
50
	 * Post type.
51
	 *
52
	 * @var string
53
	 */
54
	public $post_type;
55
56
	/**
57
	 * Post author id.
58
	 *
59
	 * @var int
60
	 */
61
	public $post_author;
62
63
	/**
64
	 * Post date. String as stored in the WP database, ex: 2012-04-23 08:11:23.
65
	 *
66
	 * @var string
67
	 */
68
	public $post_date;
69
70
	/**
71
	 * Post excerpt (raw).
72
	 *
73
	 * @var string
74
	 */
75
	public $post_excerpt;
76
77
	/**
78
	 * Post status. It can be draft, publish, pending, private, trash, etc.
79
	 *
80
	 * @var string
81
	 */
82
	public $post_status;
83
84
	/**
85
	 * Post permalink.
86
	 *
87
	 * @var string
88
	 */
89
	public $permalink;
90
91
	/**
92
	 * Main constructor function. If ID won't be provided we will try to find it, based on your query.
93
	 *
94
	 * @param object|int $post WP_Post or WP_Post.ID.
95
	 */
96
	public function __construct( $post = null ) {
97
		if ( is_integer( $post ) ) {
98
			$this->ID = $post;
99
			$this->init();
100
		} elseif ( is_a( $post, '\WP_Post' ) ) {
101
			$this->import( $post );
0 ignored issues
show
Bug introduced by
It seems like $post defined by parameter $post on line 96 can also be of type null; however, Classy\Basis::import() does only seem to accept object|array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
102
		}
103
	}
104
105
	/**
106
	 * Initialises Instance based on provided post id.
107
	 */
108
	protected function init() {
109
		$post = $this->get_object();
110
111
		if ( is_a( $post, '\WP_Post' ) ) {
112
			$this->import( $post );
113
		}
114
	}
115
116
	/**
117
	 * Returns post object.
118
	 *
119
	 * @return \WP_Post
120
	 */
121
	public function get_object() {
122
		$object = get_post( $this->ID );
123
124
		return $object;
125
	}
126
127
	/**
128
	 * Checks if current user can edit this post.
129
	 *
130
	 * @return boolean
131
	 */
132
	public function can_edit() {
133
		if ( ! function_exists( 'current_user_can' ) ) {
134
			return false;
135
		}
136
		if ( current_user_can( 'edit_post', $this->ID ) ) {
137
			return true;
138
		}
139
140
		return false;
141
	}
142
143
	/**
144
	 * Returns post edit url.
145
	 *
146
	 * @return string
147
	 */
148
	public function get_edit_url() {
149
		if ( $this->can_edit() ) {
150
			return get_edit_post_link( $this->ID );
151
		}
152
153
		return '';
154
	}
155
156
	/**
157
	 * Returns array of attached image ids.
158
	 *
159
	 * @return false|array of ids
160
	 */
161
	public function get_attached_images() {
162
		$attrs = array(
163
			'post_parent' => $this->ID,
164
			'post_status' => null,
165
			'post_type' => 'attachment',
166
			'post_mime_type' => 'image',
167
			'order' => 'ASC',
168
			'numberposts' => -1,
169
			'orderby' => 'menu_order',
170
			'fields' => 'ids',
171
		);
172
173
		$images = get_children( $attrs );
174
175
		if ( ! count( $images ) ) {
176
			return false;
177
		}
178
179
		return $images;
180
	}
181
182
	/**
183
	 * Returns array of attached images as Image objects.
184
	 *
185
	 * @return array of Image
186
	 */
187
	public function attached_images() {
188
		$_return = array();
189
190
		$images = $this->get_attached_images();
191
192
		if ( $images ) {
193
194
			foreach ( $images as $image_id ) {
195
196
				$_return[] = new Image( $image_id );
197
198
			}
199
		}
200
201
		return $_return;
202
	}
203
204
205
	/**
206
	 * Returns first attached image id.
207
	 *
208
	 * @return int|boolean
209
	 */
210
	public function get_first_attached_image_id() {
211
		$attrs = array(
212
			'post_parent' => $this->ID,
213
			'post_status' => null,
214
			'post_type' => 'attachment',
215
			'post_mime_type' => 'image',
216
			'order' => 'ASC',
217
			'numberposts' => 1,
218
			'orderby' => 'menu_order',
219
			'fields' => 'ids',
220
		);
221
222
		$images = get_children( $attrs );
223
224
		if ( ! count( $images ) ) {
225
			return false;
226
		}
227
228
		$images = array_values( $images );
229
230
		return $images[0];
231
	}
232
233
	/**
234
	 * Returns first attached image.
235
	 *
236
	 * @return Image
237
	 */
238
	public function first_attached_image() {
239
240
		$image_id = $this->get_first_attached_image_id();
241
242
		if ( $image_id ) {
243
			return new Image( $image_id );
0 ignored issues
show
Bug introduced by
It seems like $image_id defined by $this->get_first_attached_image_id() on line 240 can also be of type boolean; however, Classy\Models\Image::__construct() does only seem to accept integer|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
244
		}
245
246
		return new Image();
247
	}
248
249
	/**
250
	 * Returns post thumbnail.
251
	 *
252
	 * @return Image
253
	 */
254
	public function thumbnail() {
255
		if ( function_exists( 'get_post_thumbnail_id' ) ) {
256
			$image_id = get_post_thumbnail_id( $this->ID );
257
258
			if ( $image_id ) {
259
260
				return new Image( $image_id );
261
262
			}
263
		}
264
265
		return new Image();
266
	}
267
268
	/**
269
	 * Returns post title with filters applied.
270
	 *
271
	 * @return string
272
	 */
273
	public function get_title() {
274
		return apply_filters( 'the_title', $this->post_title, $this->ID );
275
	}
276
277
	/**
278
	 * Alias for get_title.
279
	 *
280
	 * @return string
281
	 */
282
	public function title() {
283
		return $this->get_title();
284
	}
285
286
	/**
287
	 * Returns the post content with filters applied.
288
	 *
289
	 * @param  integer $page Page number, in case our post has <!--nextpage--> tags.
290
	 *
291
	 * @return string        Post content
292
	 */
293
	public function get_content( $page = 0 ) {
294
		if ( 0 === absint( $page ) && $this->post_content ) {
295
			return $this->post_content;
296
		}
297
298
		$content = $this->post_content;
299
300
		if ( $page ) {
301
			$contents = explode( '<!--nextpage-->', $content );
302
303
			$page--;
304
305
			if ( count( $contents ) > $page ) {
306
				$content = $contents[ $page ];
307
			}
308
		}
309
310
		$content = apply_filters( 'the_content', ($content) );
311
312
		return $content;
313
	}
314
315
	/**
316
	 * Alias for get_content.
317
	 *
318
	 * @return string
319
	 */
320
	public function content() {
321
		return $this->get_content();
322
	}
323
324
	/**
325
	 * Returns post type object for current post.
326
	 *
327
	 * @return object
328
	 */
329
	public function get_post_type() {
330
		return get_post_type_object( $this->post_type );
331
	}
332
333
	/**
334
	 * Returns post permalink.
335
	 *
336
	 * @return string
337
	 */
338
	public function get_permalink() {
339
		if ( isset( $this->permalink ) ) {
340
			return $this->permalink;
341
		}
342
343
		$this->permalink = get_permalink( $this->ID );
344
345
		return $this->permalink;
346
	}
347
348
	/**
349
	 * Alias for get_permalink
350
	 *
351
	 * @return string
352
	 */
353
	public function permalink() {
354
		return $this->get_permalink();
355
	}
356
357
	/**
358
	 * Returns post preview of requested length.
359
	 * It will look for post_excerpt and will return it.
360
	 * If post contains <!-- more --> tag it will return content until it
361
	 *
362
	 * @param  integer $len      Number of words.
363
	 * @param  boolean $force    If is set to true it will cut your post_excerpt to desired $len length.
364
	 * @param  string  $readmore The text for 'readmore' link.
365
	 * @param  boolean $strip    Should we strip tags.
366
	 *
367
	 * @return string            Post preview.
368
	 */
369
	public function get_preview( $len = 50, $force = false, $readmore = 'Read More', $strip = true ) {
370
		$text = '';
371
		$trimmed = false;
372
373
		if ( isset( $this->post_excerpt ) && strlen( $this->post_excerpt ) ) {
374
375
			if ( $force ) {
376
				$text = Helper::trim_words( $this->post_excerpt, $len, false );
377
				$trimmed = true;
378
			} else {
379
				$text = $this->post_excerpt;
380
			}
381
		}
382
383
		if ( ! strlen( $text ) && preg_match( '/<!--\s?more(.*?)?-->/', $this->post_content, $readmore_matches ) ) {
384
385
			$pieces = explode( $readmore_matches[0], $this->post_content );
386
			$text = $pieces[0];
387
388
			if ( $force ) {
389
				$text = Helper::trim_words( $text, $len, false );
390
				$trimmed = true;
391
			}
392
393
			$text = do_shortcode( $text );
394
395
		}
396
397
		if ( ! strlen( $text ) ) {
398
399
			$text = Helper::trim_words( $this->get_content(), $len, false );
400
			$trimmed = true;
401
402
		}
403
404
		if ( ! strlen( trim( $text ) ) ) {
405
406
			return trim( $text );
407
408
		}
409
410
		if ( $strip ) {
411
412
			$text = trim( strip_tags( $text ) );
413
414
		}
415
416
		if ( strlen( $text ) ) {
417
418
			$text = trim( $text );
419
			$last = $text[ strlen( $text ) - 1 ];
420
421
			if ( '.' !== $last && $trimmed ) {
422
				$text .= ' &hellip; ';
423
			}
424
425
			if ( ! $strip ) {
426
				$last_p_tag = strrpos( $text, '</p>' );
427
				if ( false !== $last_p_tag ) {
428
					$text = substr( $text, 0, $last_p_tag );
429
				}
430
				if ( '.' !== $last && $trimmed ) {
431
					$text .= ' &hellip; ';
432
				}
433
			}
434
435
			if ( $readmore && isset( $readmore_matches ) && ! empty( $readmore_matches[1] ) ) {
436
				$text .= ' <a href="' . $this->get_permalink() . '" class="read-more">' . trim( $readmore_matches[1] ) . '</a>';
437
			} elseif ( $readmore ) {
438
				$text .= ' <a href="' . $this->get_permalink() . '" class="read-more">' . trim( $readmore ) . '</a>';
439
			}
440
441
			if ( ! $strip ) {
442
				$text .= '</p>';
443
			}
444
		}
445
446
		return trim( $text );
447
	}
448
449
	/**
450
	 * Returns comments array
451
	 *
452
	 * @param string $status Comment status.
453
	 * @param string $order  Order for comments query.
454
	 *
455
	 * @return array
456
	 */
457
	public function get_comments( $status = 'approve', $order = 'DESC' ) {
458
459
		$_return = array();
460
461
		$args = array(
462
			'post_id' => $this->ID,
463
			'status' => $status,
464
			'order' => $order,
465
		);
466
467
		$comments = get_comments( $args );
468
469
		foreach ( $comments as $comment ) {
470
			
471
			$_return[ $comment->comment_ID ] = new Comment( $comment );
472
473
		}
474
475
		foreach ( $_return as $key => $comment ) {
476
477
			if ( $comment->has_parent() ) {
478
479
				$_return[ $comment->comment_parent ]->add_child( $comment );
480
481
				unset( $_return[ $key ] );
482
483
			}
484
		}
485
486
		return array_values( $_return );
487
	}
488
}
489