Passed
Push — master ( 49ec8d...5de802 )
by Paul
03:41
created

CountsManager::getCounts()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
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
			$term = get_term( $termId, Application::TAXONOMY );
131
			if( !isset( $term->term_id ))continue;
132
			$counts[] = $this->getTermCounts( $termId );
133
		}
134
		if( empty( $counts )) {
135
			$counts[] = $this->getCounts();
136
		}
137
		return array_column( $counts, $args['type'] );
138
	}
139
140
	/**
141
	 * @return array
142
	 */
143 1
	public function getCounts()
144
	{
145 1
		return glsr( OptionManager::class )->get( 'count', [] );
146
	}
147
148
	/**
149
	 * @param int $postId
150
	 * @return array
151
	 */
152
	public function getPostCounts( $postId )
153
	{
154
		return (array)get_post_meta( $postId, static::META_COUNT, true );
155
	}
156
157
	/**
158
	 * @param int $termId
159
	 * @return array
160
	 */
161
	public function getTermCounts( $termId )
162
	{
163
		return (array)get_term_meta( $termId, static::META_COUNT, true );
164
	}
165
166
	/**
167
	 * @return void
168
	 */
169 1
	public function increase( Review $review )
170
	{
171 1
		$this->increaseCounts( $review );
172 1
		$this->increasePostCounts( $review );
173 1
		$this->increaseTermCounts( $review );
174 1
	}
175
176
	/**
177
	 * @return void
178
	 */
179 1
	public function increaseCounts( Review $review )
180
	{
181 1
		if( empty( $counts = $this->getCounts() )) {
182 1
			$counts = $this->buildCounts();
183
		}
184 1
		$this->setCounts( $this->increaseRating(
185 1
			$counts,
186 1
			$review->review_type,
187 1
			$review->rating
188
		));
189 1
	}
190
191
	/**
192
	 * @return void
193
	 */
194 1
	public function increasePostCounts( Review $review )
195
	{
196 1
		if( !( get_post( $review->assigned_to ) instanceof WP_Post ))return;
197
		if( empty( $counts = $this->getPostCounts( $review->assigned_to ))) {
198
			$counts = $this->buildPostCounts( $review->assigned_to );
199
		}
200
		$counts = $this->increaseRating( $counts, $review->review_type, $review->rating );
201
		$this->setPostCounts( $review->assigned_to, $counts );
202
	}
203
204
	/**
205
	 * @return void
206
	 */
207 1
	public function increaseTermCounts( Review $review )
208
	{
209 1
		foreach( $review->term_ids as $termId ) {
210
			if( !( get_term( $termId, Application::TAXONOMY ) instanceof WP_Term ))continue;
211
			if( empty( $counts = $this->getTermCounts( $termId ))) {
212
				$counts = $this->buildTermCounts( $termId );
213
			}
214
			$counts = $this->increaseRating( $counts, $review->review_type, $review->rating );
215
			$this->setTermCounts( $termId, $counts );
216
		}
217 1
	}
218
219
	/**
220
	 * @return void
221
	 */
222 1
	public function setCounts( array $reviewCounts )
223
	{
224 1
		glsr( OptionManager::class )->set( 'count', $reviewCounts );
225 1
	}
226
227
	/**
228
	 * @param int $postId
229
	 * @return void
230
	 */
231
	public function setPostCounts( $postId, array $reviewCounts )
232
	{
233
		$ratingCounts = glsr( CountsManager::class )->flatten( $reviewCounts );
234
		update_post_meta( $postId, static::META_COUNT, $reviewCounts );
235
		update_post_meta( $postId, static::META_AVERAGE, glsr( Rating::class )->getAverage( $ratingCounts ));
236
		update_post_meta( $postId, static::META_RANKING, glsr( Rating::class )->getRanking( $ratingCounts ));
237
	}
238
239
	/**
240
	 * @param int $termId
241
	 * @return void
242
	 */
