Passed
Push — master ( cec1ed...b70895 )
by Paul
03:44
created

CountsManager::increasePostCounts()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 6.28

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 1
dl 0
loc 8
ccs 2
cts 7
cp 0.2857
crap 6.28
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Database;
4
5
use GeminiLabs\SiteReviews\Application;
6
use GeminiLabs\SiteReviews\Database\OptionManager;
7
use GeminiLabs\SiteReviews\Database\ReviewManager;
8
use GeminiLabs\SiteReviews\Database\SqlQueries;
9
use GeminiLabs\SiteReviews\Modules\Rating;
10
use GeminiLabs\SiteReviews\Review;
11
use WP_Post;
12
use WP_Term;
13
14
class CountsManager
15
{
16
	const META_AVERAGE = '_glsr_average';
17
	const META_COUNT = '_glsr_count';
18
	const META_RANKING = '_glsr_ranking';
19
20
	/**
21
	 * @param int $limit
22
	 * @return array
23
	 */
24 1
	public function buildCounts( $limit = 500 )
25
	{
26 1
		return $this->build( $limit );
27
	}
28
29
	/**
30
	 * @param int $postId
31
	 * @param int $limit
32
	 * @return array
33
	 */
34
	public function buildPostCounts( $postId, $limit = 500 )
35
	{
36
		return $this->build( $limit, ['post_id' => $postId] );
37
	}
38
39
	/**
40
	 * @param int $termId
41
	 * @param int $limit
42
	 * @return array
43
	 */
44
	public function buildTermCounts( $termId, $limit = 500 )
45
	{
46
		return $this->build( $limit, ['term_id' => $termId] );
47
	}
48
49
	/**
50
	 * @return void
51
	 */
52
	public function decrease( Review $review )
53
	{
54
		$this->decreaseCounts( $review );
55
		$this->decreasePostCounts( $review );
56
		$this->decreaseTermCounts( $review );
57
	}
58
59
	/**
60
	 * @return void
61
	 */
62
	public function decreaseCounts( Review $review )
63
	{
64
		$this->setCounts( $this->decreaseRating(
65
			$this->getCounts(),
66
			$review->review_type,
67
			$review->rating
68
		));
69
	}
70
71
	/**
72
	 * @return void
73
	 */
74
	public function decreasePostCounts( Review $review )
75
	{
76
		if( empty( $counts = $this->getPostCounts( $review->assigned_to )))return;
77
		$counts = $this->decreaseRating( $counts, $review->review_type, $review->rating );
78
		$this->setPostCounts( $review->assigned_to, $counts );
79
	}
80
81
	/**
82
	 * @return void
83
	 */
84
	public function decreaseTermCounts( Review $review )
85
	{
86
		foreach( $review->term_ids as $termId ) {
87
			if( empty( $counts = $this->getTermCounts( $termId )))continue;
88
			$counts = $this->decreaseRating( $counts, $review->review_type, $review->rating );
89
			$this->setTermCounts( $termId, $counts );
90
		}
91
	}
92
93
	/**
94
	 * @return array
95
	 */
96
	public function flatten( array $reviewCounts, array $args = [] )
97
	{
98
		$counts = [];
99
		array_walk_recursive( $reviewCounts, function( $num, $index ) use( &$counts ) {
100
			$counts[$index] = isset( $counts[$index] )
101
				? $num + $counts[$index]
102
				: $num;
103
		});
104
		$args = wp_parse_args( $args, [
105
			'max' => Rating::MAX_RATING,
106
			'min' => Rating::MIN_RATING,
107
		]);
108
		foreach( $counts as $index => &$num ) {
109
			if( $index >= intval( $args['min'] ) && $index <= intval( $args['max'] ))continue;
110
			$num = 0;
111
		}
112
		return $counts;
113
	}
114
115
	/**
116
	 * @return array
117
	 */
118
	public function get( array $args = [] )
119
	{
120
		$args = wp_parse_args( $args, [
121
			'post_ids' => [],
122
			'term_ids' => [],
123
			'type' => 'local',
124
		]);
125
		$counts = [];
126
		foreach( $args['post_ids'] as $postId ) {
127
			$counts[] = $this->getPostCounts( $postId );
128
		}
129
		foreach( $args['term_ids'] as $termId ) {
130
			$counts[] = $this->getTermCounts( $termId );
131
		}
132
		if( empty( $counts )) {
133
			$counts[] = $this->getCounts();
134
		}
135
		return array_column( $counts, $args['type'] );
136
	}
137
138
	/**
139
	 * @return array
140
	 */
141 1
	public function getCounts()
142
	{
143 1
		return glsr( OptionManager::class )->get( 'count', [] );
144
	}
145
146
	/**
147
	 * @param int $postId
148
	 * @return array
149
	 */
150
	public function getPostCounts( $postId )
151
	{
152
		return array_filter( (array)get_post_meta( $postId, static::META_COUNT, true ));
153
	}
154
155
	/**
156
	 * @param int $termId
157
	 * @return array
158
	 */
159
	public function getTermCounts( $termId )
160
	{
161
		return array_filter( (array)get_term_meta( $termId, static::META_COUNT, true ));
162
	}
163
164
	/**
165
	 * @return void
166
	 */
167 1
	public function increase( Review $review )
168
	{
169 1
		$this->increaseCounts( $review );
170 1
		$this->increasePostCounts( $review );
171 1
		$this->increaseTermCounts( $review );
172 1
	}
173
174
	/**
175
	 * @return void
176
	 */
177 1
	public function increaseCounts( Review $review )
178
	{
179 1
		if( empty( $counts = $this->getCounts() )) {
180 1
			$counts = $this->buildCounts();
181
		}
182 1
		$this->setCounts( $this->increaseRating(
183 1
			$counts,
184 1
			$review->review_type,
185 1
			$review->rating
186
		));
187 1
	}
188
189
	/**
190
	 * @return void
191
	 */
192 1
	public function increasePostCounts( Review $review )
193
	{
194 1
		if( !( get_post( $review->assigned_to ) instanceof WP_Post ))return;
195
		$counts = $this->getPostCounts( $review->assigned_to );
196
		$counts = empty( $counts )
197
			? $this->buildPostCounts( $review->assigned_to )
198
			: $this->increaseRating( $counts, $review->review_type, $review->rating );
199
		$this->setPostCounts( $review->assigned_to, $counts );
200
	}
201
202
	/**
203
	 * @return void
204
	 */
205 1
	public function increaseTermCounts( Review $review )
206
	{
207 1
		$termIds = glsr( ReviewManager::class )->normalizeTerms( implode( ',', $review->term_ids ));
208 1
		foreach( $termIds as $termId ) {
209
			$counts = $this->getTermCounts( $termId );
210
			$counts = empty( $counts )
211
				? $this->buildTermCounts( $termId )
212
				: $this->increaseRating( $counts, $review->review_type, $review->rating );
213
			$this->setTermCounts( $termId, $counts );
214
		}
215 1
	}
216
217
	/**
218
	 * @return void
219
	 */
220 1
	public function setCounts( array $reviewCounts )
221
	{
222 1
		glsr( OptionManager::class )->set( 'count', $reviewCounts );
223 1
	}
224
225
	/**
226
	 * @param int $postId
227
	 * @return void
228
	 */
229
	public function setPostCounts( $postId, array $reviewCounts )
230
	{
231
		$ratingCounts = glsr( CountsManager::class )->flatten( $reviewCounts );
232
		update_post_meta( $postId, static::META_COUNT, $reviewCounts );
233
		update_post_meta( $postId, static::META_AVERAGE, glsr( Rating::class )->getAverage( $ratingCounts ));
234
		update_post_meta( $postId, static::META_RANKING, glsr( Rating::class )->getRanking( $ratingCounts ));
235
	}
236
237
	/**
238
	 * @param int $termId
239
	 * @return void
240
	 */
241
	public function setTermCounts( $termId, array $reviewCounts )
242
	{
243
		if( !term_exists( $termId ))return;
244
		$ratingCounts = glsr( CountsManager::class )->flatten( $reviewCounts );
245
		update_term_meta( $termId, static::META_COUNT, $reviewCounts );
246
		update_term_meta( $termId, static::META_AVERAGE, glsr( Rating::class )->getAverage( $ratingCounts ));
247
		update_term_meta( $termId, static::META_RANKING, glsr( Rating::class )->getRanking( $ratingCounts ));
248
	}
249
250
	/**
251
	 * @param int $limit
252
	 * @return array
253
	 */
254 1
	protected function build( $limit, array $args = [] )
255
	{
256 1
		$counts = [];
257 1
		$lastPostId = 0;
258 1
		while( $reviews = $this->queryReviews( $args, $lastPostId, $limit )) {
259 1
			$types = array_keys( array_flip( array_column( $reviews, 'type' )));
260 1
			foreach( $types as $type ) {
261 1
				if( isset( $counts[$type] ))continue;
262 1
				$counts[$type] = array_fill_keys( range( 0, Rating::MAX_RATING ), 0 );
263
			}
264 1
			foreach( $reviews as $review ) {
265 1
				$counts[$review->type][$review->rating]++;
266
			}
267 1
			$lastPostId = end( $reviews )->ID;
268
		}
269 1
		return $counts;
270
	}
271
272
	/**
273
	 * @param string $type
274
	 * @param int $rating
275
	 * @return array
276
	 */
277
	protected function decreaseRating( array $reviewCounts, $type, $rating )
278
	{
279
		if( isset( $reviewCounts[$type][$rating] )) {
280
			$reviewCounts[$type][$rating] = max( 0, $reviewCounts[$type][$rating] - 1 );
281
		}
282
		return $reviewCounts;
283
	}
284
285
	/**
286
	 * @param string $type
287
	 * @param int $rating
288
	 * @return array
289
	 */
290 1
	protected function increaseRating( array $reviewCounts, $type, $rating )
291
	{
292 1
		if( !array_key_exists( $type, glsr()->reviewTypes )) {
293
			return $reviewCounts;
294
		}
295 1
		if( !array_key_exists( $type, $reviewCounts )) {
296
			$reviewCounts[$type] = [];
297
		}
298 1
		$reviewCounts = $this->normalize( $reviewCounts );
299 1
		$reviewCounts[$type][$rating] = intval( $reviewCounts[$type][$rating] ) + 1;
300 1
		return $reviewCounts;
301
	}
302
303
	/**
304
	 * @return array
305
	 */
306 1
	protected function normalize( array $reviewCounts )
307
	{
308 1
		foreach( $reviewCounts as &$counts ) {
309 1
			foreach( range( 0, Rating::MAX_RATING ) as $index ) {
310 1
				if( isset( $counts[$index] ))continue;
311
				$counts[$index] = 0;
312
			}
313 1
			ksort( $counts );
314
		}
315 1
		return $reviewCounts;
316
	}
317
318
	/**
319
	 * @param int $lastPostId
320
	 * @param int $limit
321
	 * @return void|array
322
	 */
323 1
	protected function queryReviews( array $args = [], $lastPostId, $limit )
324
	{
325 1
		$args = wp_parse_args( $args, array_fill_keys( ['post_id', 'term_id'], '' ));
326 1
		if( empty( array_filter( $args ))) {
327 1
			return glsr( SqlQueries::class )->getReviewCounts( $lastPostId, $limit );
328
		}
329
		if( !empty( $args['post_id'] )) {
330
			return glsr( SqlQueries::class )->getReviewPostCounts( $args['post_id'], $lastPostId, $limit );
331
		}
332
		if( !empty( $args['term_id'] )) {
333
			return glsr( SqlQueries::class )->getReviewTermCounts( $args['term_id'], $lastPostId, $limit );
334
		}
335
	}
336
}
337