Passed
Push — master ( 7e7a3a...c54c1a )
by Paul
12:25 queued 05:17
created

ReviewController::onAfterChangeAssignedTerms()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 6
dl 0
loc 7
ccs 6
cts 6
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Controllers;
4
5
use GeminiLabs\SiteReviews\Commands\AssignPosts;
6
use GeminiLabs\SiteReviews\Commands\AssignTerms;
7
use GeminiLabs\SiteReviews\Commands\AssignUsers;
8
use GeminiLabs\SiteReviews\Commands\CreateReview;
9
use GeminiLabs\SiteReviews\Commands\ToggleStatus;
10
use GeminiLabs\SiteReviews\Commands\UnassignPosts;
11
use GeminiLabs\SiteReviews\Commands\UnassignTerms;
12
use GeminiLabs\SiteReviews\Commands\UnassignUsers;
13
use GeminiLabs\SiteReviews\Database;
14
use GeminiLabs\SiteReviews\Database\Cache;
15
use GeminiLabs\SiteReviews\Database\Query;
16
use GeminiLabs\SiteReviews\Database\ReviewManager;
17
use GeminiLabs\SiteReviews\Database\TaxonomyManager;
18
use GeminiLabs\SiteReviews\Defaults\RatingDefaults;
19
use GeminiLabs\SiteReviews\Helper;
20
use GeminiLabs\SiteReviews\Helpers\Arr;
21
use GeminiLabs\SiteReviews\Helpers\Cast;
22
use GeminiLabs\SiteReviews\Review;
23
24
class ReviewController extends Controller
25
{
26
    /**
27
     * @return void
28
     * @action admin_action_approve
29
     */
30
    public function approve()
31
    {
32
        if (glsr()->id == filter_input(INPUT_GET, 'plugin')) {
33
            check_admin_referer('approve-review_'.($postId = $this->getPostId()));
34
            $this->execute(new ToggleStatus($postId, 'publish'));
35
            wp_safe_redirect(wp_get_referer());
36
            exit;
37
        }
38
    }
39
40
    /**
41
     * @param array $posts
42
     * @return array
43
     * @filter the_posts
44
     */
45
    public function filterPostsToCacheReviews($posts)
46
    {
47
        $reviews = array_filter($posts, function ($post) {
48
            return glsr()->post_type === $post->post_type;
49
        });
50
        if ($postIds = wp_list_pluck($reviews, 'ID')) {
51
            glsr(Query::class)->reviews([], $postIds); // this caches the associated Review objects
52
        }
53
        return $posts;
54
    }
55
56
    /**
57
     * Triggered when one or more categories are added or removed from a review.
58
     *
59
     * @param int $postId
60
     * @param array $terms
61
     * @param array $newTTIds
62
     * @param string $taxonomy
63
     * @param bool $append
64
     * @param array $oldTTIds
65
     * @return void
66
     * @action set_object_terms
67
     */
68 12
    public function onAfterChangeAssignedTerms($postId, $terms, $newTTIds, $taxonomy, $append, $oldTTIds)
69
    {
70 12
        if (Review::isReview($postId)) {
71 2
            $review = glsr(Query::class)->review($postId);
72 2
            $diff = $this->getAssignedDiffs($oldTTIds, $newTTIds);
73 2
            $this->execute(new UnassignTerms($review, $diff['old']));
74 2
            $this->execute(new AssignTerms($review, $diff['new']));
75
        }
76 12
    }
77
78
    /**
79
     * Triggered when a post status changes or when a review is approved|unapproved|trashed.
80
     *
81
     * @param string $oldStatus
82
     * @param string $newStatus
83
     * @param \WP_Post $post
84
     * @return void
85
     * @action transition_post_status
86
     */
87 15
    public function onAfterChangeStatus($newStatus, $oldStatus, $post)
88
    {
89 15
        if (in_array($oldStatus, ['new', $newStatus])) {
90 15
            return;
91
        }
92
        $isPublished = 'publish' === $newStatus;
93
        if (Review::isReview($post)) {
94
            glsr(ReviewManager::class)->update($post->ID, ['is_approved' => $isPublished]);
95
        } else {
96
            glsr(ReviewManager::class)->updateAssignedPost($post->ID, $isPublished);
97
        }
98
    }
99
100
    /**
101
     * Triggered when a review's assigned post IDs are updated.
102
     *
103
     * @return void
104
     * @action site-reviews/review/updated/post_ids
105
     */
106
    public function onChangeAssignedPosts(Review $review, array $postIds = [])
107
    {
108
        $diff = $this->getAssignedDiffs($review->assigned_posts, $postIds);
109
        $this->execute(new UnassignPosts($review, $diff['old']));
110
        $this->execute(new AssignPosts($review, $diff['new']));
111
    }
112
113
    /**
114
     * Triggered when a review's assigned users IDs are updated.
115
     *
116
     * @return void
117
     * @action site-reviews/review/updated/user_ids
118
     */
119
    public function onChangeAssignedUsers(Review $review, array $userIds = [])
120
    {
121
        $diff = $this->getAssignedDiffs($review->assigned_users, $userIds);
122
        $this->execute(new UnassignUsers($review, $diff['old']));
123
        $this->execute(new AssignUsers($review, $diff['new']));
124
    }
125
126
    /**
127
     * Triggered after a review is created.
128
     *
129
     * @return void
130
     * @action site-reviews/review/created
131
     */
132 13
    public function onCreatedReview(Review $review, CreateReview $command)
133
    {
134 13
        $this->execute(new AssignPosts($review, $command->assigned_posts));
135 13
        $this->execute(new AssignUsers($review, $command->assigned_users));
136 13
    }
137
138
    /**
139
     * Triggered when a review is created.
140
     *
141
     * @param int $postId
142
     * @return void
143
     * @action site-reviews/review/create
144
     */
145 13
    public function onCreateReview($postId, CreateReview $command)
146
    {
147 13
        $values = glsr()->args($command->toArray()); // this filters the values
148 13
        $data = glsr(RatingDefaults::class)->restrict($values->toArray());
149 13
        $data['review_id'] = $postId;
150 13
        $data['is_approved'] = 'publish' === get_post_status($postId);
151 13
        if (false === glsr(Database::class)->insert('ratings', $data)) {
152
            wp_delete_post($postId, true); // remove post as review was not created
153
            return;
154
        }
155 13
        if (!empty($values->response)) {
156
            glsr(Database::class)->metaSet($postId, 'response', $values->response); // save the response if one is provided
157
        }
158 13
        glsr(TaxonomyManager::class)->setTerms($postId, $values->assigned_terms); // terms are assigned with the set_object_terms hook
159 13
        foreach ($values->custom as $key => $value) {
160
            glsr(Database::class)->metaSet($postId, 'custom_'.$key, $value);
161
        }
162 13
    }
163
164
    /**
165
     * Triggered when a review or other post type is deleted and the posts table uses the MyISAM engine.
166
     * @param int $postId
167
     * @param \WP_Post $post
168
     * @return void
169
     * @action deleted_post
170
     */
171
    public function onDeletePost($postId, $post)
172
    {
173
        if (glsr()->post_type === $post->post_type) {
174
            $this->onDeleteReview($postId);
175
            return;
176
        }
177
        $reviews = glsr(Query::class)->reviews([
178
            'assigned_posts' => $postId,
179
            'per_page' => -1,
180
            'status' => 'all',
181
        ]);
182
        if (glsr(Database::class)->delete('assigned_posts', ['post_id' => $postId])) {
183
            foreach ($reviews as $review) {
184
                glsr(Cache::class)->delete($review->ID, 'reviews');
185
            }
186
        }
187
    }
188
189
    /**
190
     * Triggered when a review is deleted and the posts table uses the MyISAM engine.
191
     * @param int $reviewId
192
     * @return void
193
     * @see $this->onDeletePost()
194
     */
195
    public function onDeleteReview($reviewId)
196
    {
197
        if (glsr(Database::class)->delete('ratings', ['review_id' => $reviewId])) {
198
            glsr(Cache::class)->delete($reviewId, 'reviews');
199
        }
200
    }
201
202
    /**
203
     * Triggered when a user is deleted and the users table uses the MyISAM engine.
204
     * @param int $userId
205
     * @return void
206
     * @action deleted_user
207
     */
208
    public function onDeleteUser($userId)
209
    {
210
        $reviews = glsr(Query::class)->reviews([
211
            'assigned_users' => $userId,
212
            'per_page' => -1,
213
            'status' => 'all',
214
        ]);
215
        if (glsr(Database::class)->delete('assigned_users', ['user_id' => $userId])) {
216
            foreach ($reviews as $review) {
217
                glsr(Cache::class)->delete($review->ID, 'reviews');
218
            }
219
        }
220
    }
221
222
    /**
223
     * Triggered when a review is edited.
224
     * It's unnecessary to trigger a term recount as this is done by the set_object_terms hook
225
     * We need to use "edit_post" to support revisions (vs "save_post").
226
     *
227
     * @param int $postId
228
     * @return void
229
     * @action edit_post_{glsr()->post_type}
230
     */
231
    public function onEditReview($postId)
232
    {
233
        $input = 'edit' === glsr_current_screen()->base ? INPUT_GET : INPUT_POST;
234
        if (!glsr()->can('edit_posts') || 'glsr_action' === filter_input($input, 'action')) {
235
            return; // abort if user does not have permission or if not a proper post update (i.e. approve/unapprove)
236
        }
237
        $review = glsr(Query::class)->review($postId);
238
        $assignedPostIds = filter_input($input, 'post_ids', FILTER_SANITIZE_NUMBER_INT, FILTER_FORCE_ARRAY);
239
        $assignedUserIds = filter_input($input, 'user_ids', FILTER_SANITIZE_NUMBER_INT, FILTER_FORCE_ARRAY);
240
        glsr()->action('review/updated/post_ids', $review, Cast::toArray($assignedPostIds)); // trigger a recount of assigned posts
241
        glsr()->action('review/updated/user_ids', $review, Cast::toArray($assignedUserIds)); // trigger a recount of assigned users
242
        glsr(MetaboxController::class)->saveResponseMetabox($review);
243
        $submittedValues = Helper::filterInputArray(glsr()->id);
244
        if (Arr::get($submittedValues, 'is_editing_review')) {
245
            $submittedValues['rating'] = Arr::get($submittedValues, 'rating');
246
            glsr(ReviewManager::class)->update($postId, $submittedValues);
247
            glsr(ReviewManager::class)->updateCustom($postId, $submittedValues);
248
        }
249
        glsr()->action('review/saved', glsr(Query::class)->review($postId), $submittedValues);
250
    }
251
252
    /**
253
     * @return void
254
     * @action admin_action_unapprove
255
     */
256
    public function unapprove()
257
    {
258
        if (glsr()->id == filter_input(INPUT_GET, 'plugin')) {
259
            check_admin_referer('unapprove-review_'.($postId = $this->getPostId()));
260
            $this->execute(new ToggleStatus($postId, 'pending'));
261
            wp_safe_redirect(wp_get_referer());
262
            exit;
263
        }
264
    }
265
266
    /**
267
     * @return array
268
     */
269 2
    protected function getAssignedDiffs(array $existing, array $replacements)
270
    {
271 2
        sort($existing);
272 2
        sort($replacements);
273 2
        $new = $old = [];
274 2
        if ($existing !== $replacements) {
275 2
            $ignored = array_intersect($existing, $replacements);
276 2
            $new = array_diff($replacements, $ignored);
277 2
            $old = array_diff($existing, $ignored);
278
        }
279
        return [
280 2
            'new' => $new,
281 2
            'old' => $old,
282
        ];
283
    }
284
}
285