key * @since 0.0.6 */ public $key; /** * Plugins. * * @var array $plugins * @since 0.0.8 */ public $plugins; /** * Main Constructor * This constructor initializes the class, checks for the plugin revision key, * populates the plugins data, and adds necessary filters for action links and cleaning the plugins list. * * @since 0.0.6 */ public function __construct() { $this->key = eos_plugin_revision_key(); $this->plugins = array(); if( $this->key && current_user_can( 'activate_plugin' ) ) { $this->plugins = $this->populate_plugins(); if( ! empty( $this->plugins ) ) { add_filter( 'plugin_action_links' , array( $this, 'add_link' ), 10, 4 ); } add_filter( 'all_plugins', array( $this, 'clean_plugins_list' ) ); } } /** * Populate plugins data * This function scans the plugins directory for plugin zip files that match the revision key. * It extracts the plugin name and version from the zip file names and organizes them into an array. * The array contains plugin names as keys, with their versions and zip file names as values. * * @since 0.0.6 */ public function populate_plugins() { $all_plugin_files = scandir( WP_PLUGIN_DIR ); if( $all_plugin_files && is_array( $all_plugin_files ) && ! empty( $all_plugin_files ) ) { $plugins = array(); foreach( $all_plugin_files as $plugin ) { if( 'zip' === pathinfo( $plugin, PATHINFO_EXTENSION ) ) { if( false !== strpos( $plugin, 'pr-' . $this->key .'-' ) && false !== strpos( $plugin, '-ver-' ) ) { $arr = explode( 'ver-', $plugin ); $arr = explode( '-', $arr[0] ); if( 'pr' === $arr[0] && isset( $arr[1] ) && $this->key === $arr[1] && isset( $arr[2] ) ) { $version = $arr[2]; $plugin_name = str_replace( array( 'pr-' . $this->key . '-' . $version . '-ver-', '.zip' ), array( '', '' ), $plugin ); if( is_dir( WP_PLUGIN_DIR . '/' . $plugin_name ) ) { if( ! isset( $plugins[$plugin_name]['versions'] ) ) { $plugins[$plugin_name]['versions'] = array(); } if( ! isset( $plugins[$plugin_name]['zips'] ) ) { $plugins[$plugin_name]['zips'] = array(); } $plugins[$plugin_name]['versions'][] = $version; $plugins[$plugin_name]['zips'][] = $plugin; } } } } } return $plugins; } } /** * Remove unzipped versions from the plugins list * This function iterates through the plugins list and removes any plugin that has a name starting with 'pr-' followed by the revision key. * It ensures that only the original plugins remain in the list, excluding any unzipped versions created by the plugin revisions. * * @param array $plugins * @param 0.0.8 */ public function clean_plugins_list( $plugins ) { foreach( $plugins as $plugin => $arr ) { if( false !== strpos( '_' . $plugin, 'pr-' . $this->key ) ) { unset( $plugins[$plugin] ); } } return $plugins; } /** * Add action link to restore plugin version. * This function adds a link to the plugin action links in the plugins list. * It checks if the plugin has any versions available for restoration, * and if so, it adds a link to restore each version. * * @param array $actions * @param string $plugin_file * @param array $plugin_data * @param string $context * @param 0.0.6 */ public function add_link( $actions, $plugin_file, $plugin_data, $context ) { if( isset( $this->plugins[dirname( $plugin_file )] ) ) { $plugin_vers = $this->plugins[dirname( $plugin_file )]; if( $plugin_vers && ! empty( $plugin_vers ) ) { $links = ''; $n = 0; foreach( $plugin_vers['versions'] as $version ) { if( isset( $plugin_vers['zips'][$n] ) ) { $zip_name = $plugin_vers['zips'][$n]; /* translators: version of the plugin. */ $links .= ''.sprintf( esc_html__( 'Replace with version: %s','plugversions' ), esc_attr( $version ) ).' '; } ++$n; } /* translators: the plugin revisions. */ $actions['versions'] = '' . esc_html__( 'Revisions','plugversions' ) . '' . rtrim( $links, ' ' ) . ''; } } return $actions; } }