Passed
Push — master ( dae648...c5e678 )
by Paul
05:32
created

SiteReviews   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 304
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 304
ccs 0
cts 180
cp 0
rs 8.3673
c 0
b 0
f 0
wmc 45

20 Methods

Rating   Name   Duplication   Size   Complexity  
A buildReviews() 0 7 2
A buildReview() 0 9 3
A build() 0 16 2
A buildOptionAvatar() 0 8 2
A buildOptionAssignedTo() 0 10 3
A buildOptionTitle() 0 7 3
A buildOptionContent() 0 5 2
A buildOptionRating() 0 7 2
A buildOptionAuthor() 0 7 3
A buildOptionDate() 0 14 4
A buildOptionResponse() 0 9 2
A wrap() 0 4 1
A getExcerpt() 0 15 2
A generateSchema() 0 5 2
A getOption() 0 6 2
A isOptionEnabled() 0 3 1
A normalizeText() 0 9 2
A isHiddenOrEmpty() 0 3 2
A getClass() 0 7 2
A isHidden() 0 6 3

How to fix   Complexity   

Complex Class

Complex classes like SiteReviews 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.

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 SiteReviews, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules\Html\Partials;
4
5
use GeminiLabs\SiteReviews\Database;
6
use GeminiLabs\SiteReviews\Database\OptionManager;
7
use GeminiLabs\SiteReviews\Helper;
8
use GeminiLabs\SiteReviews\Modules\Date;
9
use GeminiLabs\SiteReviews\Modules\Html;
10
use GeminiLabs\SiteReviews\Modules\Html\Builder;
11
use GeminiLabs\SiteReviews\Modules\Html\Partial;
12
use GeminiLabs\SiteReviews\Modules\Html\Template;
13
use GeminiLabs\SiteReviews\Modules\Rating;
14
use GeminiLabs\SiteReviews\Modules\Schema;
15
use WP_Post;
16
17
class SiteReviews
18
{
19
	/**
20
	 * @var array
21
	 */
22
	protected $args;
23
24
	/**
25
	 * @var array
26
	 */
27
	protected $options;
28
29
	/**
30
	 * @var object
31
	 */
32
	protected $reviews;
33
34
	/**
35
	 * @return void|string
36
	 */
37
	public function build( array $args = [] )
38
	{
39
		$this->args = $args;
40
		$this->options = glsr( Helper::class )->flattenArray( glsr( OptionManager::class )->all() );
41
		$this->reviews = glsr( Database::class )->getReviews( $args );
42
		$this->generateSchema();
43
		$navigation = wp_validate_boolean( $this->args['pagination'] )
44
			? glsr( Partial::class )->build( 'pagination', ['total' => $this->reviews->max_num_pages] )
45
			: '';
46
		return glsr( Template::class )->build( 'templates/reviews', [
47
			'context' => [
48
				'class' => $this->getClass(),
49
				'id' => $this->args['id'],
50
				'navigation' => $navigation,
51
			],
52
			'reviews' => $this->buildReviews(),
53
		]);
54
	}
55
56
	/**
57
	 * @return array
58
	 */
59
	public function buildReviews()
60
	{
61
		$reviews = [];
62
		foreach( $this->reviews->results as $review ) {
63
			$reviews[] = $this->buildReview( $review );
64
		}
65
		return $reviews;
66
	}
67
68
	/**
69
	 * @param object $review
70
	 * @return object
71
	 */
72
	protected function buildReview( $review )
73
	{
74
		$generatedReview = [];
75
		foreach( $review as $key => $value ) {
76
			$method = glsr( Helper::class )->buildMethodName( $key, 'buildOption' );
77
			if( !method_exists( $this, $method ))continue;
78
			$generatedReview[$key] = $this->$method( $key, $value );
79
		}
80
		return (object)$generatedReview;
81
	}
82
83
	/**
84
	 * @param string $key
85
	 * @param string $value
86
	 * @return void|string
87
	 */
88
	protected function buildOptionAssignedTo( $key, $value )
89
	{
90
		if( $this->isHiddenOrEmpty( $key, 'settings.reviews.assigned_links.enabled' ))return;
91
		$post = get_post( intval( $value ));
92
		if( !( $post instanceof WP_Post ))return;
93
		$permalink = glsr( Builder::class )->a( get_the_title( $post->ID ), [
94
			'href' => get_the_permalink( $post->ID ),
95
		]);
96
		$assignedTo = sprintf( __( 'Review of %s', 'site-reviews' ), $permalink );
97
		return $this->wrap( $key, '<span>'.$assignedTo.'</span>' );
98
	}
99
100
	/**
101
	 * @param string $key
102
	 * @param string $value
103
	 * @return void|string
104
	 */
105
	protected function buildOptionAuthor( $key, $value )
106
	{
107
		if( $this->isHidden( $key ))return;
108
		$prefix = !$this->isOptionEnabled( 'settings.reviews.avatars.enabled' )
109
			? apply_filters( 'site-reviews/review/author/prefix', '&mdash;' )
110
			: '';
111
		return $this->wrap( $key, $prefix.'<span>'.$value.'</span>' );
112
	}
113
114
	/**
115
	 * @param string $key
116
	 * @param string $value
117
	 * @return void|string
118
	 */
119
	protected function buildOptionAvatar( $key, $value )
120
	{
121
		if( $this->isHidden( $key, 'settings.reviews.avatars.enabled' ))return;
122
		$size = $this->getOption( 'settings.reviews.avatars.size', 36 );
123
		return $this->wrap( $key, glsr( Builder::class )->img([
124
			'src' => $value,
125
			'height' => $size,
126
			'width' => $size,
127
		]));
128
	}
129
130
	/**
131
	 * @param string $key
132
	 * @param string $value
133
	 * @return void|string
134
	 */
135
	protected function buildOptionContent( $key, $value )
136
	{
137
		$text = $this->normalizeText( $value );
138
		if( $this->isHiddenOrEmpty( $key, $text ))return;
139
		return $this->wrap( $key, '<p>'.$text.'</p>' );
140
	}
141
142
	/**
143
	 * @param string $key
144
	 * @param string $value
145
	 * @return void|string
146
	 */
147
	protected function buildOptionDate( $key, $value )
148
	{
149
		if( $this->isHidden( $key ))return;
150
		$dateFormat = $this->getOption( 'settings.reviews.date.format', 'default' );
151
		if( $dateFormat == 'relative' ) {
152
			$date = glsr( Date::class )->relative( $value );
153
		}
154
		else {
155
			$format = $dateFormat == 'custom'
156
				? $this->getOption( 'settings.reviews.date.custom', 'M j, Y' )
157
				: (string)get_option( 'date_format' );
158
			$date = date_i18n( $format, strtotime( $value ));
159
		}
160
		return $this->wrap( $key, '<span>'.$date.'</span>' );
161
	}
162
163
	/**
164
	 * @param string $key
165
	 * @param string $value
166
	 * @return void|string
167
	 */
168
	protected function buildOptionRating( $key, $value )
169
	{
170
		if( $this->isHiddenOrEmpty( $key, $value ))return;
171
		$rating = glsr( Html::class )->buildPartial( 'star-rating', [
172
			'rating' => $value,
173
		]);
174
		return $this->wrap( $key, $rating );
175
	}
176
177
	/**
178
	 * @param string $key
179
	 * @param string $value
180
	 * @return void|string
181
	 */
182
	protected function buildOptionResponse( $key, $value )
183
	{
184
		if( $this->isHiddenOrEmpty( $key, $value ))return;
185
		$title = sprintf( __( 'Response from %s', 'site-reviews' ), get_bloginfo( 'name' ));
186
		$text = $this->normalizeText( $value );
187
		$text = '<p><strong>'.$title.'</strong></p><p>'.$text.'</p>';
188
		return $this->wrap( $key,
189
			glsr( Builder::class )->div( $text, ['class' => 'glsr-review-response-inner'] ).
190
			glsr( Builder::class )->div( ['class' => 'glsr-review-response-background'] )
191
		);
192
	}
193
194
	/**
195
	 * @param string $key
196
	 * @param string $value
197
	 * @return void|string
198
	 */
199
	protected function buildOptionTitle( $key, $value )
200
	{
201
		if( $this->isHidden( $key ))return;
202
		if( empty( $value )) {
203
			$value = __( 'No Title', 'site-reviews' );
204
		}
205
		return $this->wrap( $key, '<h3>'.$value.'</h3>' );
206
	}
207
208
	/**
209
	 * @return void
210
	 */
211
	protected function generateSchema()
212
	{
213
		if( !wp_validate_boolean( $this->args['schema'] ))return;
214
		glsr( Schema::class )->store(
215
			glsr( Schema::class )->build( $this->args )
216
		);
217
	}
218
219
	/**
220
	 * @return string
221
	 */
222
	protected function getClass()
223
	{
224
		$style = apply_filters( 'site-reviews/style', 'glsr-style' );
225
		$pagination = $this->args['pagination'] == 'ajax'
226
			? 'glsr-ajax-pagination'
227
			: '';
228
		return trim( 'glsr-reviews '.$style.' '.$pagination.' '.$this->args['class'] );
229
	}
230
231
	/**
232
	 * @param string $text
233
	 * @return string
234
	 */
235
	protected function getExcerpt( $text )
236
	{
237
		$limit = $this->getOption( 'settings.reviews.excerpt.length', 55 );
238
		if( str_word_count( $text, 0 ) > $limit ) {
239
			$words = array_keys( str_word_count( $text, 2 ));
240
			$excerpt = ltrim( substr( $text, 0, $words[$limit] ));
241
			$hiddenText = substr( $text, strlen( $excerpt ));
242
			$showMore = glsr( Builder::class )->span( $hiddenText, [
243
				'class' => 'glsr-hidden glsr-hidden-text',
244
				'data-show-less' => __( 'Show less', 'site-reviews' ),
245
				'data-show-more' => __( 'Show more', 'site-reviews' ),
246
			]);
247
			$text = $excerpt.$showMore;
248
		}
249
		return nl2br( $text );
250
	}
251
252
	/**
253
	 * @param string $path
254
	 * @param mixed $fallback
255
	 * @return mixed
256
	 */
257
	protected function getOption( $path, $fallback = '' )
258
	{
259
		if( array_key_exists( $path, $this->options )) {
260
			return $this->options[$path];
261
		}
262
		return $fallback;
263
	}
264
265
	/**
266
	 * @param string $key
267
	 * @param string $path
268
	 * @return bool
269
	 */
270
	protected function isHidden( $key, $path = '' )
271
	{
272
		$isOptionEnabled = !empty( $path )
273
			? $this->isOptionEnabled( $path )
274
			: true;
275
		return in_array( $key, $this->args['hide'] ) || !$isOptionEnabled;
276
	}
277
278
	/**
279
	 * @param string $key
280
	 * @param string $value
281
	 * @return bool
282
	 */
283
	protected function isHiddenOrEmpty( $key, $value )
284
	{
285
		return $this->isHidden( $key ) || empty( $value );
286
	}
287
288
	/**
289
	 * @param string $path
290
	 * @return bool
291
	 */
292
	protected function isOptionEnabled( $path )
293
	{
294
		return $this->getOption( $path ) == 'yes';
295
	}
296
297
	/**
298
	 * @param string $text
299
	 * @return string
300
	 */
301
	protected function normalizeText( $text )
302
	{
303
		$text = wp_kses( $text, wp_kses_allowed_html() );
304
		$text = convert_smilies( wptexturize( strip_shortcodes( $text )));
305
		$text = str_replace( ']]>', ']]&gt;', $text );
306
		$text = preg_replace( '/(\R){2,}/', '$1', $text );
307
		return $this->isOptionEnabled( 'settings.reviews.excerpt.enabled' )
308
			? $this->getExcerpt( $text )
309
			: $text;
310
	}
311
312
	/**
313
	 * @param string $key
314
	 * @param string $value
315
	 * @return string
316
	 */
317
	protected function wrap( $key, $value )
318
	{
319
		return glsr( Builder::class )->div( $value, [
320
			'class' => 'glsr-review-'.$key,
321
		]);
322
	}
323
}
324