Passed
Push — main ( 20ef5f...b4b594 )
by Paul
06:10
created

Application::hasPermission()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
cc 3
nc 4
nop 2
crap 12
1
<?php
2
3
namespace GeminiLabs\SiteReviews;
4
5
use GeminiLabs\SiteReviews\Addons\Updater;
6
use GeminiLabs\SiteReviews\Database\DefaultsManager;
7
use GeminiLabs\SiteReviews\Database\OptionManager;
8
use GeminiLabs\SiteReviews\Defaults\PermissionDefaults;
9
use GeminiLabs\SiteReviews\Helpers\Arr;
10
use GeminiLabs\SiteReviews\Modules\Migrate;
11
12
/**
13
 * @property array $addons
14
 * @property string $capability
15
 * @property string $cron_event
16
 * @property array $db_version
17
 * @property array $defaults
18
 * @property string $export_key
19
 * @property string $file
20
 * @property string $id
21
 * @property string $languages
22
 * @property string $name
23
 * @property string $paged_handle
24
 * @property string $paged_query_var
25
 * @property string $post_type
26
 * @property string $prefix
27
 * @property array $session
28
 * @property \GeminiLabs\SiteReviews\Arguments $storage
29
 * @property string $taxonomy
30
 * @property array $updated
31
 * @property string $version
32
 * @property string $testedTo;
33
 */
