Passed
Push — master ( 6b35fa...ccb079 )
by Paul
10:24 queued 05:13
created

Updater   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 262
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 4
Bugs 2 Features 2
Metric Value
eloc 96
c 4
b 2
f 2
dl 0
loc 262
ccs 0
cts 160
cp 0
rs 9.52
wmc 36

18 Methods

Rating   Name   Duplication   Size   Complexity  
A normalizeResponse() 0 11 3
A modifyPluginUpdates() 0 17 2
A setCachedVersion() 0 4 2
A isLicenseValid() 0 4 1
A getCachedVersion() 0 3 1
A filterPluginUpdates() 0 6 2
A request() 0 16 1
A filterPluginUpdateDetails() 0 10 4
A getVersion() 0 3 1
A onForceUpdateCheck() 0 10 4
A __construct() 0 9 2
A checkLicense() 0 7 2
A getPluginUpdate() 0 12 4
A deactivateLicense() 0 3 1
A modifyUpdateDetails() 0 9 1
A renderLicenseMissingLink() 0 4 2
A activateLicense() 0 3 1
A init() 0 9 2
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use GeminiLabs\SiteReviews\Application;
6
use GeminiLabs\SiteReviews\Helper;
7
use GeminiLabs\SiteReviews\Helpers\Arr;
8
9
class Updater
10
{
11
    /**
12
     * @var string
13
     */
14
    protected $apiUrl;
15
    /**
16
     * @var array
17
     */
18
    protected $data;
19
    /**
20
     * @var string
21
     */
22
    protected $plugin;
23
    /**
24
     * @var string
25
     */
26
    protected $transientName;
27
28
    /**
29
     * @param string $apiUrl
30
     * @param string $file
31
     */
32
    public function __construct($apiUrl, $file, array $data = [])
33
    {
34
        if (!function_exists('get_plugin_data')) {
35
            require_once ABSPATH.WPINC.'/plugin.php';
36
        }
37
        $this->apiUrl = trailingslashit(apply_filters('site-reviews/addon/api-url', $apiUrl));
38
        $this->data = wp_parse_args($data, get_plugin_data($file));
39
        $this->plugin = plugin_basename($file);
40
        $this->transientName = Application::PREFIX.md5(Arr::get($data, 'TextDomain'));
41
    }
42
43
    /**
44
     * @return object
45
     */
46
    public function activateLicense(array $data = [])
47
    {
48
        return $this->request('activate_license', $data);
49
    }
50
51
    /**
52
     * @return object
53
     */
54
    public function checkLicense(array $data = [])
55
    {
56
        $response = $this->request('check_license', $data);
57
        if ('valid' === Arr::get($response, 'license')) {
58
            $this->getPluginUpdate(true);
59
        }
60
        return $response;
61
    }
62
63
    /**
64
     * @return object
65
     */
66
    public function deactivateLicense(array $data = [])
67
    {
68
        return $this->request('deactivate_license', $data);
69
    }
70
71
    /**
72
     * @param false|object|array $result
73
     * @param string $action
74
     * @param object $args
75
     * @return mixed
76
     */
77
    public function filterPluginUpdateDetails($result, $action, $args)
78
    {
79
        if ('plugin_information' != $action
80
            || Arr::get($this->data, 'TextDomain') != Arr::get($args, 'slug')) {
81
            return $result;
82
        }
83
        if ($updateInfo = $this->getPluginUpdate()) {
84
            return $this->modifyUpdateDetails($updateInfo);
85
        }
86
        return $result;
87
    }
88
89
    /**
90
     * @param object $transient
91
     * @return object
92
     */
93
    public function filterPluginUpdates($transient)
94
    {
95
        if ($updateInfo = $this->getPluginUpdate()) {
96
            return $this->modifyPluginUpdates($transient, $updateInfo);
97
        }
98
        return $transient;
99
    }
100
101
    /**
102
     * @return object
103
     */
104
    public function getVersion(array $data = [])
105
    {
106
        return $this->request('get_version', $data);
107
    }
108
109
    /**
110
     * @return void
111
     */
112
    public function init()
113
    {
114
        if ($this->apiUrl === trailingslashit(home_url())) {
115
            return;
116
        }
117
        add_filter('plugins_api',                             [$this, 'filterPluginUpdateDetails'], 10, 3);
118
        add_filter('pre_set_site_transient_update_plugins',   [$this, 'filterPluginUpdates'], 999);
119
        add_action('load-update-core.php',                    [$this, 'onForceUpdateCheck'], 9);
120
        add_action('in_plugin_update_message-'.$this->plugin, [$this, 'renderLicenseMissingLink']);
121
    }
122
123
    /**
124
     * @return bool
125
     */
126
    public function isLicenseValid()
127
    {
128
        $result = $this->checkLicense();
129
        return 'valid' === Arr::get($result, 'license');
130
    }
131
132
    /**
133
     * @return void
134
     */
135
    public function onForceUpdateCheck()
136
    {
137
        if (!filter_input(INPUT_GET, 'force-check')) {
138
            return;
139
        }
140
        foreach (glsr()->addons as $addon) {
141
            try {
142
                glsr($addon)->updater->getPluginUpdate(true);
143
            } catch (\Exception $e) {
144
                glsr_log()->error($e->getMessage());
145
            }
146
        }
147
    }
148
149
    /**
150
     * @return void
151
     */
152
    public function renderLicenseMissingLink()
153
    {
154
        if (!$this->isLicenseValid()) {
155
            glsr()->render('partials/addons/license-missing');
156
        }
157
    }
158
159
    /**
160
     * @return false|object
161
     */
162
    protected function getCachedVersion()
163
    {
164
        return get_transient($this->transientName);
165
    }
166
167
    /**
168
     * @param bool $force
169
     * @return false|object
170
     */
171
    protected function getPluginUpdate($force = false)
172
    {
173
        $version = $this->getCachedVersion();
174
        if (false === $version || $force) {
175
            $version = $this->getVersion();
176
            $this->setCachedVersion($version);
177
        }
178
        if (isset($version->error)) {
179
            glsr_log()->error($version->error);
180
            return false;
181
        }
182
        return $version;
183
    }
184
185
    /**
186
     * @param object $transient
187
     * @param object $updateInfo
188
     * @return object
189
     */
190
    protected function modifyPluginUpdates($transient, $updateInfo)
191
    {
192
        $updateInfo->id = Application::ID.'/'.Arr::get($this->data, 'TextDomain');
193
        $updateInfo->plugin = $this->plugin;
194
        $updateInfo->requires_php = Arr::get($this->data, 'RequiresPHP');
195
        $updateInfo->tested = Arr::get($this->data, 'testedTo');
196
        $transient->checked[$this->plugin] = Arr::get($this->data, 'Version');
197
        $transient->last_checked = time();
198
        if (Helper::isGreaterThan($updateInfo->new_version, Arr::get($this->data, 'Version'))) {
199
            unset($transient->no_update[$this->plugin]);
200
            $updateInfo->update = true;
201
            $transient->response[$this->plugin] = $updateInfo;
202
        } else {
203
            unset($transient->response[$this->plugin]);
204
            $transient->no_update[$this->plugin] = $updateInfo;
205
        }
206
        return $transient;
207
    }
208
209
    /**
210
     * @param object $updateInfo
211
     * @return object
212
     */
213
    protected function modifyUpdateDetails($updateInfo)
214
    {
215
        $updateInfo->author = Arr::get($this->data, 'Author');
216
        $updateInfo->author_profile = Arr::get($this->data, 'AuthorURI');
217
        $updateInfo->requires = Arr::get($this->data, 'RequiresWP');
218
        $updateInfo->requires_php = Arr::get($this->data, 'RequiresPHP');
219
        $updateInfo->tested = Arr::get($this->data, 'testedTo');
220
        $updateInfo->version = $updateInfo->new_version;
221
        return $updateInfo;
222
    }
223
224
    /**
225
     * @param \WP_Error|array $response
226
     * @return object
227
     */
228
    protected function normalizeResponse($response)
229
    {
230
        $body = wp_remote_retrieve_body($response);
231
        if ($data = json_decode($body)) {
232
            $data = array_map('maybe_unserialize', (array) $data);
233
            return (object) $data;
234
        }
235
        $error = is_wp_error($response)
236
            ? $response->get_error_message()
237
            : 'Update server not responding ('.Arr::get($this->data, 'TextDomain').')';
238
        return (object) ['error' => $error];
239
    }
240
241
    /**
242
     * @param string $action activate_license|check_license|deactivate_license|get_version
243
     * @return object
244
     */
245
    protected function request($action, array $data = [])
246
    {
247
        $data = wp_parse_args($data, $this->data);
248
        $response = wp_remote_post($this->apiUrl, [
249
            'body' => [
250
                'edd_action' => $action,
251
                'item_id' => Arr::get($data, 'item_id'),
252
                'item_name' => Arr::get($data, 'Name'),
253
                'license' => Arr::get($data, 'license'),
254
                'slug' => Arr::get($data, 'TextDomain'),
255
                'url' => home_url(),
256
            ],
257
            'sslverify' => apply_filters('site-reviews/sslverify/post', false),
258
            'timeout' => 15,
259
        ]);
260
        return $this->normalizeResponse($response);
261
    }
262
263
    /**
264
     * @param object $version
265
     * @return void
266
     */
267
    protected function setCachedVersion($version)
268
    {
269
        if (!isset($version->error)) {
270
            set_transient($this->transientName, $version, 3 * HOUR_IN_SECONDS);
271
        }
272
    }
273
}
274