Passed
Push — master ( a406f9...3ba855 )
by Paul
08:12 queued 04:00
created

EditorController   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 398
Duplicated Lines 0 %

Test Coverage

Coverage 4.6%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
eloc 143
dl 0
loc 398
ccs 8
cts 174
cp 0.046
rs 6
c 3
b 1
f 0
wmc 55

25 Methods

Rating   Name   Duplication   Size   Complexity  
A isReviewPostType() 0 3 2
A isReviewEditable() 0 5 3
A normalizeDetailsMetaBox() 0 23 3
A renderReviewNotice() 0 12 3
A removeAutosave() 0 3 1
A buildDetailsMetaBoxRevertButton() 0 25 2
A redirect() 0 11 4
A registerMetaBoxes() 0 8 2
A buildAssignedToTemplate() 0 10 2
A filterEditorTextarea() 0 3 1
A getReviewType() 0 15 4
A removeMetaBoxes() 0 3 1
A filterIsProtectedMeta() 0 10 4
A renderReviewFields() 0 8 3
A saveMetaboxes() 0 6 2
A renderAssignedToMetabox() 0 10 2
A filterEditorSettings() 0 4 1
A revertReview() 0 8 2
A renderReviewEditor() 0 8 3
A renderPinnedInPublishMetaBox() 0 11 2
A removePostTypeSupport() 0 3 1
A filterUpdateMessages() 0 4 1
A renderResponseMetaBox() 0 8 2
A renderDetailsMetaBox() 0 9 2
A renderTaxonomyMetabox() 0 9 2

How to fix   Complexity   

Complex Class

