PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.8
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 3.10.4 All 148 releases
visualizer / vendor / codeinwp / themeisle-sdk / src / Modules / Rollback.php

Rollback.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.4.8, at vendor/codeinwp/themeisle-sdk/src/Modules/Rollback.php

377 lines 10.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The rollback class for ThemeIsle SDK.
4 *
5 * @package ThemeIsleSDK
6 * @subpackage Rollback
7 * @copyright Copyright (c) 2017, Marius Cristea
8 * @license http://opensource.org/licenses/gpl-3.0.php GNU Public License
9 * @since 1.0.0
10 */
11
12 namespace ThemeisleSDK\Modules;
13
14 // Exit if accessed directly.
15 use ThemeisleSDK\Common\Abstract_Module;
16 use ThemeisleSDK\Product;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit;
20 }
21
22 /**
23 * Rollback for ThemeIsle SDK.
24 */
25 class Rollback extends Abstract_Module {
26
27 /**
28 * Add js scripts for themes rollback.
29 */
30 public function add_footer() {
31 $screen = get_current_screen();
32 if ( ! isset( $screen->parent_file ) ) {
33 return;
34 }
35 if ( 'themes.php' !== $screen->parent_file ) {
36 return;
37 }
38 if ( ! $this->product->is_theme() ) {
39 return;
40 }
41 $version = $this->get_rollback();
42 if ( empty( $version ) ) {
43 return;
44 }
45 ?>
46 <script type="text/javascript">
47 jQuery(document).ready(function ($) {
48 setInterval(checkTheme, 500);
49
50 function checkTheme() {
51 var theme = '<?php echo esc_attr( $this->product->get_slug() ); ?>-action';
52
53 if (jQuery('#' + theme).length > 0) {
54 if (jQuery('.theme-overlay.active').is(':visible')) {
55 if (jQuery('#' + theme + '-rollback').length === 0) {
56 jQuery('.theme-actions .active-theme').prepend('<a class="button" style="float:left" id="' + theme + '-rollback" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=' . $this->product->get_key() . '_rollback' ), $this->product->get_key() . '_rollback' ) ); ?>">Rollback to v<?php echo esc_attr( $version['version'] ); ?></a>')
57 }
58 }
59
60 }
61 }
62 })
63
64 </script>
65 <?php
66
67 }
68
69 /**
70 * Get the last rollback for this product.
71 *
72 * @return array The rollback version.
73 */
74 public function get_rollback() {
75 $rollback = array();
76 $versions = $this->get_api_versions();
77 $versions = apply_filters( $this->product->get_key() . '_rollbacks', $versions );
78 if ( empty( $versions ) ) {
79 return $rollback;
80 }
81 if ( $versions ) {
82 usort( $versions, array( $this, 'sort_rollback_array' ) );
83 foreach ( $versions as $version ) {
84 if ( isset( $version['version'] ) && isset( $version['url'] ) && version_compare( $this->product->get_version(), $version['version'], '>' ) ) {
85 $rollback = $version;
86 break;
87 }
88 }
89 }
90
91 return $rollback;
92 }
93
94 /**
95 * Get versions array from wp.org
96 *
97 * @return array Array of versions.
98 */
99 private function get_api_versions() {
100
101 $cache_key = $this->product->get_key() . '_' . preg_replace( '/[^0-9a-zA-Z ]/m', '', $this->product->get_version() ) . 'versions';
102 $cache_versions = get_transient( $cache_key );
103 if ( false === $cache_versions ) {
104 $versions = $this->get_remote_versions();
105 set_transient( $cache_key, $versions, 5 * DAY_IN_SECONDS );
106 } else {
107 $versions = is_array( $cache_versions ) ? $cache_versions : array();
108 }
109
110 return $versions;
111 }
112
113 /**
114 * Get remote versions zips.
115 *
116 * @return array Array of available versions.
117 */
118 private function get_remote_versions() {
119 $url = $this->get_versions_api_url();
120 if ( empty( $url ) ) {
121 return [];
122 }
123 $response = wp_remote_get( $url );
124 if ( is_wp_error( $response ) ) {
125 return array();
126 }
127 $response = wp_remote_retrieve_body( $response );
128
129 if ( is_serialized( $response ) ) {
130 $response = maybe_unserialize( $response );
131 } else {
132 $response = json_decode( $response );
133 }
134
135 if ( ! is_object( $response ) ) {
136 return array();
137 }
138 if ( ! isset( $response->versions ) ) {
139 return array();
140 }
141
142 $versions = array();
143 foreach ( $response->versions as $key => $value ) {
144 $versions[] = array(
145 'version' => is_object( $value ) ? $value->version : $key,
146 'url' => is_object( $value ) ? $value->file : $value,
147 );
148 }
149
150 return $versions;
151 }
152
153 /**
154 * Return url where to check for versions.
155 *
156 * @return string Url where to check for versions.
157 */
158 private function get_versions_api_url() {
159 if ( $this->product->is_wordpress_available() && $this->product->is_plugin() ) {
160 return sprintf( 'https://api.wordpress.org/plugins/info/1.0/%s', $this->product->get_slug() );
161 }
162 if ( $this->product->is_wordpress_available() && $this->product->is_theme() ) {
163 return sprintf( 'https://api.wordpress.org/themes/info/1.1/?action=theme_information&request[slug]=%s&request[fields][versions]=true', $this->product->get_slug() );
164 }
165 $license = $this->product->get_license();
166 if ( $this->product->requires_license() && strlen( $license ) < 10 ) {
167 return '';
168 }
169
170 return sprintf( '%slicense/versions/%s/%s/%s/%s', Product::API_URL, rawurlencode( $this->product->get_name() ), $license, urlencode( get_site_url() ), $this->product->get_version() );
171 }
172
173 /**
174 * Show the rollback links in the plugin page.
175 *
176 * @param array $links Plugin links.
177 *
178 * @return array $links Altered links.
179 */
180 public function add_rollback_link( $links ) {
181 $version = $this->get_rollback();
182 if ( empty( $version ) ) {
183 return $links;
184 }
185 $links[] = '<a href="' . wp_nonce_url( admin_url( 'admin-post.php?action=' . $this->product->get_key() . '_rollback' ), $this->product->get_key() . '_rollback' ) . '">' . sprintf( apply_filters( $this->product->get_key() . '_rollback_label', 'Rollback to v%s' ), $version['version'] ) . '</a>';
186
187 return $links;
188 }
189
190 /**
191 * Start the rollback operation.
192 */
193 public function start_rollback() {
194 if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], $this->product->get_key() . '_rollback' ) ) {
195 wp_nonce_ays( '' );
196 }
197
198 if ( $this->product->is_plugin() ) {
199 $this->start_rollback_plugin();
200
201 return;
202 }
203 if ( $this->product->is_theme() ) {
204 $this->start_rollback_theme();
205
206 return;
207 }
208 }
209
210 /**
211 * Start the rollback operation for the plugin.
212 */
213 private function start_rollback_plugin() {
214 $rollback = $this->get_rollback();
215 $plugin_transient = get_site_transient( 'update_plugins' );
216 $plugin_folder = $this->product->get_slug();
217 $plugin_file = $this->product->get_file();
218 $version = $rollback['version'];
219 $temp_array = array(
220 'slug' => $plugin_folder,
221 'new_version' => $version,
222 'package' => $rollback['url'],
223 );
224
225 $temp_object = (object) $temp_array;
226 $plugin_transient->response[ $plugin_folder . '/' . $plugin_file ] = $temp_object;
227 set_site_transient( 'update_plugins', $plugin_transient );
228
229 $transient = get_transient( $this->product->get_key() . '_warning_rollback' );
230
231 if ( false === $transient ) {
232 set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
233 require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
234 $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
235 $plugin = $plugin_folder . '/' . $plugin_file;
236 $nonce = 'upgrade-plugin_' . $plugin;
237 $url = 'update.php?action=upgrade-plugin&plugin=' . urlencode( $plugin );
238 $upgrader_skin = new \Plugin_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'plugin' ) );
239 $upgrader = new \Plugin_Upgrader( $upgrader_skin );
240 $upgrader->upgrade( $plugin );
241 delete_transient( $this->product->get_key() . '_warning_rollback' );
242 wp_die(
243 '',
244 $title,
245 array(
246 'response' => 200,
247 )
248 );
249 }
250 }
251
252 /**
253 * Start the rollback operation for the theme.
254 */
255 private function start_rollback_theme() {
256 add_filter( 'update_theme_complete_actions', array( $this, 'alter_links_theme_upgrade' ) );
257 $rollback = $this->get_rollback();
258 $transient = get_site_transient( 'update_themes' );
259 $folder = $this->product->get_slug();
260 $version = $rollback['version'];
261 $temp_array = array(
262 'new_version' => $version,
263 'package' => $rollback['url'],
264 );
265
266 $transient->response[ $folder . '/style.css' ] = $temp_array;
267 set_site_transient( 'update_themes', $transient );
268
269 $transient = get_transient( $this->product->get_key() . '_warning_rollback' );
270
271 if ( false === $transient ) {
272 set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
273 require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
274 $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
275 $theme = $folder . '/style.css';
276 $nonce = 'upgrade-theme_' . $theme;
277 $url = 'update.php?action=upgrade-theme&theme=' . urlencode( $theme );
278
279 $upgrader = new \Theme_Upgrader( new \Theme_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'theme' ) ) );
280 $upgrader->upgrade( $theme );
281 delete_transient( $this->product->get_key() . '_warning_rollback' );
282 wp_die(
283 '',
284 $title,
285 array(
286 'response' => 200,
287 )
288 );
289 }
290 }
291
292 /**
293 * Alter links and remove duplicate customize message.
294 *
295 * @param array $links Array of old links.
296 *
297 * @return mixed Array of links.
298 */
299 public function alter_links_theme_upgrade( $links ) {
300 if ( isset( $links['preview'] ) ) {
301 $links['preview'] = str_replace( '<span aria-hidden="true">Customize</span>', '', $links['preview'] );
302 }
303
304 return $links;
305 }
306
307 /**
308 * Loads product object.
309 *
310 * @param Product $product Product object.
311 *
312 * @return bool Should we load the module?
313 */
314 public function can_load( $product ) {
315 if ( $this->is_from_partner( $product ) ) {
316 return false;
317 }
318 if ( $product->is_theme() && ! current_user_can( 'switch_themes' ) ) {
319 return false;
320 }
321
322 if ( $product->is_plugin() && ! current_user_can( 'install_plugins' ) ) {
323 return false;
324 }
325
326 return true;
327 }
328
329 /**
330 * Sort the rollbacks array in descending order.
331 *
332 * @param mixed $a First version to compare.
333 * @param mixed $b Second version to compare.
334 *
335 * @return bool Which version is greater?
336 */
337 public function sort_rollback_array( $a, $b ) {
338 return version_compare( $a['version'], $b['version'], '<' ) > 0;
339 }
340
341 /**
342 * Load module logic.
343 *
344 * @param Product $product Product object.
345 *
346 * @return $this Module object.
347 */
348 public function load( $product ) {
349 $this->product = $product;
350 $this->show_link();
351 $this->add_hooks();
352
353 return $this;
354 }
355
356 /**
357 * If product can be rolled back, show the link to rollback.
358 */
359 private function show_link() {
360 add_filter(
361 'plugin_action_links_' . plugin_basename( $this->product->get_basefile() ),
362 array(
363 $this,
364 'add_rollback_link',
365 )
366 );
367 }
368
369 /**
370 * Set the rollback hook. Strangely, this does not work if placed in the ThemeIsle_SDK_Rollback class, so it is being called from there instead.
371 */
372 public function add_hooks() {
373 add_action( 'admin_post_' . $this->product->get_key() . '_rollback', array( $this, 'start_rollback' ) );
374 add_action( 'admin_footer', array( $this, 'add_footer' ) );
375 }
376 }
377