Test Failed
Push — develop ( bec489...ad6b70 )
by Paul
08:56
created

MenuController::processPageActions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Controllers;
4
5
use GeminiLabs\SiteReviews\Api;
6
use GeminiLabs\SiteReviews\Database\Cache;
7
use GeminiLabs\SiteReviews\Database\Tables;
8
use GeminiLabs\SiteReviews\Defaults\AddonDefaults;
9
use GeminiLabs\SiteReviews\Defaults\FeatureDefaults;
10
use GeminiLabs\SiteReviews\Helper;
11
use GeminiLabs\SiteReviews\Helpers\Arr;
12
use GeminiLabs\SiteReviews\Helpers\Str;
13
use GeminiLabs\SiteReviews\License;
14
use GeminiLabs\SiteReviews\Modules\Console;
15
use GeminiLabs\SiteReviews\Modules\Html\Builder;
16
use GeminiLabs\SiteReviews\Modules\Html\SettingForm;
17
use GeminiLabs\SiteReviews\Modules\Notice;
18
use GeminiLabs\SiteReviews\Overrides\ScheduledActionsTable;
19
20
class MenuController extends AbstractController
21
{
22
    /**
23
     * This is necessary because the ActionScheduler table is rendered late
24
     * after request headers have already be set which breaks redirects.
25
     *
26
     * @action load-site-review_page_glsr-tools
27
     */
28
    public function processPageActions(): void
29
    {
30
        glsr(ScheduledActionsTable::class)->process_actions();
31
    }
32
33
    /**
34
     * @action admin_menu
35
     */
36
    public function registerMenuCount(): void
37
    {
38
        global $menu, $typenow;
39
        foreach ($menu as $key => $value) {
40
            if (!isset($value[2]) || $value[2] != 'edit.php?post_type='.glsr()->post_type) {
41
                continue;
42
            }
43
            $postCount = wp_count_posts(glsr()->post_type);
44
            $pendingCount = glsr(Builder::class)->span(number_format_i18n($postCount->pending), [
45
                'class' => 'unapproved-count',
46
            ]);
47
            $awaitingModeration = glsr(Builder::class)->span($pendingCount, [
48
                'class' => "awaiting-mod count-{$postCount->pending}",
49
            ]);
50
            $menu[$key][0] .= " {$awaitingModeration}";
51
            if (glsr()->post_type === $typenow) {
52
                $menu[$key][4] .= ' current';
53
            }
54
            break;
55
        }
56
    }
57
58
    /**
59
     * @action admin_menu
60
     */
61
    public function registerSubMenus(): void
62
    {
63
        $pages = $this->parseWithFilter('submenu/pages', [
64
            'settings' => _x('Settings', 'admin-text', 'site-reviews'),
65
            'tools' => _x('Tools', 'admin-text', 'site-reviews'),
66
            'documentation' => _x('Help & Support', 'admin-text', 'site-reviews'),
67
            'premium' => _x('Upgrade to Premium', 'admin-text', 'site-reviews'),
68
        ]);
69
        foreach ($pages as $slug => $title) {
70
            $method = Helper::buildMethodName('render', $slug, 'menu', 'callback');
71
            if (!method_exists($this, $method)) {
72
                continue;
73
            }
74 8
            $callback = glsr()->filter('addon/submenu/callback', [$this, $method], $slug);
75
            if (!is_callable($callback)) {
76 8
                continue;
77
            }
78
            add_submenu_page('edit.php?post_type='.glsr()->post_type, $title, $title, glsr()->getPermission($slug), Str::dashCase(glsr()->prefix).$slug, $callback);
79 8
        }
80 8
    }
81 8
82 8
    /**
83
     * We don't use admin_menu because it breaks the privilege check which runs
84
     * after the admin_menu hook is triggered in wp-admin/includes/menu.php.
85
     *
86
     * @action admin_init
87
     */
88
    public function removeSubMenu(): void
89
    {
90
        if (!function_exists('remove_submenu_page')) {
91
            require_once ABSPATH.'wp-admin/includes/plugin.php';
92
        }
93
        remove_submenu_page(
94
            'edit.php?post_type='.glsr()->post_type,
95
            'post-new.php?post_type='.glsr()->post_type
96
        );
97
    }
98
99
    /**
100
     * @see registerSubMenus
101
     */
102
    public function renderDocumentationMenuCallback(): void
103
    {
104
        $tabs = $this->parseWithFilter('documentation/tabs', [
105
            'support' => _x('Support', 'admin-text', 'site-reviews'),
106
            'faq' => _x('FAQ', 'admin-text', 'site-reviews'),
107
            'shortcodes' => _x('Shortcodes', 'admin-text', 'site-reviews'),
108
            'hooks' => _x('Hooks', 'admin-text', 'site-reviews'),
109
            'functions' => _x('Functions', 'admin-text', 'site-reviews'),
110
            'api' => _x('API', 'admin-text', 'site-reviews'),
111
            'addons' => _x('Addons', 'admin-text', 'site-reviews'),
112
        ]);
113
        $addons = glsr()->filterArray('addon/documentation', []);
114
        uksort($addons, fn ($a, $b) => strnatcasecmp(glsr($a)->name, glsr($b)->name));
115
        if (empty($addons)) {
116
            unset($tabs['addons']);
117
        }
118
        $this->renderPage('documentation', [
119
            'addons' => $addons,
120
            'tabs' => $tabs,
121
        ]);
122
    }
123
124
    /**
125
     * @see registerSubMenus
126
     */
127
    public function renderPremiumMenuCallback(): void
128
    {
129
        $addons = [];
130
        $features = [];
131
        $isPremium = glsr(License::class)->isPremium();
132
        if ($isPremium) {
133
            $data = glsr(Api::class)->get('addons')->data();
134
            foreach ($data as $values) {
135
                $context = glsr(AddonDefaults::class)->restrict($values);
136
                $addons[] = array_merge($context, compact('context'));
137
            }
138
        } else {
139
            $data = glsr(Api::class)->get('features')->data();
140
            foreach ($data as $values) {
141
                $features[] = glsr(FeatureDefaults::class)->restrict($values);
142
            }
143
            array_multisort(
144
                array_column($features, 'premium'), SORT_DESC,
0 ignored issues
show
Bug introduced by
GeminiLabs\SiteReviews\Controllers\SORT_DESC cannot be passed to array_multisort() as the parameter $rest expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

144
                array_column($features, 'premium'), /** @scrutinizer ignore-type */ SORT_DESC,
Loading history...
Bug introduced by
array_column($features, 'premium') cannot be passed to array_multisort() as the parameter $array expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

144
                /** @scrutinizer ignore-type */ array_column($features, 'premium'), SORT_DESC,
Loading history...
145
                array_column($features, 'feature'), SORT_ASC | SORT_NATURAL,
0 ignored issues
show
Bug introduced by
array_column($features, 'feature') cannot be passed to array_multisort() as the parameter $rest expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

145
                /** @scrutinizer ignore-type */ array_column($features, 'feature'), SORT_ASC | SORT_NATURAL,
Loading history...
Bug introduced by
GeminiLabs\SiteReviews\C...ontrollers\SORT_NATURAL cannot be passed to array_multisort() as the parameter $rest expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

145
                array_column($features, 'feature'), /** @scrutinizer ignore-type */ SORT_ASC | SORT_NATURAL,
Loading history...
146
                $features
147
            );
148
        }
149
        $this->renderPage('premium', [
150
            'addons' => $addons,
151
            'features' => $features,
152
            'is_premium' => $isPremium,
153
        ]);
154
    }
155
156
    /**
157
     * @see registerSubMenus
158
     */
159
    public function renderSettingsMenuCallback(): void
160
    {
161
        $tabs = $this->parseWithFilter('settings/tabs', [ // order is intentional
162
            'general' => _x('General', 'admin-text', 'site-reviews'),
163
            'reviews' => _x('Reviews', 'admin-text', 'site-reviews'),
164
            'forms' => _x('Forms', 'admin-text', 'site-reviews'),
165
            'schema' => _x('Schema', 'admin-text', 'site-reviews'),
166
            'strings' => _x('Strings', 'admin-text', 'site-reviews'),
167
            'integrations' => _x('Integrations', 'admin-text', 'site-reviews'),
168
            'addons' => _x('Addons', 'admin-text', 'site-reviews'),
169
            'licenses' => _x('Licenses', 'admin-text', 'site-reviews'),
170
        ]);
171
        if (empty(Arr::get(glsr()->defaults(), 'settings.addons'))) {
172
            unset($tabs['addons']);
173
        }
174
        if (empty(Arr::get(glsr()->defaults(), 'settings.licenses'))) {
175
            unset($tabs['licenses']);
176
        }
177
        $this->renderPage('settings', [
178
            'fields' => glsr(SettingForm::class, ['groups' => $tabs])->build(),
179
            'tabs' => $tabs,
180
        ]);
181
    }
182
183
    /**
184
     * @see registerSubMenus
185
     */
186
    public function renderToolsMenuCallback(): void
187 8
    {
188
        $tabs = $this->parseWithFilter('tools/tabs', [
189 8
            'general' => _x('General', 'admin-text', 'site-reviews'),
190 8
            'scheduled' => _x('Scheduled Actions', 'admin-text', 'site-reviews'),
191
            'sync' => _x('Sync Reviews', 'admin-text', 'site-reviews'),
192
            'console' => _x('Console', 'admin-text', 'site-reviews'),
193
            'system-info' => _x('System Info', 'admin-text', 'site-reviews'),
194
        ]);
195
        if (!glsr()->filterBool('addon/sync/enable', false)) {
196
            unset($tabs['sync']);
197
        }
198
        $this->renderPage('tools', [
199
            'data' => [
200
                'console_level' => glsr(Console::class)->getLevel(),
201
                'context' => [
202
                    'base_url' => glsr_admin_url(),
203
                    'console' => glsr(Console::class)->get(),
204
                    'id' => glsr()->id,
205
                ],
206
                'myisam_tables' => Arr::get(glsr(Tables::class)->tableEngines(), 'MyISAM', []),
207
                'rollback_script' => file_get_contents(glsr()->path('assets/scripts/rollback.js')),
208
                'rollback_versions' => glsr(Cache::class)->getPluginVersions(),
209
                'services' => glsr()->filterArray('addon/sync/services', []),
210
            ],
211
            'tabs' => $tabs,
212
        ]);
213
    }
214
215
    /**
216
     * @action admin_init
217
     */
218
    public function setCustomPermissions(): void
219
    {
220
        foreach (wp_roles()->roles as $role => $value) {
221
            wp_roles()->remove_cap($role, 'create_'.glsr()->post_type);
222
        }
223
    }
224
225
    protected function getNotices(): string
226
    {
227
        return glsr(Builder::class)->div(glsr(Notice::class)->get(), [
228
            'id' => 'glsr-notices',
229
        ]);
230
    }
231
232
    protected function parseWithFilter(string $hookSuffix, array $args = []): array
233
    {
234
        if (str_ends_with($hookSuffix, '/tabs')) {
235
            $page = str_replace('/tabs', '', $hookSuffix);
236
            foreach ($args as $tab => $title) {
237
                if (!glsr()->hasPermission($page, $tab)) {
238
                    unset($args[$tab]);
239
                }
240
            }
241
        } elseif (array_key_exists('premium', $args) && glsr(License::class)->isPremium()) {
242
            $args['premium'] = _x('Premium Addons', 'admin-text', 'site-reviews');
243
        }
244
        return glsr()->filterArray("addon/{$hookSuffix}", $args);
245
    }
246
247
    protected function renderPage(string $page, array $data = []): void
248
    {
249
        $data['http_referer'] = (string) wp_get_referer();
250
        $data['notices'] = $this->getNotices();
251
        glsr()->render("pages/{$page}/index", $data);
252
    }
253
}
254