34
final class Application extends Container
35
{
36
    use Plugin;
37
    use Session;
38
    use Storage;
39
40
    public const DB_VERSION = '1.2';
41
    public const EXPORT_KEY = '_glsr_export';
42
    public const ID = 'site-reviews';
43
    public const PAGED_HANDLE = 'pagination_request';
44
    public const PAGED_QUERY_VAR = 'reviews-page'; // filtered
45
    public const POST_TYPE = 'site-review';
46
    public const PREFIX = 'glsr_';
47
    public const TAXONOMY = 'site-review-category';
48
49
    /**
50
     * @var array
51
     */
52
    protected $addons = [];
53
54
    /**
55
     * @var array
56
     */
57
    protected $defaults;
58
59
    /**
60
     * @var string
61
     */
62
    protected $name;
63
64
    /**
65
     * @var array
66
     */
67
    protected $settings;
68
69
    /**
70
     * @var array
71
     */
72
    protected $updated = [];
73
74
    /**
75
     * @param string $addonId
76
     * @return false|\GeminiLabs\SiteReviews\Addons\Addon
77
     */
78 23
    public function addon($addonId)
79
    {
80 23
        return $this->addons[$addonId] ?? false;
81
    }
82
83
    /**
84
     * @param string $capability
85
     * @param mixed ...$args
86
     * @return bool
87
     */
88 2
    public function can($capability, ...$args)
89
    {
90 2
        return $this->make(Role::class)->can($capability, ...$args);
91
    }
92
93
    /**
94
     * @param bool $networkDeactivating
95
     * @return void
96
     * @callback register_deactivation_hook
97
     */
98
    public function deactivate($networkDeactivating)
99
    {
100
        $this->make(Install::class)->deactivate($networkDeactivating);
101
    }
102
103
    /**
104
     * @param string $page
105
     * @param string $tab
106
     * @return string
107
     */
108
    public function getPermission($page = '', $tab = 'index')
109
    {
110
        $fallback = 'edit_posts';
111
        $permissions = $this->make(PermissionDefaults::class)->defaults();
112
        $permission = Arr::get($permissions, $page, $fallback);
113
        if (is_array($permission)) {
114
            $permission = Arr::get($permission, $tab, $fallback);
115
        }
116
        $capability = empty($permission) || !is_string($permission)
117
            ? $fallback
118
            : $permission;
119
        return $this->make(Role::class)->capability($capability);
120
    }
121
122
    /**
123
     * @param string $page
124
     * @param string $tab
125
     * @return bool
126
     */
127
    public function hasPermission($page = '', $tab = 'index')
128
    {
129
        $isAdminScreen = is_admin() || is_network_admin();
130
        return !$isAdminScreen || $this->can($this->getPermission($page, $tab));
131
    }
132
133
    /**
134
     * @return void
135
     */
136
    public function init()
137
    {
138
        // Ensure the custom database tables exist, this is needed in cases
139
        // where the plugin has been updated instead of activated.
140
        if (empty(get_option(static::PREFIX.'db_version'))) {
141
            $this->make(Install::class)->run();
142
        }
143
        // If this is a new major version, copy over the previous version settings
144
        if (empty(get_option(OptionManager::databaseKey()))) {
145
            if ($settings = $this->make(OptionManager::class)->previous()) {
146
                update_option(OptionManager::databaseKey(), $settings);
147
            }
148
        }
149
        // Force an immediate plugin migration on database version upgrades
150
        if (static::DB_VERSION !== get_option(static::PREFIX.'db_version')) {
151
            $migrate = $this->make(Migrate::class);
152
            add_action('plugins_loaded', [$migrate, 'run'], 1); // use plugins_loaded!
153
        }
154
        $this->make(Hooks::class)->run();
155
    }
156
157
    /**
158
     * The setting defaults (these are not the saved settings!).
159
     * @return void
160
     */
161
    public function initDefaults()
162
    {
163
        if (empty($this->defaults)) {
164
            $defaults = $this->make(DefaultsManager::class)->get();
165
            $this->defaults = $this->filterArray('get/defaults', $defaults);
166
        }
167
    }
168
169
    /**
170
     * @return bool
171
     */
172 29
    public function isAdmin()
173
    {
174 29
        $isAdminScreen = is_admin() || is_network_admin();
175 29
        return $isAdminScreen && !wp_doing_ajax();
176
    }
177
178
    /**
179
     * @param object|string $addon
180
     * @return void
181
     */
182
    public function license($addon)
183
    {
184
        try {
185
            $settings = $this->settings(); // populate the initial settings
186
            $reflection = new \ReflectionClass($addon);
187
            $id = $reflection->getConstant('ID');
188
            $licensed = $reflection->getConstant('LICENSED');
189
            $name = $reflection->getConstant('NAME');
190
            if (true !== $licensed || 2 !== count(array_filter([$id, $name]))) {
191
                return;
192
            }
193
            $license = [
194
                'settings.licenses.'.$id => [
195
                    'class' => 'glsr-license-key regular-text',
196
                    'default' => '',
197
                    'label' => $name,
198
                    'sanitizer' => 'text',
199
                    'tooltip' => sprintf(_x('Enter the license key here. Your license can be found on the %s page of your Nifty Plugins account.', 'License Keys (admin-text)', 'site-reviews'),
200
                        sprintf('<a href="https://niftyplugins.com/account/license-keys/" target="_blank">%s</a>', _x('License Keys', 'admin-text', 'site-reviews'))
201
                    ),
202
                    'type' => 'text',
203
                ],
204
            ];
205
            $this->settings = array_merge($license, $settings);
206
        } catch (\ReflectionException $e) {
207
            // Fail silently
208
        }
209
    }
210
211
    /**
212
     * @param string|object $addon
213
     * @return void
214
     */
215
    public function register($addon)
216
    {
217
        $retired = [ // @compat these addons have been retired
218
            'site-reviews-gamipress',
219
            'site-reviews-woocommerce',
220
        ];
221
        $premium = glsr()->filterArray('site-reviews-premium', []);
222
        try {
223
            $reflection = new \ReflectionClass($addon); // make sure that the class exists
224
            $addon = $reflection->getName();
225
            if (in_array($addon::ID, $retired)) {
226
                $this->append('retired', $addon);
227
            } elseif (in_array($addon::ID, $premium)
228
                && !str_starts_with($reflection->getNamespaceName(), 'GeminiLabs\SiteReviewsPremium')) {
229
                $this->append('site-reviews-premium', $addon);
230
            } else {
231
                $this->addons[$addon::ID] = $addon;
232
                $this->singleton($addon); // this goes first!
233
                $this->alias($addon::ID, $this->make($addon)); // @todo for some reason we have to link an alias to an instantiated class
234
                $instance = $this->make($addon)->init();
235
                $this->append('addons', $instance->version, $instance->id);
236
            }
237
        } catch (\ReflectionException $e) {
238
            glsr_log()->error('Attempted to register an invalid addon.');
239
        }
240
    }
241
242
    /**
243
     * The settings config (these are not the saved settings!).
244
     * @return array
245
     */
246 25
    public function settings()
247
    {
248 25
        if (empty($this->settings)) {
249
            $settings = $this->config('settings');
250
            $settings = $this->filterArray('addon/settings', $settings);
251
            array_walk($settings, function (&$setting) {
252
                $setting = wp_parse_args($setting, [
253
                    'default' => '',
254
                    'sanitizer' => '',
255
                ]);
256
            });
257
            $this->settings = $settings;
258
        }
259 25
        return $this->settings;
260
    }
261
262
    /**
263
     * @param object|string $addon
264
     * @param string $file
265
     * @return void
266
     */
267
    public function update($addon, $file)
268
    {
269
        if (!current_user_can('manage_options') && !(defined('DOING_CRON') && DOING_CRON)) {
270
            return;
271
        }
272
        if (!file_exists($file)) {
273
            glsr_log()->error("Add-on does not exist: $file")->debug($addon);
274
        }
275
        try {
276
            $reflection = new \ReflectionClass($addon);
277
            $addonId = $reflection->getConstant('ID');
278
            $licensed = $reflection->getConstant('LICENSED');
279
            $updateUrl = $reflection->getConstant('UPDATE_URL');
280
            if ($addonId && $updateUrl && !array_key_exists($addonId, $this->updated)) {
281
                $this->license($addon);
282
                $license = glsr_get_option('licenses.'.$addonId);
283
                $updater = new Updater($updateUrl, $file, $addonId, compact('license'));
284
                $updater->init();
285
                $this->updated[$addonId] = compact('file', 'licensed', 'updateUrl'); // store details for license verification in settings
286
            }
287
        } catch (\ReflectionException $e) {
288
            // We don't need to log an error here.
289
        }
290
    }
291
}
292