Yoast_Plugin_Conflict

Base class for handling plugin conflicts.

Defined (1)

The class is defined in the following location(s).

/admin/class-yoast-plugin-conflict.php  
  1. class Yoast_Plugin_Conflict { 
  2.  
  3. /** 
  4. * The plugins must be grouped per section. 
  5. * It's possible to check for each section if there are conflicting plugin 
  6. * @var array 
  7. */ 
  8. protected $plugins = array(); 
  9.  
  10. /** 
  11. * All the current active plugins will be stored in this private var 
  12. * @var array 
  13. */ 
  14. protected $all_active_plugins = array(); 
  15.  
  16. /** 
  17. * After searching for active plugins that are in $this->plugins the active plugins will be stored in this 
  18. * property 
  19. * @var array 
  20. */ 
  21. protected $active_plugins = array(); 
  22.  
  23. /** 
  24. * Property for holding instance of itself 
  25. * @var Yoast_Plugin_Conflict 
  26. */ 
  27. protected static $instance; 
  28.  
  29. /** 
  30. * For the use of singleton pattern. Create instance of itself and return his instance 
  31. * @param string $class_name Give the classname to initialize. If classname is false (empty) it will use it's own __CLASS__. 
  32. * @return Yoast_Plugin_Conflict 
  33. */ 
  34. public static function get_instance( $class_name = '' ) { 
  35.  
  36. if ( is_null( self::$instance ) ) { 
  37. if ( ! is_string( $class_name ) || $class_name === '' ) { 
  38. $class_name = __CLASS__; 
  39.  
  40. self::$instance = new $class_name(); 
  41.  
  42. return self::$instance; 
  43.  
  44. /** 
  45. * Setting instance, all active plugins and search for active plugins 
  46. * Protected constructor to prevent creating a new instance of the 
  47. * *Singleton* via the `new` operator from outside of this class. 
  48. */ 
  49. protected function __construct() { 
  50. // Set active plugins. 
  51. $this->all_active_plugins = get_option( 'active_plugins' ); 
  52.  
  53. if ( filter_input( INPUT_GET, 'action' ) === 'deactivate' ) { 
  54. $this->remove_deactivated_plugin(); 
  55.  
  56. // Search for active plugins. 
  57. $this->search_active_plugins(); 
  58.  
  59. /** 
  60. * Check if there are conflicting plugins for given $plugin_section 
  61. * @param string $plugin_section Type of plugin conflict (such as Open Graph or sitemap). 
  62. * @return bool 
  63. */ 
  64. public function check_for_conflicts( $plugin_section ) { 
  65.  
  66. static $sections_checked; 
  67.  
  68. if ( $sections_checked === null ) { 
  69. $sections_checked = array(); 
  70.  
  71. if ( ! in_array( $plugin_section, $sections_checked ) ) { 
  72. $sections_checked[] = $plugin_section; 
  73. $has_conflicts = ( ! empty( $this->active_plugins[ $plugin_section ] ) ); 
  74.  
  75. return $has_conflicts; 
  76.  
  77. return false; 
  78.  
  79. /** 
  80. * Getting all the conflicting plugins and return them as a string. 
  81. * This method will loop through all conflicting plugins to get the details of each plugin. The plugin name 
  82. * will be taken from the details to parse a comma separated string, which can be use for by example a notice 
  83. * @param string $plugin_section Plugin conflict type (such as Open Graph or sitemap). 
  84. * @return string 
  85. */ 
  86. public function get_conflicting_plugins_as_string( $plugin_section ) { 
  87. if ( ! function_exists( 'get_plugin_data' ) ) { 
  88. require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); 
  89.  
  90. // Getting the active plugins by given section. 
  91. $plugins = $this->active_plugins[ $plugin_section ]; 
  92.  
  93. $plugin_names = array(); 
  94. foreach ( $plugins as $plugin ) { 
  95. if ( $name = WPSEO_Utils::get_plugin_name( $plugin ) ) { 
  96. $plugin_names[] = '<em>' . $name . '</em>'; 
  97. unset( $plugins, $plugin ); 
  98.  
  99. if ( ! empty( $plugin_names ) ) { 
  100. return implode( ' & ', $plugin_names ); 
  101.  
  102. /** 
  103. * Checks for given $plugin_sections for conflicts 
  104. * @param array $plugin_sections Set of sections. 
  105. */ 
  106. public function check_plugin_conflicts( $plugin_sections ) { 
  107. foreach ( $plugin_sections as $plugin_section => $readable_plugin_section ) { 
  108. // Check for conflicting plugins and show error if there are conflicts. 
  109. if ( $this->check_for_conflicts( $plugin_section ) ) { 
  110. $this->set_error( $plugin_section, $readable_plugin_section ); 
  111.  
  112. // List of all active sections. 
  113. $sections = array_keys( $plugin_sections ); 
  114. // List of all sections. 
  115. $all_plugin_sections = array_keys( $this->plugins ); 
  116.  
  117. /** 
  118. * Get all sections that are inactive. 
  119. * These plugins need to be cleared. 
  120. * This happens when Sitemaps or OpenGraph implementations toggle active/disabled. 
  121. */ 
  122. $inactive_sections = array_diff( $all_plugin_sections, $sections ); 
  123. if ( ! empty( $inactive_sections ) ) { 
  124. foreach ( $inactive_sections as $section ) { 
  125. array_walk( $this->plugins[ $section ], array( $this, 'clear_error' ) ); 
  126.  
  127. // For active sections clear errors for inactive plugins. 
  128. foreach ( $sections as $section ) { 
  129. // By default clear errors for all plugins of the section. 
  130. $inactive_plugins = $this->plugins[ $section ]; 
  131.  
  132. // If there are active plugins, filter them from being cleared. 
  133. if ( isset( $this->active_plugins[ $section ] ) ) { 
  134. $inactive_plugins = array_diff( $this->plugins[ $section ], $this->active_plugins[ $section ] ); 
  135.  
  136. array_walk( $inactive_plugins, array( $this, 'clear_error' ) ); 
  137.  
  138. /** 
  139. * Setting an error on the screen 
  140. * @param string $plugin_section Type of conflict group (such as Open Graph or sitemap). 
  141. * @param string $readable_plugin_section This is the value for the translation. 
  142. */ 
  143. protected function set_error( $plugin_section, $readable_plugin_section ) { 
  144.  
  145. $notification_center = Yoast_Notification_Center::get(); 
  146.  
  147. foreach ( $this->active_plugins[ $plugin_section ] as $plugin_file ) { 
  148.  
  149. $plugin_name = WPSEO_Utils::get_plugin_name( $plugin_file ); 
  150.  
  151. $error_message = ''; 
  152. /** translators: %1$s: 'Facebook & Open Graph' plugin name(s) of possibly conflicting plugin(s), %2$s to Yoast SEO */ 
  153. $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>'; 
  154. $error_message .= '<p>' . sprintf( $readable_plugin_section, 'Yoast SEO', $plugin_name ) . '</p>'; 
  155.  
  156. /** translators: %s: 'Facebook' plugin name of possibly conflicting plugin */ 
  157. $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' ), WPSEO_Utils::get_plugin_name( $plugin_file ) ) . '</a> '; 
  158.  
  159. $identifier = $this->get_notification_identifier( $plugin_file ); 
  160.  
  161. // Add the message to the notifications center. 
  162. $notification_center->add_notification( 
  163. new Yoast_Notification( 
  164. $error_message,  
  165. array( 
  166. 'type' => Yoast_Notification::ERROR,  
  167. 'id' => 'wpseo-conflict-' . $identifier,  
  168. ); 
  169.  
  170. /** 
  171. * Clear the notification for a plugin 
  172. * @param string $plugin_file Clear the optional notification for this plugin. 
  173. */ 
  174. protected function clear_error( $plugin_file ) { 
  175. $identifier = $this->get_notification_identifier( $plugin_file ); 
  176.  
  177. $notification_center = Yoast_Notification_Center::get(); 
  178. $notification = $notification_center->get_notification_by_id( 'wpseo-conflict-' . $identifier ); 
  179.  
  180. if ( $notification ) { 
  181. $notification_center->remove_notification( $notification ); 
  182.  
  183. /** 
  184. * Loop through the $this->plugins to check if one of the plugins is active. 
  185. * This method will store the active plugins in $this->active_plugins. 
  186. */ 
  187. protected function search_active_plugins() { 
  188. foreach ( $this->plugins as $plugin_section => $plugins ) { 
  189. $this->check_plugins_active( $plugins, $plugin_section ); 
  190.  
  191. /** 
  192. * Loop through plugins and check if each plugin is active 
  193. * @param array $plugins Set of plugins. 
  194. * @param string $plugin_section Type of conflict group (such as Open Graph or sitemap). 
  195. */ 
  196. protected function check_plugins_active( $plugins, $plugin_section ) { 
  197. foreach ( $plugins as $plugin ) { 
  198. if ( $this->check_plugin_is_active( $plugin ) ) { 
  199. $this->add_active_plugin( $plugin_section, $plugin ); 
  200.  
  201.  
  202. /** 
  203. * Check if given plugin exists in array with all_active_plugins 
  204. * @param string $plugin Plugin basename string. 
  205. * @return bool 
  206. */ 
  207. protected function check_plugin_is_active( $plugin ) { 
  208. return in_array( $plugin, $this->all_active_plugins ); 
  209.  
  210. /** 
  211. * Add plugin to the list of active plugins. 
  212. * This method will check first if key $plugin_section exists, if not it will create an empty array 
  213. * If $plugin itself doesn't exist it will be added. 
  214. * @param string $plugin_section Type of conflict group (such as Open Graph or sitemap). 
  215. * @param string $plugin Plugin basename string. 
  216. */ 
  217. protected function add_active_plugin( $plugin_section, $plugin ) { 
  218.  
  219. if ( ! array_key_exists( $plugin_section, $this->active_plugins ) ) { 
  220. $this->active_plugins[ $plugin_section ] = array(); 
  221.  
  222. if ( ! in_array( $plugin, $this->active_plugins[ $plugin_section ] ) ) { 
  223. $this->active_plugins[ $plugin_section ][] = $plugin; 
  224.  
  225. /** 
  226. * Search in $this->plugins for the given $plugin 
  227. * If there is a result it will return the plugin category 
  228. * @param string $plugin Plugin basename string. 
  229. * @return int|string 
  230. */ 
  231. protected function find_plugin_category( $plugin ) { 
  232.  
  233. foreach ( $this->plugins as $plugin_section => $plugins ) { 
  234. if ( in_array( $plugin, $plugins ) ) { 
  235. return $plugin_section; 
  236.  
  237.  
  238. /** 
  239. * When being in the deactivation process the currently deactivated plugin has to be removed. 
  240. */ 
  241. private function remove_deactivated_plugin() { 
  242. $deactivated_plugin = filter_input( INPUT_GET, 'plugin' ); 
  243. $key_to_remove = array_search( $deactivated_plugin, $this->all_active_plugins ); 
  244.  
  245. if ( $key_to_remove !== false ) { 
  246. unset( $this->all_active_plugins[ $key_to_remove ] ); 
  247.  
  248. /** 
  249. * Get the identifier from the plugin file 
  250. * @param string $plugin_file Plugin file to get Identifier from. 
  251. * @return string 
  252. */ 
  253. private function get_notification_identifier( $plugin_file ) { 
  254. return md5( $plugin_file );