243
	public function setTermCounts( $termId, array $reviewCounts )
244
	{
245
		if( !term_exists( $termId ))return;
246
		$ratingCounts = glsr( CountsManager::class )->flatten( $reviewCounts );
247
		update_term_meta( $termId, static::META_COUNT, $reviewCounts );
248
		update_term_meta( $termId, static::META_AVERAGE, glsr( Rating::class )->getAverage( $ratingCounts ));
249
		update_term_meta( $termId, static::META_RANKING, glsr( Rating::class )->getRanking( $ratingCounts ));
250
	}
251
252
	/**
253
	 * @param int $limit
254
	 * @return array
255
	 */
256 1
	protected function build( $limit, array $args = [] )
257
	{
258 1
		$counts = [];
259 1
		$lastPostId = 0;
260 1
		while( $reviews = $this->queryReviews( $args, $lastPostId, $limit )) {
261 1
			$types = array_keys( array_flip( array_column( $reviews, 'type' )));
262 1
			foreach( $types as $type ) {
263 1
				if( isset( $counts[$type] ))continue;
264 1
				$counts[$type] = array_fill_keys( range( 0, Rating::MAX_RATING ), 0 );
265
			}
266 1
			foreach( $reviews as $review ) {
267 1
				$counts[$review->type][$review->rating]++;
268
			}
269 1
			$lastPostId = end( $reviews )->ID;
270
		}
271 1
		return $counts;
272
	}
273
274
	/**
275
	 * @param string $type
276
	 * @param int $rating
277
	 * @return array
278
	 */
279
	protected function decreaseRating( array $reviewCounts, $type, $rating )
280
	{
281
		if( isset( $reviewCounts[$type][$rating] )) {
282
			$reviewCounts[$type][$rating] = max( 0, $reviewCounts[$type][$rating] - 1 );
283
		}
284
		return $reviewCounts;
285
	}
286
287
	/**
288
	 * @param string $type
289
	 * @param int $rating
290
	 * @return array
291
	 */
292 1
	protected function increaseRating( array $reviewCounts, $type, $rating )
293
	{
294 1
		if( !array_key_exists( $type, glsr()->reviewTypes )) {
295
			return $reviewCounts;
296
		}
297 1
		if( !array_key_exists( $type, $reviewCounts )) {
298
			$reviewCounts[$type] = [];
299
		}
300 1
		$reviewCounts = $this->normalize( $reviewCounts );
301 1
		$reviewCounts[$type][$rating] = intval( $reviewCounts[$type][$rating] ) + 1;
302 1
		return $reviewCounts;
303
	}
304
305
	/**
306
	 * @return array
307
	 */
308 1
	protected function normalize( array $reviewCounts )
309
	{
310 1
		foreach( $reviewCounts as &$counts ) {
311 1
			foreach( range( 0, Rating::MAX_RATING ) as $index ) {
312 1
				if( isset( $counts[$index] ))continue;
313
				$counts[$index] = 0;
314
			}
315 1
			ksort( $counts );
316
		}
317 1
		return $reviewCounts;
318
	}
319
320
	/**
321
	 * @param int $lastPostId
322
	 * @param int $limit
323
	 * @return void|array
324
	 */
325 1
	protected function queryReviews( array $args = [], $lastPostId, $limit )
326
	{
327 1
		$args = wp_parse_args( $args, array_fill_keys( ['post_id', 'term_id'], '' ));
328 1
		if( empty( array_filter( $args ))) {
329 1
			return glsr( SqlQueries::class )->getReviewCounts( $lastPostId, $limit );
330
		}
331
		if( !empty( $args['post_id'] )) {
332
			return glsr( SqlQueries::class )->getReviewPostCounts( $args['post_id'], $lastPostId, $limit );
333
		}
334
		if( !empty( $args['term_id'] )) {
335
			return glsr( SqlQueries::class )->getReviewTermCounts( $args['term_id'], $lastPostId, $limit );
336
		}
337
	}
338
}
339