<?php
/**
* The Compatibility Checker parent.
*
* @package Automattic/WooCommerce/Grow/Tools
*/
namespace Automattic\WooCommerce\Grow\Tools\CompatChecker\v0_0_1\Checks;
use WC_Admin_Notices;
defined( 'ABSPATH' ) || exit;
/**
* The CompatCheck class.
*/
abstract class CompatCheck {
/**
* Array of admin notices.
*
* @var array
*/
protected $notices = [];
/**
* Array of CompatCheck instances.
*
* @var array
*/
private static $instances = [];
/**
* The plugin data.
*
* @var array
*/
protected $plugin_data = [];
/**
* Run checks
*
* @return bool
*/
abstract protected function run_checks();
/**
* Get the instance of the CompatCheck object.
*
* @param string $plugin_basename The basename of the plugin.
*
* @return CompatCheck
*/
public static function instance( $plugin_basename ) {
$class = get_called_class();
if ( ! isset( self::$instances[ $class ][ $plugin_basename ] ) ) {
self::$instances[ $class ][ $plugin_basename ] = new $class();
}
return self::$instances[ $class ][ $plugin_basename ];
}
/**
* Adds an admin notice to be displayed.
*
* @param string $slug The slug for the notice.
* @param string $css_class The CSS class for the notice.
* @param string $message The notice message.
*/
protected function add_admin_notice( $slug, $css_class, $message ) {
$screen = get_current_screen();
$hidden = [ 'update', 'update-network', 'update-core', 'update-core-network', 'upgrade', 'upgrade-network', 'network' ];
$show = isset( $screen->id ) && ! in_array( $screen->id, $hidden, true );
$slug = isset( $this->plugin_data['File'] ) ? plugin_basename( $this->plugin_data['File'] ) . '-' . $slug : $slug;
/**
* The Compat Check filter to show an admin notice.
*
* @since 0.0.1
*
* @param bool $show Whether to show the admin notice.
* @param string $slug The slug for the notice.
*/
if ( ! apply_filters( 'wc_grow_compat_check_show_admin_notice', $show, $slug ) ) {
return;
}
// If the notice is a warning and WooCommerce admin notice system is available. Then use it.
if ( str_contains( $css_class, 'warning' ) && class_exists( WC_Admin_Notices::class ) ) {
// Do not display the notice if it was dismissed.
if ( ! get_user_meta( get_current_user_id(), 'dismissed_' . $slug . '_notice', true ) ) {
WC_Admin_Notices::add_custom_notice( $slug, $message );
}
} else {
$this->notices[ $slug ] = [
'class' => $css_class,
'message' => $message,
];
}
}
/**
* Compares major version.
*
* @param string $left First version number.
* @param string $right Second version number.
* @param string $operator An optional operator. The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively.
*
* @return int|bool
*/
protected function compare_major_version( $left, $right, $operator = null ) {
$pattern = '/^(\d+\.\d+).*/';
$replace = '$1.0';
$left = preg_replace( $pattern, $replace, $left );
$right = preg_replace( $pattern, $replace, $right );
return version_compare( $left, $right, $operator );
}
/**
* Display admin notices generated by the checker.
*/
public function display_admin_notices() {
$allowed_tags = [
'a' => [
'class' => [],
'href' => [],
'target' => [],
],
'strong' => [],
];
foreach ( $this->notices as $key => $notice ) {
$class = $notice['class'];
$message = $notice['message'];
printf(
'<div class="notice notice-%1$s"><p>%2$s</p></div>',
esc_attr( $class ),
wp_kses( $message, $allowed_tags )
);
}
}
/**
* Sets the plugin data.
*
* @param array $plugin_data The plugin data.
*/
protected function set_plugin_data( $plugin_data ) {
$defaults = [
'Name' => '',
'Version' => '',
'RequiresWP' => '',
'RequiresPHP' => '',
'RequiresWC' => '',
'TestedWP' => '',
'TestedWC' => '',
];
$this->plugin_data = wp_parse_args( $plugin_data, $defaults );
}
/**
* Determines if the plugin is WooCommerce compatible.
*
* @param array $plugin_data The plugin data.
*
* @return bool
*/
public function is_compatible( $plugin_data ) {
$this->set_plugin_data( $plugin_data );
add_action( 'admin_notices', [ $this, 'display_admin_notices' ], 20 );
return $this->run_checks();
}
/**
* Remove dismissable notices.
*/
public function remove_dismissable_notices() {
if ( class_exists( WC_Admin_Notices::class ) ) {
$plugin_basename = plugin_basename( $this->plugin_data['File'] );
$all_notices = WC_Admin_Notices::get_notices();
foreach ( $all_notices as $notice_name ) {
if ( 0 === strpos( $notice_name, $plugin_basename ) ) {
WC_Admin_Notices::remove_notice( $notice_name );
}
}
}
}
}