PluginProbe
Boxzilla – WordPress Popup Builder / 3.4.4
Boxzilla – WordPress Popup Builder v3.4.4
3.4.11 3.4.10 3.4.9 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 trunk 3.0 3.0.1 3.0.2 3.0.3 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 All 72 releases
boxzilla / src / licensing / class-update-manager.php

class-update-manager.php in Boxzilla – WordPress Popup Builder 3.4.4, at src/licensing/class-update-manager.php

271 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Boxzilla\Licensing;
4
5 use Boxzilla\Plugin;
6
7 class UpdateManager
8 {
9 /**
10 * @var array
11 */
12 protected $extensions = [];
13
14 /**
15 * @var API
16 */
17 protected $api;
18
19 /**
20 * @var License
21 */
22 protected $license;
23
24 /**
25 * @var
26 */
27 protected $available_updates;
28
29 /**
30 * @param array $extensions
31 * @param API $api
32 * @param License $license
33 */
34 public function __construct(array $extensions, API $api, License $license)
35 {
36 $this->extensions = $extensions;
37 $this->license = $license;
38 $this->api = $api;
39 }
40
41 /**
42 * Add hooks
43 */
44 public function init()
45 {
46 add_filter('pre_set_site_transient_update_plugins', [ $this, 'add_updates' ]);
47 add_filter('plugins_api', [ $this, 'get_plugin_info' ], 20, 3);
48 add_filter('http_request_args', [ $this, 'add_auth_headers' ], 10, 2);
49 }
50
51 /**
52 * This adds the license key header to download package requests.
53 *
54 * @param array $args
55 * @param string $url
56 *
57 * @return mixed
58 */
59 public function add_auth_headers($args, $url)
60 {
61 // only act on download request's to the Boxzilla update API
62 if (strpos($url, $this->api->url) !== 0 || strpos($url, '/download') === false) {
63 return $args;
64 }
65
66 // only add if activation key not empty
67 if (empty($this->license->activation_key)) {
68 return $args;
69 }
70
71 if (! isset($args['headers'])) {
72 $args['headers'] = [];
73 }
74
75 $args['headers']['Authorization'] = "Bearer {$this->license->activation_key}";
76 return $args;
77 }
78
79 private function get_plugin_by_slug($slug)
80 {
81 foreach ($this->extensions as $p) {
82 // find plugin by slug
83 if (dirname($p->slug()) === $slug) {
84 return $p;
85 }
86 }
87
88 return null;
89 }
90
91 /**
92 * @param $result
93 * @param string $action
94 * @param null $args
95 *
96 * @return object
97 */
98 public function get_plugin_info($result, $action = '', $args = null)
99 {
100 // do nothing for unrelated requests
101 if ($action !== 'plugin_information' || ! isset($args->slug)) {
102 return $result;
103 }
104
105 // only act on our plugins
106 if (strpos($args->slug, 'boxzilla-') !== 0) {
107 return $result;
108 }
109
110 return $this->get_update_info($args->slug);
111 }
112
113 /**
114 * @param object $updates
115 * @return object
116 */
117 public function add_updates($updates)
118 {
119
120 // do nothing if no plugins registered
121 if (empty($this->extensions)) {
122 return $updates;
123 }
124
125 // failsafe WP bug
126 if (empty($updates) || ! isset($updates->response) || ! is_array($updates->response)) {
127 return $updates;
128 }
129
130 // fetch available updates
131 $available_updates = $this->fetch_updates();
132
133 // merge with other updates
134 $updates->response = array_merge($updates->response, $available_updates);
135
136 return $updates;
137 }
138
139 /**
140 * Fetch array of available updates from remote server
141 *
142 * @return array
143 */
144 protected function fetch_updates()
145 {
146 if (is_array($this->available_updates)) {
147 return $this->available_updates;
148 }
149
150 // don't try if we failed a request recently.
151 $failed_at = get_transient('boxzilla_request_failed');
152 if (! empty($failed_at) && ( ( strtotime('now') - 300 ) < $failed_at )) {
153 return [];
154 }
155
156 // fetch remote info
157 try {
158 $remote_plugins = $this->api->get_plugins();
159 } catch (API_Exception $e) {
160 // set flag for 5 minutes
161 set_transient('boxzilla_request_failed', strtotime('now'), 300);
162 return [];
163 }
164
165 // filter remote plugins, we only want the ones with an update available
166 $this->available_updates = $this->filter_remote_plugins($remote_plugins);
167
168 return $this->available_updates;
169 }
170
171 /**
172 * @param $remote_plugins
173 * @return array
174 */
175 protected function filter_remote_plugins($remote_plugins)
176 {
177 $available_updates = [];
178
179 // find new versions
180 foreach ($remote_plugins as $remote_plugin) {
181 // sanity check
182 if (! isset($remote_plugin->new_version)) {
183 continue;
184 }
185
186 // if plugin is activated, we can access it here
187 if (isset($this->extensions[ $remote_plugin->sid ])) {
188
189 /** @var Plugin $local_plugin */
190 $local_plugin = $this->extensions[ $remote_plugin->sid ];
191
192 // plugin found and local plugin version not same as remote version?
193 if (! $local_plugin || version_compare($local_plugin->version(), $remote_plugin->new_version, '>=')) {
194 continue;
195 }
196
197 // add some dynamic data
198 $available_updates[ $local_plugin->slug() ] = $this->format_response($local_plugin->slug(), $remote_plugin);
199 } else {
200 // if plugin is not active, use get_plugin_data for fetching version
201 $plugin_file = WP_PLUGIN_DIR . "/{$remote_plugin->slug}/{$remote_plugin->slug}.php";
202 if (! file_exists($plugin_file)) {
203 continue;
204 }
205
206 $plugin_data = get_plugin_data($plugin_file);
207
208 if (! $plugin_data || version_compare($plugin_data['Version'], $remote_plugin->new_version, '>=')) {
209 continue;
210 }
211
212 // add some dynamic data
213 $slug = plugin_basename($plugin_file);
214 $available_updates[ $slug ] = $this->format_response($slug, $remote_plugin);
215 }
216 }
217
218 return $available_updates;
219 }
220
221 /**
222 * @param string $slug
223 *
224 * @return null
225 */
226 public function get_update_info($slug)
227 {
228 $available_updates = $this->fetch_updates();
229
230 foreach ($available_updates as $plugin_file => $update_info) {
231 if ($slug === $update_info->slug) {
232 return $update_info;
233 }
234 }
235
236 return null;
237 }
238
239 /**
240 * @param $slug
241 * @param $response
242 *
243 * @return mixed
244 */
245 protected function format_response($slug, $response)
246 {
247 $response->slug = dirname($slug);
248 $response->plugin = $slug;
249
250 // add some notices if license is inactive
251 if (! $this->license->activated) {
252 $response->upgrade_notice = sprintf('You will need to <a href="%s">activate your license</a> to install this plugin update.', admin_url('edit.php?post_type=boxzilla-box&page=boxzilla-settings'));
253 $response->sections->changelog = '<p>' . sprintf('You will need to <a href="%s" target="_top">activate your license</a> to install this plugin update.', admin_url('edit.php?post_type=boxzilla-box&page=boxzilla-settings')) . '</p>' . $response->sections->changelog;
254 $response->package = null;
255 }
256
257 // cast subkey objects to array as that is what WP expects
258 $response->sections = get_object_vars($response->sections);
259 $response->banners = get_object_vars($response->banners);
260 $response->contributors = get_object_vars($response->contributors);
261 $response->contributors = array_map(
262 function ($v) {
263 return get_object_vars($v);
264 },
265 $response->contributors
266 );
267
268 return $response;
269 }
270 }
271