2021-09-21 15:01:08 +02:00
< ? php
/**
* WPSEO plugin file .
*
* @ package WPSEO\Admin
* @ since 1.7 . 0
*/
/**
* Base class for handling plugin conflicts .
*/
class Yoast_Plugin_Conflict {
/**
* The plugins must be grouped per section .
*
2021-09-21 15:05:30 +02:00
* It ' s possible to check for each section if there are conflicting plugins .
2021-09-21 15:01:08 +02:00
*
* @ var array
*/
2021-09-21 15:05:30 +02:00
protected $plugins = [];
2021-09-21 15:01:08 +02:00
/**
2021-09-21 15:05:30 +02:00
* All the current active plugins will be stored in this private var .
2021-09-21 15:01:08 +02:00
*
* @ var array
*/
2021-09-21 15:05:30 +02:00
protected $all_active_plugins = [];
2021-09-21 15:01:08 +02:00
/**
* After searching for active plugins that are in $this -> plugins the active plugins will be stored in this
2021-09-21 15:05:30 +02:00
* property .
2021-09-21 15:01:08 +02:00
*
* @ var array
*/
2021-09-21 15:05:30 +02:00
protected $active_plugins = [];
2021-09-21 15:01:08 +02:00
/**
2021-09-21 15:05:30 +02:00
* Property for holding instance of itself .
2021-09-21 15:01:08 +02:00
*
* @ var Yoast_Plugin_Conflict
*/
protected static $instance ;
/**
2021-09-21 15:05:30 +02:00
* For the use of singleton pattern . Create instance of itself and return this instance .
2021-09-21 15:01:08 +02:00
*
2021-09-21 15:05:30 +02:00
* @ param string $class_name Give the classname to initialize . If classname is
* false ( empty ) it will use it ' s own __CLASS__ .
2021-09-21 15:01:08 +02:00
*
* @ return Yoast_Plugin_Conflict
*/
public static function get_instance ( $class_name = '' ) {
if ( is_null ( self :: $instance ) ) {
if ( ! is_string ( $class_name ) || $class_name === '' ) {
$class_name = __CLASS__ ;
}
self :: $instance = new $class_name ();
}
return self :: $instance ;
}
/**
2021-09-21 15:05:30 +02:00
* Setting instance , all active plugins and search for active plugins .
2021-09-21 15:01:08 +02:00
*
* Protected constructor to prevent creating a new instance of the
* * Singleton * via the `new` operator from outside of this class .
*/
protected function __construct () {
// Set active plugins.
$this -> all_active_plugins = get_option ( 'active_plugins' );
if ( filter_input ( INPUT_GET , 'action' ) === 'deactivate' ) {
$this -> remove_deactivated_plugin ();
}
// Search for active plugins.
$this -> search_active_plugins ();
}
/**
2021-09-21 15:05:30 +02:00
* Check if there are conflicting plugins for given $plugin_section .
2021-09-21 15:01:08 +02:00
*
* @ param string $plugin_section Type of plugin conflict ( such as Open Graph or sitemap ) .
*
* @ return bool
*/
public function check_for_conflicts ( $plugin_section ) {
static $sections_checked ;
if ( $sections_checked === null ) {
2021-09-21 15:05:30 +02:00
$sections_checked = [];
2021-09-21 15:01:08 +02:00
}
if ( ! in_array ( $plugin_section , $sections_checked , true ) ) {
$sections_checked [] = $plugin_section ;
$has_conflicts = ( ! empty ( $this -> active_plugins [ $plugin_section ] ) );
return $has_conflicts ;
}
return false ;
}
/**
* Getting all the conflicting plugins and return them as a string .
*
* This method will loop through all conflicting plugins to get the details of each plugin . The plugin name
* will be taken from the details to parse a comma separated string , which can be use for by example a notice
*
* @ param string $plugin_section Plugin conflict type ( such as Open Graph or sitemap ) .
*
* @ return string
*/
public function get_conflicting_plugins_as_string ( $plugin_section ) {
if ( ! function_exists ( 'get_plugin_data' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php' ;
}
// Getting the active plugins by given section.
$plugins = $this -> active_plugins [ $plugin_section ];
2021-09-21 15:05:30 +02:00
$plugin_names = [];
2021-09-21 15:01:08 +02:00
foreach ( $plugins as $plugin ) {
2021-09-21 15:05:30 +02:00
$name = $this -> get_plugin_name ( $plugin );
2021-09-21 15:01:08 +02:00
if ( ! empty ( $name ) ) {
$plugin_names [] = '<em>' . $name . '</em>' ;
}
}
unset ( $plugins , $plugin );
if ( ! empty ( $plugin_names ) ) {
return implode ( ' & ' , $plugin_names );
}
}
/**
2021-09-21 15:05:30 +02:00
* Checks for given $plugin_sections for conflicts .
2021-09-21 15:01:08 +02:00
*
* @ param array $plugin_sections Set of sections .
*/
public function check_plugin_conflicts ( $plugin_sections ) {
foreach ( $plugin_sections as $plugin_section => $readable_plugin_section ) {
// Check for conflicting plugins and show error if there are conflicts.
if ( $this -> check_for_conflicts ( $plugin_section ) ) {
$this -> set_error ( $plugin_section , $readable_plugin_section );
}
}
// List of all active sections.
$sections = array_keys ( $plugin_sections );
// List of all sections.
$all_plugin_sections = array_keys ( $this -> plugins );
/*
* Get all sections that are inactive .
* These plugins need to be cleared .
*
* This happens when Sitemaps or OpenGraph implementations toggle active / disabled .
*/
$inactive_sections = array_diff ( $all_plugin_sections , $sections );
if ( ! empty ( $inactive_sections ) ) {
foreach ( $inactive_sections as $section ) {
2021-09-21 15:05:30 +02:00
array_walk ( $this -> plugins [ $section ], [ $this , 'clear_error' ] );
2021-09-21 15:01:08 +02:00
}
}
// For active sections clear errors for inactive plugins.
foreach ( $sections as $section ) {
// By default clear errors for all plugins of the section.
$inactive_plugins = $this -> plugins [ $section ];
// If there are active plugins, filter them from being cleared.
if ( isset ( $this -> active_plugins [ $section ] ) ) {
$inactive_plugins = array_diff ( $this -> plugins [ $section ], $this -> active_plugins [ $section ] );
}
2021-09-21 15:05:30 +02:00
array_walk ( $inactive_plugins , [ $this , 'clear_error' ] );
2021-09-21 15:01:08 +02:00
}
}
/**
2021-09-21 15:05:30 +02:00
* Setting an error on the screen .
2021-09-21 15:01:08 +02:00
*
* @ param string $plugin_section Type of conflict group ( such as Open Graph or sitemap ) .
* @ param string $readable_plugin_section This is the value for the translation .
*/
protected function set_error ( $plugin_section , $readable_plugin_section ) {
$notification_center = Yoast_Notification_Center :: get ();
foreach ( $this -> active_plugins [ $plugin_section ] as $plugin_file ) {
2021-09-21 15:05:30 +02:00
$plugin_name = $this -> get_plugin_name ( $plugin_file );
2021-09-21 15:01:08 +02:00
$error_message = '' ;
/* translators: %1$s: 'Facebook & Open Graph' plugin name(s) of possibly conflicting plugin(s), %2$s to Yoast SEO */
$error_message .= '<p>' . sprintf ( __ ( 'The %1$s plugin might cause issues when used in conjunction with %2$s.' , 'wordpress-seo' ), '<em>' . $plugin_name . '</em>' , 'Yoast SEO' ) . '</p>' ;
$error_message .= '<p>' . sprintf ( $readable_plugin_section , 'Yoast SEO' , $plugin_name ) . '</p>' ;
/* translators: %s: 'Facebook' plugin name of possibly conflicting plugin */
2021-09-21 15:05:30 +02:00
$error_message .= '<a class="button button-primary" href="' . wp_nonce_url ( 'plugins.php?action=deactivate&plugin=' . $plugin_file . '&plugin_status=all' , 'deactivate-plugin_' . $plugin_file ) . '">' . sprintf ( __ ( 'Deactivate %s' , 'wordpress-seo' ), $this -> get_plugin_name ( $plugin_file ) ) . '</a> ' ;
2021-09-21 15:01:08 +02:00
$identifier = $this -> get_notification_identifier ( $plugin_file );
// Add the message to the notifications center.
$notification_center -> add_notification (
new Yoast_Notification (
$error_message ,
2021-09-21 15:05:30 +02:00
[
2021-09-21 15:01:08 +02:00
'type' => Yoast_Notification :: ERROR ,
'id' => 'wpseo-conflict-' . $identifier ,
2021-09-21 15:05:30 +02:00
]
2021-09-21 15:01:08 +02:00
)
);
}
}
/**
2021-09-21 15:05:30 +02:00
* Clear the notification for a plugin .
2021-09-21 15:01:08 +02:00
*
* @ param string $plugin_file Clear the optional notification for this plugin .
*/
public function clear_error ( $plugin_file ) {
$identifier = $this -> get_notification_identifier ( $plugin_file );
$notification_center = Yoast_Notification_Center :: get ();
2021-09-21 15:05:30 +02:00
$notification_center -> remove_notification_by_id ( 'wpseo-conflict-' . $identifier );
2021-09-21 15:01:08 +02:00
}
/**
* Loop through the $this -> plugins to check if one of the plugins is active .
*
* This method will store the active plugins in $this -> active_plugins .
*/
protected function search_active_plugins () {
foreach ( $this -> plugins as $plugin_section => $plugins ) {
$this -> check_plugins_active ( $plugins , $plugin_section );
}
}
/**
2021-09-21 15:05:30 +02:00
* Loop through plugins and check if each plugin is active .
2021-09-21 15:01:08 +02:00
*
* @ param array $plugins Set of plugins .
* @ param string $plugin_section Type of conflict group ( such as Open Graph or sitemap ) .
*/
protected function check_plugins_active ( $plugins , $plugin_section ) {
foreach ( $plugins as $plugin ) {
if ( $this -> check_plugin_is_active ( $plugin ) ) {
$this -> add_active_plugin ( $plugin_section , $plugin );
}
}
}
/**
2021-09-21 15:05:30 +02:00
* Check if given plugin exists in array with all_active_plugins .
2021-09-21 15:01:08 +02:00
*
* @ param string $plugin Plugin basename string .
*
* @ return bool
*/
protected function check_plugin_is_active ( $plugin ) {
return in_array ( $plugin , $this -> all_active_plugins , true );
}
/**
* Add plugin to the list of active plugins .
*
* This method will check first if key $plugin_section exists , if not it will create an empty array
* If $plugin itself doesn ' t exist it will be added .
*
* @ param string $plugin_section Type of conflict group ( such as Open Graph or sitemap ) .
* @ param string $plugin Plugin basename string .
*/
protected function add_active_plugin ( $plugin_section , $plugin ) {
if ( ! array_key_exists ( $plugin_section , $this -> active_plugins ) ) {
2021-09-21 15:05:30 +02:00
$this -> active_plugins [ $plugin_section ] = [];
2021-09-21 15:01:08 +02:00
}
if ( ! in_array ( $plugin , $this -> active_plugins [ $plugin_section ], true ) ) {
$this -> active_plugins [ $plugin_section ][] = $plugin ;
}
}
/**
2021-09-21 15:05:30 +02:00
* Search in $this -> plugins for the given $plugin .
2021-09-21 15:01:08 +02:00
*
2021-09-21 15:05:30 +02:00
* If there is a result it will return the plugin category .
2021-09-21 15:01:08 +02:00
*
* @ param string $plugin Plugin basename string .
*
* @ return int | string
*/
protected function find_plugin_category ( $plugin ) {
foreach ( $this -> plugins as $plugin_section => $plugins ) {
if ( in_array ( $plugin , $plugins , true ) ) {
return $plugin_section ;
}
}
2021-09-21 15:05:30 +02:00
}
/**
* Get plugin name from file .
*
* @ param string $plugin Plugin path relative to plugins directory .
*
* @ return string | bool Plugin name or false when no name is set .
*/
protected function get_plugin_name ( $plugin ) {
$plugin_details = get_plugin_data ( WP_PLUGIN_DIR . '/' . $plugin );
if ( $plugin_details [ 'Name' ] !== '' ) {
return $plugin_details [ 'Name' ];
}
2021-09-21 15:01:08 +02:00
2021-09-21 15:05:30 +02:00
return false ;
2021-09-21 15:01:08 +02:00
}
/**
* When being in the deactivation process the currently deactivated plugin has to be removed .
*/
private function remove_deactivated_plugin () {
$deactivated_plugin = filter_input ( INPUT_GET , 'plugin' );
$key_to_remove = array_search ( $deactivated_plugin , $this -> all_active_plugins , true );
if ( $key_to_remove !== false ) {
unset ( $this -> all_active_plugins [ $key_to_remove ] );
}
}
/**
2021-09-21 15:05:30 +02:00
* Get the identifier from the plugin file .
2021-09-21 15:01:08 +02:00
*
* @ param string $plugin_file Plugin file to get Identifier from .
*
* @ return string
*/
private function get_notification_identifier ( $plugin_file ) {
return md5 ( $plugin_file );
}
}