Passed
Push — master ( 7e4cda...ab680b )
by Paul
08:39 queued 04:32
created

CountsManager::get()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 4
eloc 9
c 1
b 1
f 0
nc 8
nop 1
dl 0
loc 14
ccs 0
cts 10
cp 0
crap 20
rs 9.9666
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Database;
4
5
use GeminiLabs\SiteReviews\Application;
6
use GeminiLabs\SiteReviews\Database;
7
use GeminiLabs\SiteReviews\Helper;
8
use GeminiLabs\SiteReviews\Helpers\Arr;
9
use GeminiLabs\SiteReviews\Modules\Multilingual;
10
use GeminiLabs\SiteReviews\Modules\Rating;
11
use GeminiLabs\SiteReviews\Review;
12
use WP_Post;
13
14
class CountsManager
15
{
16
    const LIMIT = 500;
17
    const META_AVERAGE = '_glsr_average';
18
    const META_COUNT = '_glsr_count';
19
    const META_RANKING = '_glsr_ranking';
20
21
    /**
22
     * @return array
23
     */
24 1
    public function buildCounts(array $args = [])
25
    {
26
        $counts = [
27 1
            'local' => $this->generateEmptyCountsArray(),
28
        ];
29 1
        $query = $this->queryReviews($args);
30 1
        while ($query) {
31 1
            $counts = $this->populateCountsFromQuery($query, $counts);
32 1
            $query = $query->has_more
33
                ? $this->queryReviews($args, end($query->reviews)->ID)
34 1
                : false;
35
        }
36 1
        return $counts;
37
    }
38
39
    /**
40
     * @return void
41
     */
42
    public function decreaseAll(Review $review)
43
    {
44
        glsr(GlobalCountsManager::class)->decrease($review);
45
        glsr(PostCountsManager::class)->decrease($review);
46
        glsr(TermCountsManager::class)->decrease($review);
47
    }
48
49
    /**
50
     * @param string $type
51
     * @param int $rating
52
     * @return array
53
     */
54
    public function decreaseRating(array $reviewCounts, $type, $rating)
55
    {
56
        if (isset($reviewCounts[$type][$rating])) {
57
            $reviewCounts[$type][$rating] = max(0, $reviewCounts[$type][$rating] - 1);
58
        }
59
        return $reviewCounts;
60
    }
61
62
    /**
63
     * @return array
64
     */
65
    public function flatten(array $reviewCounts, array $args = [])
66
    {
67
        $counts = [];
68
        array_walk_recursive($reviewCounts, function ($num, $index) use (&$counts) {
69
            $counts[$index] = $num + intval(Arr::get($counts, $index, 0));
70
        });
71
        $min = Arr::get($args, 'min', glsr()->constant('MIN_RATING', Rating::class));
72
        $max = Arr::get($args, 'max', glsr()->constant('MAX_RATING', Rating::class));
73
        foreach ($counts as $index => &$num) {
74
            if (!Helper::inRange($index, $min, $max)) {
75
                $num = 0;
76
            }
77
        }
78
        return $counts;
79
    }
80
81
    /**
82
     * @return array
83
     */
84
    public function getCounts(array $args = [])
85
    {
86
        $args = $this->normalizeArgs($args);
87
        $counts = $this->hasMixedAssignment($args)
88
            ? $this->buildCounts($args) // force query the database
89
            : $this->get($args);
90
        return $this->normalize($counts);
91
    }
92
93
    /**
94
     * @return void
95
     */
96
    public function increaseAll(Review $review)
97
    {
98
        glsr(GlobalCountsManager::class)->increase($review);
99
        glsr(PostCountsManager::class)->increase($review);
100
        glsr(TermCountsManager::class)->increase($review);
101
    }
102
103
    /**
104
     * @param string $type
105
     * @param int $rating
106
     * @return array
107
     */
108 1
    public function increaseRating(array $reviewCounts, $type, $rating)
109
    {
110 1
        if (!array_key_exists($type, glsr()->reviewTypes)) {
111
            return $reviewCounts;
112
        }
113 1
        if (!array_key_exists($type, $reviewCounts)) {
114
            $reviewCounts[$type] = [];
115
        }
116 1
        $reviewCounts = $this->normalize($reviewCounts);
117 1
        $reviewCounts[$type][$rating] = intval($reviewCounts[$type][$rating]) + 1;
118 1
        return $reviewCounts;
119
    }
120
121
    /**
122
     * @return void
123
     */
124 1
    public function updateAll()
125
    {
126 1
        glsr(GlobalCountsManager::class)->updateAll();
127 1
        glsr(PostCountsManager::class)->updateAll();
128 1
        glsr(TermCountsManager::class)->updateAll();
129 1
    }
130
131
    /**
132
     * @return array
133
     */
134
    protected function combine(array $results)
135
    {
136
        if (!wp_is_numeric_array($results)) {
137
            return $results;
138
        }
139
        $mergedKeys = array_keys(array_merge(...$results));
140
        $counts = array_fill_keys($mergedKeys, $this->generateEmptyCountsArray());
141
        foreach ($results as $typeRatings) {
142
            foreach ($typeRatings as $type => $ratings) {
143
                foreach ($ratings as $index => $rating) {
144
                    $counts[$type][$index] = intval($rating) + $counts[$type][$index];
145
                }
146
            }
147
        }
148
        return $counts;
149
    }
150
151
    /**
152
     * @return array
153
     */
154 1
    protected function generateEmptyCountsArray()
155
    {
156 1
        return array_fill_keys(range(0, glsr()->constant('MAX_RATING', Rating::class)), 0);
157
    }
158
159
    /**
160
     * @return array
161
     */
162
    protected function get($args)
163
    {
164
        $results = [];
165
        foreach ($args['post_ids'] as $postId) {
166
            $results[] = glsr(PostCountsManager::class)->get($postId);
167
        }
168
        foreach ($args['term_ids'] as $termId) {
169
            $results[] = glsr(TermCountsManager::class)->get($termId);
170
        }
171
        if (empty($results)) {
172
            $results[] = glsr(GlobalCountsManager::class)->get();
173
        }
174
        $results[] = ['local' => $this->generateEmptyCountsArray()]; // make sure there is a fallback
175
        return $this->combine($results);
176
    }
177
178
    /**
179
     * @return bool
180
     */
181
    protected function hasMixedAssignment(array $args)
182
    {
183
        return !empty($args['post_ids']) && !empty($args['term_ids']);
184
    }
185
186
    /**
187
     * @return array
188
     */
189 1
    protected function normalize(array $reviewCounts)
190
    {
191 1
        foreach ($reviewCounts as &$counts) {
192 1
            foreach (array_keys($this->generateEmptyCountsArray()) as $index) {
193 1
                if (!isset($counts[$index])) {
194 1
                    $counts[$index] = 0;
195
                }
196
            }
197 1
            ksort($counts);
198
        }
199 1
        return $reviewCounts;
200
    }
201
202
    /**
203
     * @return array
204
     */
205
    protected function normalizeArgs(array $args)
206
    {
207
        $args = wp_parse_args(array_filter($args), [
208
            'post_ids' => [],
209
            'term_ids' => [],
210
            'type' => 'local',
211
        ]);
212
        $args['post_ids'] = glsr(Multilingual::class)->getPostIds($args['post_ids']);
213
        $args['type'] = $this->normalizeType($args['type']);
214
        return $args;
215
    }
216
217
    /**
218
     * @param string $type
219
     * @return string
220
     */
221
    protected function normalizeType($type)
222
    {
223
        return empty($type) || !is_string($type)
224
            ? 'local'
225
            : $type;
226
    }
227
228
    /**
229
     * @param object $query
230
     * @return array
231
     */
232 1
    protected function populateCountsFromQuery($query, array $counts)
233
    {
234 1
        foreach ($query->reviews as $review) {
235
            $type = $this->normalizeType($review->type);
236
            if (!array_key_exists($type, $counts)) {
237
                $counts[$type] = $this->generateEmptyCountsArray();
238
            }
239
            ++$counts[$type][$review->rating];
240
        }
241 1
        return $counts;
242
    }
243
244
    /**
245
     * @param int $lastPostId
246
     * @return object
247
     */
248 1
    protected function queryReviews(array $args = [], $lastPostId = 0)
249
    {
250 1
        $reviews = glsr(SqlQueries::class)->getReviewCounts($args, $lastPostId, static::LIMIT);
251 1
        $hasMore = is_array($reviews)
252 1
            ? count($reviews) == static::LIMIT
253 1
            : false;
254
        return (object) [
255 1
            'has_more' => $hasMore,
256 1
            'reviews' => $reviews,
257
        ];
258
    }
259
}
260