Complex classes like EditorController 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 EditorController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace GeminiLabs\SiteReviews\Controllers;
4
5
use GeminiLabs\SiteReviews\Application;
6
use GeminiLabs\SiteReviews\Controllers\EditorController\Customization;
7
use GeminiLabs\SiteReviews\Controllers\EditorController\Labels;
8
use GeminiLabs\SiteReviews\Controllers\EditorController\Metaboxes;
9
use GeminiLabs\SiteReviews\Controllers\ListTableController\Columns;
10
use GeminiLabs\SiteReviews\Database;
11
use GeminiLabs\SiteReviews\Database\ReviewManager;
12
use GeminiLabs\SiteReviews\Defaults\CreateReviewDefaults;
13
use GeminiLabs\SiteReviews\Helpers\Arr;
14
use GeminiLabs\SiteReviews\Helpers\Str;
15
use GeminiLabs\SiteReviews\Modules\Html\Builder;
16
use GeminiLabs\SiteReviews\Modules\Html\Template;
17
use GeminiLabs\SiteReviews\Modules\Notice;
18
use GeminiLabs\SiteReviews\Review;
19
use WP_Post;
20
21
class EditorController extends Controller
22
{
23
    /**
24
     * @param array $settings
25
     * @return array
26
     * @filter wp_editor_settings
27
     */
28
    public function filterEditorSettings($settings)
29
    {
30
        return glsr(Customization::class)->filterEditorSettings(
31
            Arr::consolidateArray($settings)
32
        );
33
    }
34
35
    /**
36
     * Modify the WP_Editor html to allow autosizing without breaking the `editor-expand` script.
37
     * @param string $html
38
     * @return string
39
     * @filter the_editor
40
     */
41
    public function filterEditorTextarea($html)
42
    {
43
        return glsr(Customization::class)->filterEditorTextarea($html);
44
    }
45
46
    /**
47
     * @param bool $protected
48
     * @param string $metaKey
49
     * @param string $metaType
50
     * @return bool
51
     * @filter is_protected_meta
52
     */
53
    public function filterIsProtectedMeta($protected, $metaKey, $metaType)
54
    {
55
        if ('post' == $metaType && Application::POST_TYPE == get_post_type()) {
56
            $values = glsr(CreateReviewDefaults::class)->unguarded();
57
            $values = Arr::prefixArrayKeys($values);
58
            if (array_key_exists($metaKey, $values)) {
59
                $protected = false;
60
            }
61
        }
62
        return $protected;
63
    }
64
65
    /**
66
     * @param array $messages
67
     * @return array
68
     * @filter post_updated_messages
69
     */
70
    public function filterUpdateMessages($messages)
71
    {
72
        return glsr(Labels::class)->filterUpdateMessages(
73
            Arr::consolidateArray($messages)
74
        );
75
    }
76
77
    /**
78
     * @return void
79
     * @action add_meta_boxes_{Application::POST_TYPE}
80
     */
81
    public function registerMetaBoxes($post)
82
    {
83
        add_meta_box(Application::ID.'_assigned_to', __('Assigned To', 'site-reviews'), [$this, 'renderAssignedToMetabox'], null, 'side');
84
        add_meta_box(Application::ID.'_review', __('Details', 'site-reviews'), [$this, 'renderDetailsMetaBox'], null, 'side');
85
        if ('local' != glsr(Database::class)->get($post->ID, 'review_type')) {
86
            return;
87
        }
88
        add_meta_box(Application::ID.'_response', __('Respond Publicly', 'site-reviews'), [$this, 'renderResponseMetaBox'], null, 'normal');
89
    }
90
91
    /**
92
     * @return void
93
     * @action admin_print_scripts
94
     */
95
    public function removeAutosave()
96
    {
97
        glsr(Customization::class)->removeAutosave();
98
    }
99
100
    /**
101
     * @return void
102
     * @action admin_menu
103
     */
104
    public function removeMetaBoxes()
105
    {
106
        glsr(Customization::class)->removeMetaBoxes();
107
    }
108
109
    /**
110
     * @return void
111
     */
112 1
    public function removePostTypeSupport()
113
    {
114 1
        glsr(Customization::class)->removePostTypeSupport();
115 1
    }
116
117
    /**
118
     * @param WP_Post $post
119
     * @return void
120
     * @callback add_meta_box
121
     */
122
    public function renderAssignedToMetabox($post)
123
    {
124
        if (!$this->isReviewPostType($post)) {
125
            return;
126
        }
127
        $assignedTo = (string) glsr(Database::class)->get($post->ID, 'assigned_to');
128
        wp_nonce_field('assigned_to', '_nonce-assigned-to', false);
129
        glsr()->render('partials/editor/metabox-assigned-to', [
130
            'id' => $assignedTo,
131
            'template' => $this->buildAssignedToTemplate($assignedTo, $post),
132
        ]);
133
    }
134
135
    /**
136
     * @param WP_Post $post
137
     * @return void
138
     * @callback add_meta_box
139
     */
140
    public function renderDetailsMetaBox($post)
141
    {
142
        if (!$this->isReviewPostType($post)) {
143
            return;
144
        }
145
        $review = glsr_get_review($post);
146
        glsr()->render('partials/editor/metabox-details', [
147
            'button' => $this->buildDetailsMetaBoxRevertButton($review, $post),
148
            'metabox' => $this->normalizeDetailsMetaBox($review),
149
        ]);
150
    }
151
152
    /**
153
     * @return void
154
     * @action post_submitbox_misc_actions
155
     */
156
    public function renderPinnedInPublishMetaBox()
157
    {
158
        if (!$this->isReviewPostType(get_post())) {
159
            return;
160
        }
161
        glsr(Template::class)->render('partials/editor/pinned', [
162
            'context' => [
163
                'no' => __('No', 'site-reviews'),
164
                'yes' => __('Yes', 'site-reviews'),
165
            ],
166
            'pinned' => wp_validate_boolean(glsr(Database::class)->get(get_the_ID(), 'pinned')),
167
        ]);
168
    }
169
170
    /**
171
     * @param WP_Post $post
172
     * @return void
173
     * @callback add_meta_box
174
     */
175
    public function renderResponseMetaBox($post)
176
    {
177
        if (!$this->isReviewPostType($post)) {
178
            return;
179
        }
180
        wp_nonce_field('response', '_nonce-response', false);
181
        glsr()->render('partials/editor/metabox-response', [
182
            'response' => glsr(Database::class)->get($post->ID, 'response'),
183
        ]);
184
    }
185
186
    /**
187
     * @param WP_Post $post
188
     * @return void
189
     * @action edit_form_after_title
190
     */
191
    public function renderReviewEditor($post)
192
    {
193
        if (!$this->isReviewPostType($post) || $this->isReviewEditable($post)) {
194
            return;
195
        }
196
        glsr()->render('partials/editor/review', [
197
            'post' => $post,
198
            'response' => glsr(Database::class)->get($post->ID, 'response'),
199
        ]);
200
    }
201
202
    /**
203
     * @return void
204
     * @action admin_head
205
     */
206
    public function renderReviewFields()
207
    {
208
        $screen = glsr_current_screen();
209
        if ('post' != $screen->base || Application::POST_TYPE != $screen->post_type) {
210
            return;
211
        }
212
        add_action('edit_form_after_title', [$this, 'renderReviewEditor']);
213
        add_action('edit_form_top', [$this, 'renderReviewNotice']);
214
    }
215
216
    /**
217
     * @param WP_Post $post
218
     * @return void
219
     * @action edit_form_top
220
     */
221
    public function renderReviewNotice($post)
222
    {
223
        if (!$this->isReviewPostType($post) || $this->isReviewEditable($post)) {
224
            return;
225
        }
226
        glsr(Notice::class)->addWarning(sprintf(
227
            __('%s reviews are read-only.', 'site-reviews'),
228
            glsr(Columns::class)->buildColumnReviewType($post->ID)
229
        ));
230
        glsr(Template::class)->render('partials/editor/notice', [
231
            'context' => [
232
                'notices' => glsr(Notice::class)->get(),
233
            ],
234
        ]);
235
    }
236
237
    /**
238
     * @param WP_Post $post
239
     * @return void
240
     * @see glsr_categories_meta_box()
241
     * @callback register_taxonomy
242
     */
243
    public function renderTaxonomyMetabox($post)
244
    {
245
        if (!$this->isReviewPostType($post)) {
246
            return;
247
        }
248
        glsr()->render('partials/editor/metabox-categories', [
249
            'post' => $post,
250
            'tax_name' => Application::TAXONOMY,
251
            'taxonomy' => get_taxonomy(Application::TAXONOMY),
252
        ]);
253
    }
254
255
    /**
256
     * @return void
257
     * @see $this->filterUpdateMessages()
258
     * @action admin_action_revert
259
     */
260
    public function revertReview()
261
    {
262
        if (Application::ID != filter_input(INPUT_GET, 'plugin')) {
263
            return;
264
        }
265
        check_admin_referer('revert-review_'.($postId = $this->getPostId()));
266
        glsr(ReviewManager::class)->revert($postId);
267
        $this->redirect($postId, 52);
268
    }
269
270
    /**
271
     * @param int $postId
272
     * @param \WP_Post $post
273
     * @param bool $isUpdate
274
     * @return void
275
     * @action save_post_.Application::POST_TYPE
276
     */
277 1
    public function saveMetaboxes($postId, $post, $isUpdating)
278
    {
279 1
        glsr(Metaboxes::class)->saveAssignedToMetabox($postId);
280 1
        glsr(Metaboxes::class)->saveResponseMetabox($postId);
281 1
        if ($isUpdating) {
282
            do_action('site-reviews/review/saved', glsr_get_review($postId));
283
        }
284 1
    }
285
286
    /**
287
     * @param string $assignedTo
288
     * @return string
289
     */
290
    protected function buildAssignedToTemplate($assignedTo, WP_Post $post)
291
    {
292
        $assignedPost = glsr(Database::class)->getAssignedToPost($post->ID, $assignedTo);
293
        if (!($assignedPost instanceof WP_Post)) {
294
            return;
295
        }
296
        return glsr(Template::class)->build('partials/editor/assigned-post', [
297
            'context' => [
298
                'data.url' => (string) get_permalink($assignedPost),
299
                'data.title' => get_the_title($assignedPost),
300
            ],
301
        ]);
302
    }
303
304
    /**
305
     * @return string
306
     */
307
    protected function buildDetailsMetaBoxRevertButton(Review $review, WP_Post $post)
308
    {
309
        $isModified = !Arr::compareArrays(
310
            [$review->title, $review->content, $review->date],
311
            [
312
                glsr(Database::class)->get($post->ID, 'title'),
313
                glsr(Database::class)->get($post->ID, 'content'),
314
                glsr(Database::class)->get($post->ID, 'date'),
315
            ]
316
        );
317
        if ($isModified) {
318
            $revertUrl = wp_nonce_url(
319
                admin_url('post.php?post='.$post->ID.'&action=revert&plugin='.Application::ID),
320
                'revert-review_'.$post->ID
321
            );
322
            return glsr(Builder::class)->a(__('Revert Changes', 'site-reviews'), [
323
                'class' => 'button button-large',
324
                'href' => $revertUrl,
325
                'id' => 'revert',
326
            ]);
327
        }
328
        return glsr(Builder::class)->button(__('Nothing to Revert', 'site-reviews'), [
329
            'class' => 'button-large',
330
            'disabled' => true,
331
            'id' => 'revert',
332
        ]);
333
    }
334
335
    /**
336
     * @param object $review
337
     * @return string|void
338
     */
339
    protected function getReviewType($review)
340
    {
341
        if (count(glsr()->reviewTypes) < 2) {
342
            return;
343
        }
344
        $reviewType = array_key_exists($review->review_type, glsr()->reviewTypes)
345
            ? glsr()->reviewTypes[$review->review_type]
346
            : __('Unknown', 'site-reviews');
347
        if (!empty($review->url)) {
348
            $reviewType = glsr(Builder::class)->a($reviewType, [
349
                'href' => $review->url,
350
                'target' => '_blank',
351
            ]);
352
        }
353
        return $reviewType;
354
    }
355
356
    /**
357
     * @return bool
358
     */
359
    protected function isReviewEditable($post)
360
    {
361
        return $this->isReviewPostType($post)
362
            && post_type_supports(Application::POST_TYPE, 'title')
363
            && 'local' == glsr(Database::class)->get($post->ID, 'review_type');
364
    }
365
366
    /**
367
     * @param mixed $post
368
     * @return bool
369
     */
370
    protected function isReviewPostType($post)
371
    {
372
        return $post instanceof WP_Post && Application::POST_TYPE == $post->post_type;
373
    }
374
375
    /**
376
     * @return array
377
     */
378
    protected function normalizeDetailsMetaBox(Review $review)
379
    {
380
        $user = empty($review->user_id)
381
            ? __('Unregistered user', 'site-reviews')
382
            : glsr(Builder::class)->a(get_the_author_meta('display_name', $review->user_id), [
383
                'href' => get_author_posts_url($review->user_id),
384
            ]);
385
        $email = empty($review->email)
386
            ? '&mdash;'
387
            : glsr(Builder::class)->a($review->email, [
388
                'href' => 'mailto:'.$review->email.'?subject='.esc_attr(__('RE:', 'site-reviews').' '.$review->title),
389
            ]);
390
        $metabox = [
391
            __('Rating', 'site-reviews') => glsr_star_rating($review->rating),
392
            __('Type', 'site-reviews') => $this->getReviewType($review),
393
            __('Date', 'site-reviews') => get_date_from_gmt($review->date, 'F j, Y'),
394
            __('Name', 'site-reviews') => $review->author,
395
            __('Email', 'site-reviews') => $email,
396
            __('User', 'site-reviews') => $user,
397
            __('IP Address', 'site-reviews') => $review->ip_address,
398
            __('Avatar', 'site-reviews') => sprintf('<img src="%s" width="96">', $review->avatar),
399
        ];
400
        return array_filter(apply_filters('site-reviews/metabox/details', $metabox, $review));
401
    }
402
403
    /**
404
     * @param int $postId
405
     * @param int $messageIndex
406
     * @return void
407
     */
408
    protected function redirect($postId, $messageIndex)
409
    {
410
        $referer = wp_get_referer();
411
        $hasReferer = !$referer
412
            || Str::contains($referer, 'post.php')
413
            || Str::contains($referer, 'post-new.php');
414
        $redirectUri = $hasReferer
415
            ? remove_query_arg(['deleted', 'ids', 'trashed', 'untrashed'], $referer)
416
            : get_edit_post_link($postId);
417
        wp_safe_redirect(add_query_arg(['message' => $messageIndex], $redirectUri));
418
        exit;
419
    }
420
}
421