PluginProbe
UpdraftPlus: WP Backup & Migration Plugin / 1.16.5
UpdraftPlus: WP Backup & Migration Plugin v1.16.5
1.26.7 1.26.6 1.26.5 1.26.4 1.26.3 1.9.19 1.9.25 1.9.26 1.9.30 1.9.31 1.9.32 1.9.4 1.9.40 1.9.41 1.9.42 1.9.43 1.9.44 1.9.45 1.9.46 1.9.5 1.9.50 1.9.51 1.9.60 1.9.62 1.9.63 All 371 releases
updraftplus / central / modules / theme.php

theme.php in UpdraftPlus: WP Backup & Migration Plugin 1.16.5, at central/modules/theme.php

547 lines 17.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
5 /**
6 * Handles UpdraftCentral Theme Commands which basically handles
7 * the installation and activation of a theme
8 */
9 class UpdraftCentral_Theme_Commands extends UpdraftCentral_Commands {
10
11 private $switched = false;
12
13 /**
14 * Function that gets called before every action
15 *
16 * @param string $command a string that corresponds to UDC command to call a certain method for this class.
17 * @param array $data an array of data post or get fields
18 * @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
19 *
20 * link to udrpc_action main function in class UpdraftPlus_UpdraftCentral_Listener
21 */
22 public function _pre_action($command, $data, $extra_info) {// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
23 // Here we assign the current blog_id to a variable $blog_id
24 $blog_id = get_current_blog_id();
25 if (!empty($data['site_id'])) $blog_id = $data['site_id'];
26
27 if (function_exists('switch_to_blog') && is_multisite() && $blog_id) {
28 $this->switched = switch_to_blog($blog_id);
29 }
30 }
31
32 /**
33 * Function that gets called after every action
34 *
35 * @param string $command a string that corresponds to UDC command to call a certain method for this class.
36 * @param array $data an array of data post or get fields
37 * @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
38 *
39 * link to udrpc_action main function in class UpdraftPlus_UpdraftCentral_Listener
40 */
41 public function _post_action($command, $data, $extra_info) {// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
42 // Here, we're restoring to the current (default) blog before we switched
43 if ($this->switched) restore_current_blog();
44 }
45
46 /**
47 * Constructor
48 */
49 public function __construct() {
50 $this->_admin_include('theme.php', 'file.php', 'template.php', 'class-wp-upgrader.php', 'theme-install.php', 'update.php');
51 }
52
53 /**
54 * Checks whether the theme is currently installed and activated.
55 *
56 * @param array $query Parameter array containing the name of the theme to check
57 * @return array Contains the result of the current process
58 */
59 public function is_theme_installed($query) {
60
61 if (!isset($query['theme']))
62 return $this->_generic_error_response('theme_name_required');
63
64
65 $result = $this->_get_theme_info($query['theme']);
66 return $this->_response($result);
67 }
68
69 /**
70 * Applies currently requested action for theme processing
71 *
72 * @param string $action The action to apply (e.g. activate or install)
73 * @param array $query Parameter array containing information for the currently requested action
74 *
75 * @return array
76 */
77 private function _apply_theme_action($action, $query) {
78
79 $result = array();
80 switch ($action) {
81 case 'activate':
82 $info = $this->_get_theme_info($query['theme']);
83 if ($info['installed']) {
84 switch_theme($info['slug']);
85 if (wp_get_theme()->get_stylesheet() === $info['slug']) {
86 $result = array('activated' => true);
87 } else {
88 $result = $this->_generic_error_response('theme_not_activated', array($query['theme']));
89 }
90 } else {
91 $result = $this->_generic_error_response('theme_not_installed', array($query['theme']));
92 }
93 break;
94 case 'network_enable':
95 $info = $this->_get_theme_info($query['theme']);
96 if ($info['installed']) {
97 // Make sure that network_enable_theme is present and callable since
98 // it is only available at 4.6. If not, we'll do things the old fashion way
99 if (is_callable(array('WP_Theme', 'network_enable_theme'))) {
100 WP_Theme::network_enable_theme($info['slug']);
101 } else {
102 $allowed_themes = get_site_option('allowedthemes');
103 $allowed_themes[$info['slug']] = true;
104
105 update_site_option('allowedthemes', $allowed_themes);
106 }
107
108 $allowed = WP_Theme::get_allowed_on_network();
109 if (is_array($allowed) && !empty($allowed[$info['slug']])) {
110 $result = array('enabled' => true);
111 } else {
112 $result = $this->_generic_error_response('theme_not_enabled', array($query['theme']));
113 }
114 } else {
115 $result = $this->_generic_error_response('theme_not_installed', array($query['theme']));
116 }
117 break;
118 case 'network_disable':
119 $info = $this->_get_theme_info($query['theme']);
120 if ($info['installed']) {
121 // Make sure that network_disable_theme is present and callable since
122 // it is only available at 4.6. If not, we'll do things the old fashion way
123 if (is_callable(array('WP_Theme', 'network_disable_theme'))) {
124 WP_Theme::network_disable_theme($info['slug']);
125 } else {
126 $allowed_themes = get_site_option('allowedthemes');
127 if (isset($allowed_themes[$info['slug']])) {
128 unset($allowed_themes[$info['slug']]);
129 }
130
131 update_site_option('allowedthemes', $allowed_themes);
132 }
133
134 $allowed = WP_Theme::get_allowed_on_network();
135 if (is_array($allowed) && empty($allowed[$info['slug']])) {
136 $result = array('disabled' => true);
137 } else {
138 $result = $this->_generic_error_response('theme_not_disabled', array($query['theme']));
139 }
140 } else {
141 $result = $this->_generic_error_response('theme_not_installed', array($query['theme']));
142 }
143 break;
144 case 'install':
145 $api = themes_api('theme_information', array(
146 'slug' => $query['slug'],
147 'fields' => array(
148 'description' => true,
149 'sections' => false,
150 'rating' => true,
151 'ratings' => true,
152 'downloaded' => true,
153 'downloadlink' => true,
154 'last_updated' => true,
155 'screenshot_url' => true,
156 'parent' => true,
157 )
158 ));
159
160 if (is_wp_error($api)) {
161 $result = $this->_generic_error_response('generic_response_error', array($api->get_error_message()));
162 } else {
163 $info = $this->_get_theme_info($query['theme']);
164 $installed = $info['installed'];
165
166 if (!$installed) {
167 // WP < 3.7
168 if (!class_exists('Automatic_Upgrader_Skin')) include_once(UPDRAFTPLUS_DIR.'/central/classes/class-automatic-upgrader-skin.php');
169
170 $skin = new Automatic_Upgrader_Skin();
171 $upgrader = new Theme_Upgrader($skin);
172
173 $download_link = $api->download_link;
174 $installed = $upgrader->install($download_link);
175 }
176
177 if (!$installed) {
178 $result = $this->_generic_error_response('theme_install_failed', array($query['theme']));
179 } else {
180 $result = array('installed' => true);
181 }
182 }
183 break;
184 }
185
186 return $result;
187 }
188
189 /**
190 * Preloads the submitted credentials to the global $_POST variable
191 *
192 * @param array $query Parameter array containing information for the currently requested action
193 */
194 private function _preload_credentials($query) {
195 if (!empty($query) && isset($query['filesystem_credentials'])) {
196 parse_str($query['filesystem_credentials'], $filesystem_credentials);
197 if (is_array($filesystem_credentials)) {
198 foreach ($filesystem_credentials as $key => $value) {
199 // Put them into $_POST, which is where request_filesystem_credentials() checks for them.
200 $_POST[$key] = $value;
201 }
202 }
203 }
204 }
205
206 /**
207 * Checks whether we have the required fields submitted and the user has
208 * the capabilities to execute the requested action
209 *
210 * @param array $query The submitted information
211 * @param array $fields The required fields to check
212 * @param array $capabilities The capabilities to check and validate
213 *
214 * @return array|string
215 */
216 private function _validate_fields_and_capabilities($query, $fields, $capabilities) {
217
218 $error = '';
219 if (!empty($fields)) {
220 for ($i=0; $i<count($fields); $i++) {
221 $field = $fields[$i];
222
223 if (!isset($query[$field])) {
224 if ('keyword' === $field) {
225 $error = $this->_generic_error_response('keyword_required');
226 } else {
227 $error = $this->_generic_error_response('theme_'.$query[$field].'_required');
228 }
229 break;
230 }
231 }
232 }
233
234 if (empty($error) && !empty($capabilities)) {
235 for ($i=0; $i<count($capabilities); $i++) {
236 if (!current_user_can($capabilities[$i])) {
237 $error = $this->_generic_error_response('theme_insufficient_permission');
238 break;
239 }
240 }
241 }
242
243 return $error;
244 }
245
246 /**
247 * Activates the theme
248 *
249 * @param array $query Parameter array containing the name of the theme to activate
250 * @return array Contains the result of the current process
251 */
252 public function activate_theme($query) {
253
254 $error = $this->_validate_fields_and_capabilities($query, array('theme'), array('switch_themes'));
255 if (!empty($error)) {
256 return $error;
257 }
258
259 $result = $this->_apply_theme_action('activate', $query);
260 if (empty($result['activated'])) {
261 return $result;
262 }
263
264 return $this->_response($result);
265 }
266
267 /**
268 * Enables theme for network
269 *
270 * @param array $query Parameter array containing the name of the theme to activate
271 * @return array Contains the result of the current process
272 */
273 public function network_enable_theme($query) {
274
275 $error = $this->_validate_fields_and_capabilities($query, array('theme'), array('switch_themes'));
276 if (!empty($error)) {
277 return $error;
278 }
279
280 $result = $this->_apply_theme_action('network_enable', $query);
281 if (empty($result['enabled'])) {
282 return $result;
283 }
284
285 return $this->_response($result);
286 }
287
288 /**
289 * Disables theme from network
290 *
291 * @param array $query Parameter array containing the name of the theme to activate
292 * @return array Contains the result of the current process
293 */
294 public function network_disable_theme($query) {
295
296 $error = $this->_validate_fields_and_capabilities($query, array('theme'), array('switch_themes'));
297 if (!empty($error)) {
298 return $error;
299 }
300
301 $result = $this->_apply_theme_action('network_disable', $query);
302 if (empty($result['disabled'])) {
303 return $result;
304 }
305
306 return $this->_response($result);
307 }
308
309 /**
310 * Download, install and activates the theme
311 *
312 * @param array $query Parameter array containing the filesystem credentials entered by the user along with the theme name and slug
313 * @return array Contains the result of the current process
314 */
315 public function install_activate_theme($query) {
316
317 $error = $this->_validate_fields_and_capabilities($query, array('theme', 'slug'), array('install_themes', 'switch_themes'));
318 if (!empty($error)) {
319 return $error;
320 }
321
322 $this->_preload_credentials($query);
323
324 $result = $this->_apply_theme_action('install', $query);
325 if (!empty($result['installed']) && $result['installed']) {
326 $result = $this->_apply_theme_action('activate', $query);
327 if (empty($result['activated'])) {
328 return $result;
329 }
330 } else {
331 return $result;
332 }
333
334 return $this->_response($result);
335 }
336
337 /**
338 * Download, install the theme
339 *
340 * @param array $query Parameter array containing the filesystem credentials entered by the user along with the theme name and slug
341 * @return array Contains the result of the current process
342 */
343 public function install_theme($query) {
344
345 $error = $this->_validate_fields_and_capabilities($query, array('theme', 'slug'), array('install_themes'));
346 if (!empty($error)) {
347 return $error;
348 }
349
350 $this->_preload_credentials($query);
351
352 $result = $this->_apply_theme_action('install', $query);
353 if (empty($result['installed'])) {
354 return $result;
355 }
356
357 return $this->_response($result);
358 }
359
360 /**
361 * Uninstall/delete the theme
362 *
363 * @param array $query Parameter array containing the filesystem credentials entered by the user along with the theme name and slug
364 * @return array Contains the result of the current process
365 */
366 public function delete_theme($query) {
367
368 $error = $this->_validate_fields_and_capabilities($query, array('theme'), array('delete_themes'));
369 if (!empty($error)) {
370 return $error;
371 }
372
373 $this->_preload_credentials($query);
374 $info = $this->_get_theme_info($query['theme']);
375
376 if ($info['installed']) {
377 $deleted = delete_theme($info['slug']);
378
379 if ($deleted) {
380 $result = array('deleted' => true);
381 } else {
382 $result = $this->_generic_error_response('delete_theme_failed', array($query['theme']));
383 }
384 } else {
385 $result = $this->_generic_error_response('theme_not_installed', array($query['theme']));
386 }
387
388 return $this->_response($result);
389 }
390
391 /**
392 * Updates/upgrade the theme
393 *
394 * @param array $query Parameter array containing the filesystem credentials entered by the user along with the theme name and slug
395 * @return array Contains the result of the current process
396 */
397 public function update_theme($query) {
398
399 $error = $this->_validate_fields_and_capabilities($query, array('theme'), array('update_themes'));
400 if (!empty($error)) {
401 return $error;
402 }
403
404 $this->_preload_credentials($query);
405 $info = $this->_get_theme_info($query['theme']);
406
407 // Make sure that we still have the theme installed before running
408 // the update process
409 if ($info['installed']) {
410 // Load the updates command class if not existed
411 if (!class_exists('UpdraftCentral_Updates_Commands')) include_once('updates.php');
412 $update_command = new UpdraftCentral_Updates_Commands($this->rc);
413
414 $result = $update_command->update_theme($info['slug']);
415 if (!empty($result['error'])) {
416 $result['values'] = array($query['theme']);
417 }
418 } else {
419 return $this->_generic_error_response('theme_not_installed', array($query['theme']));
420 }
421
422 return $this->_response($result);
423 }
424
425 /**
426 * Gets the theme information along with its active and install status
427 *
428 * @internal
429 * @param array $theme The name of the theme to pull the information from
430 * @return array Contains the theme information
431 */
432 private function _get_theme_info($theme) {
433
434 $info = array(
435 'active' => false,
436 'installed' => false
437 );
438
439 // Clear theme cache so that newly installed/downloaded themes
440 // gets reflected when calling "get_themes"
441 wp_clean_themes_cache();
442
443 // Gets all themes available.
444 $themes = wp_get_themes();
445
446 // Loops around each theme available.
447 foreach ($themes as $key => $value) {
448 // If the theme name matches that of the specified name, it will gather details.
449 if ($value->Name === $theme) {
450 $info['installed'] = true;
451 $info['active'] = (wp_get_theme()->get('Name') === $value->Name) ? true : false;
452 $info['slug'] = $value->get_stylesheet();
453 $info['data'] = $value;
454 break;
455 }
456 }
457
458 return $info;
459 }
460
461 /**
462 * Loads all available themes with additional attributes and settings needed by UpdraftCentral
463 *
464 * @param array $query Parameter array Any available parameters needed for this action
465 * @return array Contains the result of the current process
466 */
467 public function load_themes($query) {
468
469 $error = $this->_validate_fields_and_capabilities($query, array(), array('install_themes', 'switch_themes'));
470 if (!empty($error)) {
471 return $error;
472 }
473
474 $website = get_bloginfo('name');
475 $results = array();
476
477 // Load the updates command class if not existed
478 if (!class_exists('UpdraftCentral_Updates_Commands')) include_once('updates.php');
479 $updates = new UpdraftCentral_Updates_Commands($this->rc);
480
481 // Get themes for update
482 $theme_updates = (array) $updates->get_item_updates('themes');
483
484 // Get all themes
485 $themes = wp_get_themes();
486
487 foreach ($themes as $slug => $value) {
488 $theme = new stdClass();
489 $theme->name = $value->Name;
490 $theme->description = $value->Description;
491 $theme->slug = $slug;
492 $theme->version = $value->Version;
493 $theme->author = $value->Author;
494 $theme->status = (wp_get_theme()->get('Name') === $value->Name) ? 'active' : 'inactive';
495 $theme->child_theme = ($slug !== $value->Template) ? true : false;
496 $theme->website = $website;
497 $theme->multisite = is_multisite();
498
499 if ($theme->child_theme) {
500 $theme->parent = wp_get_theme($value->Template)->get('Name');
501 }
502
503 if (!empty($theme_updates[$slug])) {
504 $update_info = $theme_updates[$slug];
505
506 if (version_compare($theme->version, $update_info->update['new_version'], '<')) {
507 if (!empty($update_info->update['new_version'])) $theme->latest_version = $update_info->update['new_version'];
508 if (!empty($update_info->update['package'])) $theme->download_link = $update_info->update['package'];
509 }
510 }
511
512 if (empty($theme->short_description) && !empty($theme->description)) {
513 // Only pull the first sentence as short description, it should be enough rather than displaying
514 // an empty description or a full blown one which the user can access anytime if they press on
515 // the view details link in UpdraftCentral.
516 $temp = explode('.', $theme->description);
517 $short_description = $temp[0];
518
519 // Adding the second sentence wouldn't hurt, in case the first sentence is too short.
520 if (isset($temp[1])) $short_description .= '.'.$temp[1];
521
522 $theme->short_description = $short_description.'.';
523 }
524
525 $results[] = $theme;
526 }
527
528 $result = array(
529 'themes' => $results,
530 'theme_updates' => $theme_updates,
531 );
532
533 $result = array_merge($result, $this->_get_backup_credentials_settings(get_theme_root()));
534 return $this->_response($result);
535 }
536
537 /**
538 * Gets the backup and security credentials settings for this website
539 *
540 * @param array $query Parameter array Any available parameters needed for this action
541 * @return array Contains the result of the current process
542 */
543 public function get_theme_requirements() {
544 return $this->_response($this->_get_backup_credentials_settings(get_theme_root()));
545 }
546 }
547