| @@ -6,9 +6,8 @@ | ||
| 6 | 6 | */ |
| 7 | 7 | defined( 'PLUGIN_REVISIONS_PLUGIN_DIR' ) || exit; // Exit if not accessed from Plugversions. |
| 8 | 8 | |
| 9 | 9 | if( wp_doing_ajax() ){ |
| 10 | - //* Include the Ajax admin file. | |
| 11 | 10 | require_once PLUGIN_REVISIONS_PLUGIN_DIR . '/admin/pr-ajax-admin.php'; |
| 12 | 11 | } |
| 13 | 12 | |
| 14 | 13 | register_activation_hook( __FILE__, function() { |
| @@ -21,8 +20,94 @@ | ||
| 21 | 20 | update_site_option( 'plugin_revisions',array( 'time' => time() ) ); |
| 22 | 21 | } |
| 23 | 22 | } ); |
| 24 | 23 | |
| 24 | +add_filter( 'upgrader_package_options',function( $options ) { | |
| 25 | + /** | |
| 26 | + * Update revisions after plugin update | |
| 27 | + * | |
| 28 | + * @since 0.0.1 | |
| 29 | + */ | |
| 30 | + if( isset( $options['destination'] ) && isset( $options['hook_extra'] ) ){ | |
| 31 | + $hook_extra = $options['hook_extra']; | |
| 32 | + if( isset( $hook_extra['plugin'] ) ){ | |
| 33 | + $plugin = $hook_extra['plugin']; | |
| 34 | + $plugin_name = dirname( $plugin ); | |
| 35 | + $path = sanitize_option( 'upload_path',$options['destination'].'/'.$plugin ); | |
| 36 | + if( file_exists( $path ) ){ | |
| 37 | + $plugin_data = get_plugin_data( $path ); | |
| 38 | + $version = $plugin_data['Version']; | |
| 39 | + if( !class_exists( 'WP_Upgrader' ) ){ | |
| 40 | + if( file_exists( ABSPATH.'wp-admin/includes/class-wp-upgrader.php' ) ){ | |
| 41 | + require_once ABSPATH.'/wp-admin/includes/class-wp-upgrader.php'; | |
| 42 | + } | |
| 43 | + } | |
| 44 | + if( class_exists( 'WP_Upgrader' ) ){ | |
| 45 | + $upgrader = new WP_Upgrader(); | |
| 46 | + $key = eos_plugin_revision_key(); | |
| 47 | + if( $key ){ | |
| 48 | + $destination = str_replace( dirname( $plugin ),'pr-'.$key.'-'.sanitize_option( 'upload_path',$version ).'-ver-'.dirname( $plugin ),sanitize_option( 'upload_path',plugin_dir_path( $path )) ); | |
| 49 | + if( !is_dir( $destination ) ){ | |
| 50 | + global $wp_filesystem; | |
| 51 | + if( empty( $wp_filesystem ) ){ | |
| 52 | + require_once ( ABSPATH .'/wp-admin/includes/file.php' ); | |
| 53 | + WP_Filesystem(); | |
| 54 | + } | |
| 55 | + $wp_filesystem->mkdir( $destination ); | |
| 56 | + } | |
| 57 | + if( !empty( $wp_filesystem ) && $wp_filesystem->is_dir( $destination ) ){ | |
| 58 | + $result = copy_dir( plugin_dir_path( $path ),$destination ); | |
| 59 | + eos_plugin_revisions_remove_versions( apply_filters( 'max_plugin_revisions',4 ),$plugin_name ); | |
| 60 | + } | |
| 61 | + } | |
| 62 | + } | |
| 63 | + } | |
| 64 | + } | |
| 65 | + } | |
| 66 | + return $options; | |
| 67 | +},10,4 ); | |
| 68 | + | |
| 69 | +add_filter( 'all_plugins',function( $plugins ){ | |
| 70 | + /** | |
| 71 | + * Remove plugin revisions from plugins table in the page wp-admin/plugins.php | |
| 72 | + * | |
| 73 | + * @since 0.0.1 | |
| 74 | + */ | |
| 75 | + $key = eos_plugin_revision_key(); | |
| 76 | + if( $key ){ | |
| 77 | + foreach( $plugins as $plugin => $arr ){ | |
| 78 | + if( false !== strpos( $plugin,'pr-'.$key.'-' ) ){ | |
| 79 | + unset( $plugins[$plugin] ); | |
| 80 | + $parent_plugin = str_replace( 'pr-'.$key.'-','',$plugin ); | |
| 81 | + $parent_pluginArr = explode( '-ver-',$parent_plugin ); | |
| 82 | + $parent_plugin = isset( $parent_pluginArr[1] ) ? $parent_pluginArr[1] : $parent_plugin; | |
| 83 | + add_filter( 'plugin_action_links_'.$parent_plugin,function( $actions, $plugin_file, $plugin_data, $context ){ | |
| 84 | + if( !current_user_can( 'activate_plugin' ) ) return $actions; | |
| 85 | + $key = eos_plugin_revision_key(); | |
| 86 | + $all_dirs = scandir( dirname( PLUGIN_REVISIONS_PLUGIN_DIR ) ); | |
| 87 | + if( $all_dirs && !empty( $all_dirs ) ){ | |
| 88 | + $new_action_links = ''; | |
| 89 | + $plugin = dirname( $plugin_file ); | |
| 90 | + foreach( $all_dirs as $dir ){ | |
| 91 | + if( false !== strpos( $dir,'pr-'.$key.'-' ) && substr( $dir,-strlen( $plugin ),strlen( $plugin ) ) === $plugin ){ | |
| 92 | + $ver = str_replace( 'pr-'.$key.'-','',$dir ); | |
| 93 | + $verArr = explode( '-ver-',$ver ); | |
| 94 | + $ver = $verArr[0]; | |
| 95 | + $new_action_links .= '<a class="plugin-revision-action" href="#" data-parent_plugin="'.esc_attr( $plugin_file ).'" data-dir="'.esc_attr( $dir ).'">'.sprintf( esc_html__( 'Replace with version: %s','plugversions' ),$ver ).'</a> '; | |
| 96 | + } | |
| 97 | + } | |
| 98 | + if( '' !== $new_action_links ){ | |
| 99 | + $actions['versions'] = '<span class="plugin-revision-wrp"><a href="#">'.esc_html__( 'Revisions','plugin-revisioons' ).'</a><span class="plugin-revisions-vers">'.rtrim( $new_action_links,' ' ).'</span></span>'; | |
| 100 | + } | |
| 101 | + } | |
| 102 | + return $actions; | |
| 103 | + },10,4 ); | |
| 104 | + } | |
| 105 | + } | |
| 106 | + } | |
| 107 | + return $plugins; | |
| 108 | +} ); | |
| 109 | + | |
| 25 | 110 | add_action( 'admin_head',function(){ |
| 26 | 111 | /** |
| 27 | 112 | * Add style to properly show the revisions on the page of plugins |
| 28 | 113 | * |
| @@ -46,10 +131,9 @@ | ||
| 46 | 131 | min-width:200px; |
| 47 | 132 | min-width:max-content; |
| 48 | 133 | background:#fff; |
| 49 | 134 | margin-top:15px; |
| 50 | - padding:10px 10px; | |
| 51 | - z-index:9 | |
| 135 | + padding:10px 10px | |
| 52 | 136 | } |
| 53 | 137 | .plugin-revision-wrp:hover .plugin-revisions-vers a{ |
| 54 | 138 | display:block; |
| 55 | 139 | border-bottom:1px dashed; |
| @@ -66,9 +150,8 @@ | ||
| 66 | 150 | |
| 67 | 151 | add_action( 'admin_footer',function(){ |
| 68 | 152 | /** |
| 69 | 153 | * Add JS to restore a revision via Ajax |
| 70 | - * This script is added to the plugins.php and plugin-editor.php pages. | |
| 71 | 154 | * |
| 72 | 155 | * @since 0.0.1 |
| 73 | 156 | */ |
| 74 | 157 | global $pagenow; |
| @@ -74,30 +157,8 @@ | ||
| 74 | 157 | global $pagenow; |
| 75 | 158 | if( $pagenow && 'plugins.php' === sanitize_text_field( $pagenow ) ){ |
| 76 | 159 | wp_nonce_field( 'plugin_reviews_restore_version','plugin_reviews_restore_version' ); |
| 77 | 160 | ?> |
| 78 | - <style id="plugin-revisions-js-css" type="text/css"> | |
| 79 | - .plugin-revision-processing{position:relative;cursor:wait;} | |
| 80 | - .plugin-revision-processing:after{ | |
| 81 | - content:' '; | |
| 82 | - position:absolute; | |
| 83 | - top:50%; | |
| 84 | - left:50%; | |
| 85 | - transform:translate(-50%,-50%); | |
| 86 | - background-color:rgba(255,255,255,0.8); | |
| 87 | - border-radius:50%; | |
| 88 | - box-shadow:0 0 5px rgba(0,0,0,0.2); | |
| 89 | - z-index:9999; | |
| 90 | - background-size:16px 16px; | |
| 91 | - background-image:url(<?php echo esc_url( PLUGIN_REVISIONS_PLUGIN_URL ); ?>/admin/assets/images/ajax-loader.gif ); | |
| 92 | - background-position:center center; | |
| 93 | - background-repeat:no-repeat; | |
| 94 | - width:16px; | |
| 95 | - height:16px; | |
| 96 | - display:block; | |
| 97 | - opacity:1 | |
| 98 | - } | |
| 99 | - </style> | |
| 100 | 161 | <script id="plugin-revisions-js"> |
| 101 | 162 | function eos_plugin_revisions(){ |
| 102 | 163 | var as = document.getElementsByClassName('plugin-revision-action'),n=0,req = new XMLHttpRequest(),fd=new FormData(),nonce=document.getElementById('plugin_reviews_restore_version').value; |
| 103 | 164 | for(n;n<as.length;++n){ |
| @@ -102,9 +163,8 @@ | ||
| 102 | 163 | var as = document.getElementsByClassName('plugin-revision-action'),n=0,req = new XMLHttpRequest(),fd=new FormData(),nonce=document.getElementById('plugin_reviews_restore_version').value; |
| 103 | 164 | for(n;n<as.length;++n){ |
| 104 | 165 | as[n].addEventListener('click',function(e){ |
| 105 | 166 | e.preventDefault(); |
| 106 | - this.closest('td').classList.add('plugin-revision-processing'); | |
| 107 | 167 | this.style.backgroundPosition = 'center center'; |
| 108 | 168 | for(var k=0;k<as.length;++k){ |
| 109 | 169 | as[k].style.pointerEvents = 'none'; |
| 110 | 170 | } |
| @@ -153,9 +213,8 @@ | ||
| 153 | 213 | } ); |
| 154 | 214 | |
| 155 | 215 | /** |
| 156 | 216 | * Remove all plugin revisions |
| 157 | - * This function removes all revisions of a specific plugin or all plugins if no plugin name is provided. | |
| 158 | 217 | * |
| 159 | 218 | * @since 0.0.1 |
| 160 | 219 | */ |
| 161 | 220 | function eos_plugin_revisions_remove_versions( $N = false,$plugin_name = false ){ |
| @@ -207,9 +266,8 @@ | ||
| 207 | 266 | } |
| 208 | 267 | |
| 209 | 268 | /** |
| 210 | 269 | * Revisions scandir |
| 211 | - * This function scans the plugin revisions directory and returns an array of files sorted by modification time. | |
| 212 | 270 | * |
| 213 | 271 | * @since 0.0.1 |
| 214 | 272 | */ |
| 215 | 273 | function eos_plugin_revisions_scandir( $dir ) { |
| @@ -222,324 +280,4 @@ | ||
| 222 | 280 | asort( $files ); |
| 223 | 281 | $files = array_keys( $files ); |
| 224 | 282 | return ( $files ) ? $files : false; |
| 225 | 283 | } |
| 226 | - | |
| 227 | -add_action( 'admin_init', 'eos_pv_restore_revision_links' ); | |
| 228 | -/** | |
| 229 | - * Add links to restore previous revisions from zipped plugins. | |
| 230 | - * This function initializes the restoring link functionality for plugin revisions. | |
| 231 | - * | |
| 232 | - * @since 0.0.6 | |
| 233 | - */ | |
| 234 | -function eos_pv_restore_revision_links() { | |
| 235 | - require_once PLUGIN_REVISIONS_PLUGIN_DIR . '/admin/classes/class-plugversions-restoring-link.php'; | |
| 236 | - $link = new PlugVersions_Restoring_Link(); | |
| 237 | -} | |
| 238 | - | |
| 239 | - | |
| 240 | -/** | |
| 241 | - * Backup the plugin before update. | |
| 242 | - * This filter allows you to catch all possible update scenarios, including bulk and manual replacements, as well as Ajax updates. | |
| 243 | - * | |
| 244 | - * @param string $source Plugin source path. | |
| 245 | - * @param string $remote_source Plugin remote source path. | |
| 246 | - * @param object $upgrader Upgrader object. | |
| 247 | - * @param array $hook_extra Hook extra data. | |
| 248 | - * @return string | |
| 249 | - * | |
| 250 | - * @author Vincenzo Casu. | |
| 251 | - */ | |
| 252 | -function eos_plugin_unversal_backup( $source, $remote_source, $upgrader, $hook_extra ) { | |
| 253 | - // Load get_plugin_data() if not exists. | |
| 254 | - if ( ! function_exists( 'get_plugin_data' ) ) { | |
| 255 | - require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 256 | - } | |
| 257 | - | |
| 258 | - // Get plugins to backup. | |
| 259 | - $plugins_to_backup = array(); | |
| 260 | - | |
| 261 | - if ( ! empty( $hook_extra['plugins'] ) && is_array( $hook_extra['plugins'] ) ) { | |
| 262 | - // Bulk update (hook_extra['plugins']). | |
| 263 | - $plugins_to_backup = $hook_extra['plugins']; | |
| 264 | - } elseif ( ! empty( $hook_extra['plugin'] ) ) { | |
| 265 | - // Single AJAX update (hook_extra['plugin']). | |
| 266 | - $plugins_to_backup = array( $hook_extra['plugin'] ); | |
| 267 | - } elseif ( ! empty( $hook_extra['type'] ) && $hook_extra['type'] === 'plugin' | |
| 268 | - && ! empty( $hook_extra['action'] ) | |
| 269 | - && in_array( $hook_extra['action'], array( 'update', 'install' ), true ) ) { | |
| 270 | - // Fallback “replace from ZIP” or other plugin-based cases. | |
| 271 | - | |
| 272 | - // Get slug from source. | |
| 273 | - $slug = basename( $source ); | |
| 274 | - $all = get_plugins( '/' . $slug ); | |
| 275 | - | |
| 276 | - if ( ! empty( $all ) ) { | |
| 277 | - $main_file = key( $all ); | |
| 278 | - $plugins_to_backup[] = $slug . '/' . $main_file; | |
| 279 | - } else { | |
| 280 | - // If no plugins found, return the source. | |
| 281 | - return $source; | |
| 282 | - } | |
| 283 | - } else { | |
| 284 | - // No plugins to backup. | |
| 285 | - return $source; | |
| 286 | - } | |
| 287 | - | |
| 288 | - // Preparing Filesystem & Upgrader. | |
| 289 | - if ( ! class_exists( 'WP_Upgrader' ) ) { | |
| 290 | - require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; | |
| 291 | - } | |
| 292 | - | |
| 293 | - global $wp_filesystem; | |
| 294 | - if ( empty( $wp_filesystem ) ) { | |
| 295 | - require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 296 | - WP_Filesystem(); | |
| 297 | - } | |
| 298 | - | |
| 299 | - $key = eos_plugin_revision_key(); | |
| 300 | - if ( ! $key ) { | |
| 301 | - return $source; | |
| 302 | - } | |
| 303 | - foreach ( $plugins_to_backup as $plugin_file ) { | |
| 304 | - $plugin_dir = WP_PLUGIN_DIR . '/' . dirname( $plugin_file ); | |
| 305 | - $full_path = WP_PLUGIN_DIR . '/' . $plugin_file; | |
| 306 | - if ( ! file_exists( $full_path ) ) { | |
| 307 | - continue; | |
| 308 | - } | |
| 309 | - | |
| 310 | - // Metadata & version. | |
| 311 | - $plugin_data = get_plugin_data( $full_path ); | |
| 312 | - $version = $plugin_data['Version']; | |
| 313 | - $slug = dirname( $plugin_file ); | |
| 314 | - $zip_dirname = 'pr-' . $key . '-' . sanitize_option( 'upload_path', $version ) . '-ver-' . $slug; | |
| 315 | - | |
| 316 | - // Base dir & Backup destination. | |
| 317 | - $base_dir = plugin_dir_path( $full_path ); | |
| 318 | - $backup_dir = trailingslashit( str_replace( $slug, $zip_dirname, $base_dir ) ); | |
| 319 | - // Make Backup dir and move plugin files into it. | |
| 320 | - if ( ! $wp_filesystem->is_dir( $backup_dir ) ) { | |
| 321 | - $wp_filesystem->mkdir( $backup_dir ); | |
| 322 | - } | |
| 323 | - if ( $wp_filesystem->is_dir( $backup_dir ) ) { | |
| 324 | - copy_dir( $plugin_dir, $backup_dir ); | |
| 325 | - $zip_file = $zip_dirname . '.zip'; | |
| 326 | - // Create a zip file of the plugin. | |
| 327 | - | |
| 328 | - if ( eos_pv_create_zip_pclzip( $backup_dir, $zip_file ) ) { | |
| 329 | - $wp_filesystem->delete( untrailingslashit( $backup_dir ), true ); | |
| 330 | - } | |
| 331 | - | |
| 332 | - // Remove old versions of the plugin. | |
| 333 | - eos_plugin_revisions_remove_versions( | |
| 334 | - apply_filters( 'max_plugin_revisions', 4 ), | |
| 335 | - $slug | |
| 336 | - ); | |
| 337 | - } | |
| 338 | - } | |
| 339 | - | |
| 340 | - return $source; | |
| 341 | -} | |
| 342 | -add_filter( 'upgrader_source_selection', 'eos_plugin_unversal_backup', 10, 4 ); | |
| 343 | - | |
| 344 | -/** | |
| 345 | - * Rollback WordPress core to a specific version. | |
| 346 | - * This function allows you to rollback the WordPress core to a specified version. | |
| 347 | - * It downloads the specified version, unzips it, and replaces the current core files, | |
| 348 | - * while preserving the wp-content directory and wp-config.php file. | |
| 349 | - * | |
| 350 | - * @param string $version The version of WordPress to rollback to. Default is '6.4.3'. | |
| 351 | - * @return bool|WP_Error Returns true on success or WP_Error on failure. | |
| 352 | - * | |
| 353 | - * @since 1.0.0 | |
| 354 | - */ | |
| 355 | -function eos_pv_rollback_wordpress_core($version) { | |
| 356 | - if ( ! current_user_can('update_core') ) { | |
| 357 | - wp_die( esc_html__( 'You are not allowed to update the core.', 'plugversions' ) ); | |
| 358 | - } | |
| 359 | - | |
| 360 | - require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 361 | - require_once ABSPATH . 'wp-admin/includes/misc.php'; | |
| 362 | - require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; | |
| 363 | - require_once ABSPATH . 'wp-admin/includes/update.php'; | |
| 364 | - | |
| 365 | - WP_Filesystem(); | |
| 366 | - global $wp_filesystem; | |
| 367 | - | |
| 368 | - // Put site in maintenance mode | |
| 369 | - $maintenance_string = '<?php $upgrading = ' . time() . '; ?>'; | |
| 370 | - $wp_filesystem->put_contents(ABSPATH . '.maintenance', $maintenance_string, FS_CHMOD_FILE); | |
| 371 | - | |
| 372 | - // Download WordPress version zip | |
| 373 | - $zip_url = "https://wordpress.org/wordpress-{$version}.zip"; | |
| 374 | - $tmp_file = download_url($zip_url); | |
| 375 | - | |
| 376 | - if ( is_wp_error($tmp_file) ) { | |
| 377 | - $wp_filesystem->delete(ABSPATH . '.maintenance'); | |
| 378 | - return new WP_Error('download_failed', 'Failed to download WordPress version.'); | |
| 379 | - } | |
| 380 | - | |
| 381 | - // Unzip into temp folder | |
| 382 | - $unzip_dir = WP_TEMP_DIR . "wordpress-rollback-{$version}"; | |
| 383 | - $result = unzip_file($tmp_file, $unzip_dir); | |
| 384 | - unlink($tmp_file); // Remove zip file | |
| 385 | - | |
| 386 | - if ( is_wp_error($result) ) { | |
| 387 | - $wp_filesystem->delete(ABSPATH . '.maintenance'); | |
| 388 | - return $result; | |
| 389 | - } | |
| 390 | - | |
| 391 | - // Copy files from the unzipped wordpress/ directory | |
| 392 | - $source = trailingslashit($unzip_dir) . 'wordpress'; | |
| 393 | - $dest = ABSPATH; | |
| 394 | - | |
| 395 | - $items = $wp_filesystem->dirlist($source); | |
| 396 | - foreach ($items as $item => $details) { | |
| 397 | - if ($item === 'wp-content' || $item === 'wp-config.php') { | |
| 398 | - continue; // Skip user files | |
| 399 | - } | |
| 400 | - $source_path = trailingslashit($source) . $item; | |
| 401 | - $dest_path = trailingslashit($dest) . $item; | |
| 402 | - | |
| 403 | - // Remove existing file or folder | |
| 404 | - if ($wp_filesystem->exists($dest_path)) { | |
| 405 | - $wp_filesystem->delete($dest_path, true); | |
| 406 | - } | |
| 407 | - | |
| 408 | - // Copy new one | |
| 409 | - $wp_filesystem->copy($source_path, $dest_path, true, FS_CHMOD_FILE); | |
| 410 | - } | |
| 411 | - | |
| 412 | - // Cleanup | |
| 413 | - $wp_filesystem->delete($unzip_dir, true); | |
| 414 | - $wp_filesystem->delete(ABSPATH . '.maintenance'); | |
| 415 | - | |
| 416 | - return true; | |
| 417 | -} | |
| 418 | - | |
| 419 | -add_action('admin_init', function() { | |
| 420 | - /** | |
| 421 | - * Handle rollback request for WordPress core. | |
| 422 | - * This function checks if the user has permission to update the core, | |
| 423 | - * verifies the nonce, and processes the rollback request. | |
| 424 | - * | |
| 425 | - * @since 1.0.0 | |
| 426 | - */ | |
| 427 | - | |
| 428 | - if (isset($_GET['rollback_wp']) && current_user_can('update_core') && check_admin_referer('eos_pv_core_rollback_nonce')) { | |
| 429 | - $version = sanitize_text_field($_GET['rollback_wp']); | |
| 430 | - // Validate version format | |
| 431 | - // Example: 6.4.3 | |
| 432 | - // Ensure it matches the expected format of major.minor.patch | |
| 433 | - // This regex checks for three groups of digits separated by dots. | |
| 434 | - if (!preg_match('/^\d+\.\d+\.\d+$/', $version)) { | |
| 435 | - wp_die(esc_html__('Invalid version format.', 'plugversions')); | |
| 436 | - } | |
| 437 | - | |
| 438 | - // Perform the rollback | |
| 439 | - $result = eos_pv_rollback_wordpress_core( $version ); | |
| 440 | - if (is_wp_error($result)) { | |
| 441 | - echo 'Error: ' . $result->get_error_message(); | |
| 442 | - } else { | |
| 443 | - esc_html_e( 'Rollback completed. Please manually check your site.', 'plugversions' ); | |
| 444 | - } | |
| 445 | - exit; | |
| 446 | - } | |
| 447 | -}); | |
| 448 | - | |
| 449 | -add_action('upgrader_process_complete', function ($upgrader, $hook_extra) { | |
| 450 | - /** | |
| 451 | - * Save the current WordPress core version after an update. | |
| 452 | - * This function saves the current WordPress version to an option after a core update. | |
| 453 | - * It prevents duplicates and limits the saved versions to the last 3. | |
| 454 | - * | |
| 455 | - * @param WP_Upgrader $upgrader The upgrader instance. | |
| 456 | - * @param array $hook_extra Extra data passed to the hook. | |
| 457 | - * | |
| 458 | - * @since 1.0.0 | |
| 459 | - */ | |
| 460 | - | |
| 461 | - // Check if this is a core update | |
| 462 | - if ( ! is_a( $upgrader, 'Core_Upgrader' ) || ! isset( $hook_extra['type'], $hook_extra['action'] ) ) { | |
| 463 | - return; | |
| 464 | - } | |
| 465 | - | |
| 466 | - // Check if the action is an update | |
| 467 | - // and the type is core. | |
| 468 | - // This ensures that we only save versions after a core update. | |
| 469 | - if ( | |
| 470 | - isset($hook_extra['type'], $hook_extra['action']) && | |
| 471 | - $hook_extra['type'] === 'core' && | |
| 472 | - $hook_extra['action'] === 'update' | |
| 473 | - ) { | |
| 474 | - $current_version = get_bloginfo('version'); | |
| 475 | - $option_name = 'eos_pv_core_versions'; | |
| 476 | - | |
| 477 | - // Get existing saved versions | |
| 478 | - $saved_versions = get_option($option_name, []); | |
| 479 | - | |
| 480 | - // Prevent duplicates | |
| 481 | - if (!in_array($current_version, $saved_versions, true)) { | |
| 482 | - array_unshift($saved_versions, $current_version); // Add to beginning | |
| 483 | - } | |
| 484 | - | |
| 485 | - // Optional: limit to last 3 versions | |
| 486 | - $saved_versions = array_slice($saved_versions, 0, 3); | |
| 487 | - | |
| 488 | - update_option($option_name, $saved_versions); | |
| 489 | - } | |
| 490 | -}, 10, 2); | |
| 491 | - | |
| 492 | -add_action('admin_notices', function () { | |
| 493 | - return; // Disable admin notices for now, as the core rollback functionality is still not ready. | |
| 494 | - /** | |
| 495 | - * Display rollback notice on the update-core page. | |
| 496 | - * This function displays a notice with a dropdown to select a previous WordPress core version | |
| 497 | - * for rollback, if available. | |
| 498 | - * | |
| 499 | - * @since 1.0.0 | |
| 500 | - */ | |
| 501 | - | |
| 502 | - // Only show on the update-core screen | |
| 503 | - | |
| 504 | - if (get_current_screen()->id !== 'update-core') return; | |
| 505 | - | |
| 506 | - $versions = get_option('eos_pv_core_versions', []); // Get saved versions | |
| 507 | - // Ensure versions are unique and sorted | |
| 508 | - $versions = array_unique($versions); | |
| 509 | - sort($versions); | |
| 510 | - | |
| 511 | - // If no versions are available, do not display the notice | |
| 512 | - if (empty($versions)) return; | |
| 513 | - | |
| 514 | - ?> | |
| 515 | - <div class="notice notice-info"> | |
| 516 | - <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> | |
| 517 | - <h3><?php esc_html_e( 'Rollback WordPress Core', 'plugversions' ); ?></h3> | |
| 518 | - <p><?php esc_html_e( 'Select a previously stored version to roll back to:', 'plugversions' ); ?></p> | |
| 519 | - <select name="eos_pv_version_to_rollback"> | |
| 520 | - <?php foreach ($versions as $version): ?> | |
| 521 | - <option value="<?php echo esc_attr($version); ?>"> | |
| 522 | - <?php echo esc_html($version); ?> | |
| 523 | - </option> | |
| 524 | - <?php endforeach; ?> | |
| 525 | - </select> | |
| 526 | - <?php wp_nonce_field('eos_pv_rollback_wp_core', 'eos_pv_nonce'); ?> | |
| 527 | - <input type="hidden" name="action" value="eos_pv_rollback_core"> | |
| 528 | - <button type="submit" class="button button-primary"><?php esc_html_e( 'Rollback', 'plugversions' ); ?></button> | |
| 529 | - </form> | |
| 530 | - </div> | |
| 531 | - <?php | |
| 532 | -}); | |
| 533 | - | |
| 534 | -add_filter( 'plugin_action_links_plugversions/plugversions.php', function( $links ) { | |
| 535 | - /** | |
| 536 | - * Add plugin action link for Annual Protection Plan. | |
| 537 | - * | |
| 538 | - * @param array $links Array of plugin action links | |
| 539 | - * @return array Modified array of plugin action links | |
| 540 | - */ | |
| 541 | - $plan_link = '<a href="https://shop.josemortellaro.com/downloads/plugin-update-rescue-annual-protection-plan/" style="color: #d63638; font-weight: bold;">' . esc_html__( 'Protection Plan', 'plugversions' ) . '</a>'; | |
| 542 | - // Add to the beginning of the links array | |
| 543 | - array_unshift( $links, $plan_link ); | |
| 544 | - return $links; | |
| 545 | -} ); | |