PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.4.9
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.4.9
4.0.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 All 149 releases
visualizer / vendor / codeinwp / themeisle-sdk / src / Modules / Rollback.php

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

383 lines 10.9 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 // Style fix for the api link that gets outside the content.
232 echo '<style>body#error-page{word-break:break-word;}</style>';
233
234 if ( false === $transient ) {
235 set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
236 require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
237 $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
238 $plugin = $plugin_folder . '/' . $plugin_file;
239 $nonce = 'upgrade-plugin_' . $plugin;
240 $url = 'update.php?action=upgrade-plugin&plugin=' . urlencode( $plugin );
241 $upgrader_skin = new \Plugin_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'plugin' ) );
242 $upgrader = new \Plugin_Upgrader( $upgrader_skin );
243 $upgrader->upgrade( $plugin );
244 delete_transient( $this->product->get_key() . '_warning_rollback' );
245 wp_die(
246 '',
247 $title,
248 array(
249 'response' => 200,
250 )
251 );
252 }
253 }
254
255 /**
256 * Start the rollback operation for the theme.
257 */
258 private function start_rollback_theme() {
259 add_filter( 'update_theme_complete_actions', array( $this, 'alter_links_theme_upgrade' ) );
260 $rollback = $this->get_rollback();
261 $transient = get_site_transient( 'update_themes' );
262 $folder = $this->product->get_slug();
263 $version = $rollback['version'];
264 $temp_array = array(
265 'new_version' => $version,
266 'package' => $rollback['url'],
267 );
268
269 $transient->response[ $folder . '/style.css' ] = $temp_array;
270 set_site_transient( 'update_themes', $transient );
271
272 $transient = get_transient( $this->product->get_key() . '_warning_rollback' );
273
274 // Style fix for the api link that gets outside the content.
275 echo '<style>body#error-page{word-break:break-word;}</style>';
276
277 if ( false === $transient ) {
278 set_transient( $this->product->get_key() . '_warning_rollback', 'in progress', 30 );
279 require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
280 $title = sprintf( apply_filters( $this->product->get_key() . '_rollback_message', 'Rolling back %s to v%s' ), $this->product->get_name(), $version );
281 $theme = $folder . '/style.css';
282 $nonce = 'upgrade-theme_' . $theme;
283 $url = 'update.php?action=upgrade-theme&theme=' . urlencode( $theme );
284
285 $upgrader = new \Theme_Upgrader( new \Theme_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'theme' ) ) );
286 $upgrader->upgrade( $theme );
287 delete_transient( $this->product->get_key() . '_warning_rollback' );
288 wp_die(
289 '',
290 $title,
291 array(
292 'response' => 200,
293 )
294 );
295 }
296 }
297
298 /**
299 * Alter links and remove duplicate customize message.
300 *
301 * @param array $links Array of old links.
302 *
303 * @return mixed Array of links.
304 */
305 public function alter_links_theme_upgrade( $links ) {
306 if ( isset( $links['preview'] ) ) {
307 $links['preview'] = str_replace( '<span aria-hidden="true">Customize</span>', '', $links['preview'] );
308 }
309
310 return $links;
311 }
312
313 /**
314 * Loads product object.
315 *
316 * @param Product $product Product object.
317 *
318 * @return bool Should we load the module?
319 */
320 public function can_load( $product ) {
321 if ( $this->is_from_partner( $product ) ) {
322 return false;
323 }
324 if ( $product->is_theme() && ! current_user_can( 'switch_themes' ) ) {
325 return false;
326 }
327
328 if ( $product->is_plugin() && ! current_user_can( 'install_plugins' ) ) {
329 return false;
330 }
331
332 return true;
333 }
334
335 /**
336 * Sort the rollbacks array in descending order.
337 *
338 * @param mixed $a First version to compare.
339 * @param mixed $b Second version to compare.
340 *
341 * @return bool Which version is greater?
342 */
343 public function sort_rollback_array( $a, $b ) {
344 return version_compare( $a['version'], $b['version'], '<' ) > 0;
345 }
346
347 /**
348 * Load module logic.
349 *
350 * @param Product $product Product object.
351 *
352 * @return $this Module object.
353 */
354 public function load( $product ) {
355 $this->product = $product;
356 $this->show_link();
357 $this->add_hooks();
358
359 return $this;
360 }
361
362 /**
363 * If product can be rolled back, show the link to rollback.
364 */
365 private function show_link() {
366 add_filter(
367 'plugin_action_links_' . plugin_basename( $this->product->get_basefile() ),
368 array(
369 $this,
370 'add_rollback_link',
371 )
372 );
373 }
374
375 /**
376 * 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.
377 */
378 public function add_hooks() {
379 add_action( 'admin_post_' . $this->product->get_key() . '_rollback', array( $this, 'start_rollback' ) );
380 add_action( 'admin_footer', array( $this, 'add_footer' ) );
381 }
382 }
383