Created
March 22, 2021 20:56
-
-
Save DrewAPicture/a855a49e2fdbe2dff552c8bfc81700c6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin With Checks Bootstrap | |
* | |
* @package Plugin With Checks | |
* @subpackage Core | |
* @copyright Copyright (c) 2021, Sandhills Development, LLC | |
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License | |
* @since 1.0.0 | |
*/ | |
// Exit if accessed directly | |
if ( ! defined( 'ABSPATH' ) ) { | |
exit; | |
} | |
if ( ! class_exists( 'Plugin_With_Checks' ) ) { | |
/** | |
* Setup class. | |
* | |
* @since 1.0.0 | |
*/ | |
final class Plugin_With_Checks { | |
/** | |
* Holds the instance. | |
* | |
* Ensures that only one instance of the main plugin class exists in memory at any one | |
* time and it also prevents needing to define globals all over the place. | |
* | |
* TL;DR This is a static property property that holds the singleton instance. | |
* | |
* @access private | |
* @var \Plugin_With_Checks | |
* @static | |
* | |
* @since 1.0.0 | |
*/ | |
private static $instance; | |
/** | |
* The version number. | |
* | |
* @access private | |
* @since 1.0.0 | |
* @var string | |
*/ | |
private $version = '1.0.0'; | |
/** | |
* Main plugin file. | |
* | |
* @since 1.0.0 | |
* @var string | |
*/ | |
private $file = ''; | |
/** | |
* Generates the main plugin instance. | |
* | |
* Insures that only one instance of the plugin exists in memory at any one | |
* time. Also prevents needing to define globals all over the place. | |
* | |
* @since 1.0.0 | |
* @static | |
* | |
* @param string $file Main plugin file. | |
* @return \Plugin_With_Checks The one true plugin class instance. | |
*/ | |
public static function instance( $file = null ) { | |
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Plugin_With_Checks ) ) { | |
self::$instance = new \Plugin_With_Checks; | |
self::$instance->file = $file; | |
self::$instance->setup_constants(); | |
self::$instance->includes(); | |
self::$instance->init(); | |
self::$instance->hooks(); | |
self::$instance->setup_objects(); | |
} | |
return self::$instance; | |
} | |
/** | |
* Throws an error on object clone. | |
* | |
* The whole idea of the singleton design pattern is that there is a single | |
* object therefore, we don't want the object to be cloned. | |
* | |
* @access protected | |
* @since 1.0.0 | |
* | |
* @return void | |
*/ | |
protected function __clone() { | |
// Cloning instances of the class is forbidden | |
_doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh? This object cannot be cloned.', 'plugin-with-checks' ), '1.0.0' ); | |
} | |
/** | |
* Disables unserializing of the class. | |
* | |
* @access protected | |
* @since 1.0.0 | |
* | |
* @return void | |
*/ | |
protected function __wakeup() { | |
// Unserializing instances of the class is forbidden | |
_doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh? This class cannot be unserialized.', 'plugin-with-checks' ), '1.0.0' ); | |
} | |
/** | |
* Sets up the class. | |
* | |
* @access private | |
* @since 1.0.0 | |
*/ | |
private function __construct() { | |
self::$instance = $this; | |
} | |
/** | |
* Resets the instance of the class. | |
* | |
* @access public | |
* @since 1.0.0 | |
* @static | |
*/ | |
public static function reset() { | |
self::$instance = null; | |
} | |
/** | |
* Setup plugin constants | |
* | |
* @access private | |
* @since 1.0.0 | |
* | |
* @return void | |
*/ | |
private function setup_constants() { | |
// Plugin version | |
if ( ! defined( 'PLUGIN_W_CHECKS_VERSION' ) ) { | |
define( 'PLUGIN_W_CHECKS_VERSION', $this->version ); | |
} | |
// Plugin Folder Path | |
if ( ! defined( 'PLUGIN_W_CHECKS_PLUGIN_DIR' ) ) { | |
define( 'PLUGIN_W_CHECKS_PLUGIN_DIR', plugin_dir_path( $this->file ) ); | |
} | |
// Plugin Folder URL | |
if ( ! defined( 'PLUGIN_W_CHECKS_PLUGIN_URL' ) ) { | |
define( 'PLUGIN_W_CHECKS_PLUGIN_URL', plugin_dir_url( $this->file ) ); | |
} | |
// Plugin Root File | |
if ( ! defined( 'PLUGIN_W_CHECKS_PLUGIN_FILE' ) ) { | |
define( 'PLUGIN_W_CHECKS_PLUGIN_FILE', $this->file ); | |
} | |
} | |
/** | |
* Include necessary files. | |
* | |
* @access private | |
* @since 1.0.0 | |
* | |
* @return void | |
*/ | |
private function includes() {} | |
/** | |
* Initializes the plugin. | |
* | |
* @since 1.0.0 | |
*/ | |
private function init() {} | |
/** | |
* Setup all objects | |
* | |
* @access public | |
* @since 1.0.0 | |
* @return void | |
*/ | |
public function setup_objects() {} | |
/** | |
* Sets up the default hooks and actions. | |
* | |
* @access private | |
* @since 1.0.0 | |
* | |
* @return void | |
*/ | |
private function hooks() {} | |
} | |
/** | |
* The main function responsible for returning the one true plugin class instance to functions everywhere. | |
* | |
* Use this function like you would a global variable, except without needing | |
* to declare the global. | |
* | |
* Example: <?php $plugin_with_checks = plugin_with_checks(); ?> | |
* | |
* @since 1.0.0 | |
* | |
* @return \Plugin_With_Checks The one true plugin class instance. | |
*/ | |
function plugin_with_checks() { | |
return Plugin_With_Checks::instance(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Sandhills Development Minimum Requirements API | |
* | |
* For use by Sandhills products and their extensions. | |
* | |
* @package SandhillsDev | |
* @subpackage Tools | |
* @copyright Copyright (c) 2021, Sandhills Development, LLC | |
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License | |
* @version 1.0.0 | |
*/ | |
// Exit if accessed directly | |
if ( ! defined( 'ABSPATH' ) ) exit; | |
/** | |
* Class used by AffiliateWP to enforce minimum requirements for itself and its add-ons. | |
* | |
* @since 1.0.0 | |
* @abstract | |
*/ | |
abstract class Sandhills_Requirements_Check { | |
/** | |
* Plugin base file. | |
* | |
* @since 1.0.0 | |
* @var string | |
*/ | |
private $file = ''; | |
/** | |
* Plugin basename. | |
* | |
* @since 1.0.0 | |
* @var string | |
*/ | |
private $base = ''; | |
/** | |
* Plugin slug. | |
* | |
* @since 1.0.0 | |
* @var string | |
*/ | |
protected $slug = 'sandhills-dev'; | |
/** | |
* Requirements array. | |
* | |
* @since 1.0.0 | |
* @var array[] | |
*/ | |
protected $requirements = array( | |
// PHP. | |
'php' => array( | |
'minimum' => '7.4', | |
'name' => 'PHP', | |
'exists' => true, | |
'current' => false, | |
'checked' => false, | |
'met' => false | |
), | |
// WordPress. | |
'wp' => array( | |
'minimum' => '5.0.0', | |
'name' => 'WordPress', | |
'exists' => true, | |
'current' => false, | |
'checked' => false, | |
'met' => false | |
), | |
); | |
/** | |
* Add-on requirements array. | |
* | |
* @since 1.0.0 | |
* @var array | |
*/ | |
protected $addon_requirements = array(); | |
/** | |
* Sets up the plugin requirements class. | |
* | |
* @since 1.0.0 | |
* | |
* @param string $file Main plugin file. | |
*/ | |
public function __construct( $file ) { | |
// Setup file & base. | |
$this->file = $file; | |
$this->base = plugin_basename( $this->get_file() ); | |
// Merge add-on requirements (if any). | |
$this->requirements = array_merge( $this->requirements, $this->addon_requirements ); | |
// Always load translations. | |
add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) ); | |
} | |
/** | |
* Retrieves the main plugin file. | |
* | |
* @since 1.0.0 | |
* | |
* @return string Main plugin file. | |
*/ | |
public function get_file() { | |
return $this->file; | |
} | |
/** | |
* (Maybe) loads the plugin. | |
* | |
* @since 1.0.0 | |
*/ | |
public function maybe_load() { | |
// Load or quit. | |
$this->met() ? $this->load() : $this->quit(); | |
} | |
/** | |
* Getter for requirements. | |
* | |
* The requirements class automatically supports checking wp- and php-keyed requirements. | |
* | |
* Add-ons can register custom requirements (or override defaults outlined in `$requirements`) by | |
* defining the `$addon_requirements` property in its own sub-class. If overriding default requirements, | |
* the same keys and metadata - save for the new version numbers - should be used. | |
* | |
* Custom requirement example: | |
* | |
* protected $addon_requirements = array( | |
* // AffiliateWP. | |
* 'affwp' => array( | |
* 'minimum' => '2.7', | |
* 'name' => 'AffiliateWP', | |
* 'exists' => true, | |
* 'current' => false, | |
* 'checked' => false, | |
* 'met' => false | |
* ), | |
* ); | |
* | |
* To hook up the version check, a corresponding method for each custom requirement MUST be added. | |
* The simplify this, the requirements class will automatically look for a method named | |
* "check_{requirement_name}". | |
* | |
* For example, for the 'affwp' requirement: | |
* | |
* public function check_affwp() { | |
* return get_option( 'affwp_version' ); | |
* } | |
* | |
* | |
* @since 1.0.0 | |
* | |
* @return array Plugin requirements. | |
*/ | |
protected function get_requirements() { | |
return $this->requirements; | |
} | |
/** | |
* Quits without loading the plugin. | |
* | |
* @since 1.0.0 | |
*/ | |
protected function quit() { | |
add_action( 'admin_head', array( $this, 'admin_head' ) ); | |
add_filter( "plugin_action_links_{$this->base}", array( $this, 'plugin_row_links' ) ); | |
add_action( "after_plugin_row_{$this->base}", array( $this, 'plugin_row_notice' ) ); | |
} | |
// | |
// Specific Methods | |
// | |
/** | |
* Handles actually loading the plugin. | |
* | |
* @since 1.0.0 | |
*/ | |
abstract protected function load(); | |
/** | |
* Install, usually on an activation hook. | |
* | |
* Note: A sub-class extension of this method is typically a good place to call a relevant | |
* install function or set the add-on version option directly. | |
* | |
* @since 1.0.0 | |
*/ | |
public function install() { | |
// Bootstrap to include all of the necessary files | |
$this->bootstrap(); | |
} | |
/** | |
* Bootstraps everything. | |
* | |
* @since 1.0.0 | |
*/ | |
public function bootstrap() { | |
\Sandhills_Dev::instance( $this->get_file() ); | |
} | |
/** | |
* Sets the plugin-specific URL for an external requirements page. | |
* | |
* @since 1.0.0 | |
* | |
* @return string Unmet requirements URL. | |
*/ | |
protected function unmet_requirements_url() { | |
return ''; | |
} | |
/** | |
* Sets the plugin-specific text to quickly explain what's wrong. | |
* | |
* @since 1.0.0 | |
* | |
* @return string Unmet requirements text. | |
*/ | |
private function unmet_requirements_text() { | |
esc_html_e( 'This plugin is not fully active.', 'sandhills-dev' ); | |
} | |
/** | |
* Sets the plugin-specific text to describe a single unmet requirement. | |
* | |
* @since 1.0.0 | |
* | |
* @return string Unment requirements description text. | |
*/ | |
private function unmet_requirements_description_text() { | |
return esc_html__( 'Requires %s (%s), but (%s) is installed.', 'sandhills-dev' ); | |
} | |
/** | |
* Sets the plugin-specific text to describe a single missing requirement. | |
* | |
* @since 1.0.0 | |
* | |
* @return string Unmet missing requirements text. | |
*/ | |
private function unmet_requirements_missing_text() { | |
return esc_html__( 'Requires %s (%s), but it appears to be missing.', 'sandhills-dev' ); | |
} | |
/** | |
* Sets the plugin-specific text used to link to an external requirements page. | |
* | |
* @since 1.0.0 | |
* | |
* @return string Unmet requirements link text. | |
*/ | |
private function unmet_requirements_link() { | |
return esc_html__( 'Requirements', 'sandhills-dev' ); | |
} | |
/** | |
* Sets the plugin-specific aria label text to describe the requirements link. | |
* | |
* @since 1.0.0 | |
* | |
* @return string Aria label text. | |
*/ | |
protected function unmet_requirements_label() { | |
return esc_html__( 'AffiliateWP Requirements', 'sandhills-dev' ); | |
} | |
/** | |
* Sets the plugin-specific text used in CSS to identify attribute IDs and classes. | |
* | |
* @since 1.0.0 | |
* | |
* @return string CSS selector. | |
*/ | |
protected function unmet_requirements_name() { | |
return 'affwp-requirements'; | |
} | |
// | |
// Agnostic Methods | |
// | |
/** | |
* Sets up the plugin-agnostic method to output the additional plugin row. | |
* | |
* @since 1.0.0 | |
*/ | |
public function plugin_row_notice() { | |
?><tr class="active <?php echo esc_attr( $this->unmet_requirements_name() ); ?>-row"> | |
<th class="check-column"> | |
<span class="dashicons dashicons-warning"></span> | |
</th> | |
<td class="column-primary"> | |
<?php $this->unmet_requirements_text(); ?> | |
</td> | |
<td class="column-description"> | |
<?php $this->unmet_requirements_description(); ?> | |
</td> | |
</tr><?php | |
} | |
/** | |
* Sets up the plugin-agnostic method used to output all unmet requirement information. | |
* | |
* @since 1.0.0 | |
*/ | |
private function unmet_requirements_description() { | |
foreach ( $this->requirements as $properties ) { | |
if ( empty( $properties['met'] ) ) { | |
$this->unmet_requirement_description( $properties ); | |
} | |
} | |
} | |
/** | |
* Sets up the plugin-agnostic method to output specific unmet requirement information | |
* | |
* @since 1.0.0 | |
* | |
* @param array $requirement Requirements array. | |
*/ | |
private function unmet_requirement_description( $requirement = array() ) { | |
// Requirement exists, but is out of date | |
if ( ! empty( $requirement['exists'] ) ) { | |
$text = sprintf( | |
$this->unmet_requirements_description_text(), | |
'<strong>' . esc_html( $requirement['name'] ) . '</strong>', | |
'<strong>' . esc_html( $requirement['minimum'] ) . '</strong>', | |
'<strong>' . esc_html( $requirement['current'] ) . '</strong>' | |
); | |
// Requirement could not be found | |
} else { | |
$text = sprintf( | |
$this->unmet_requirements_missing_text(), | |
'<strong>' . esc_html( $requirement['name'] ) . '</strong>', | |
'<strong>' . esc_html( $requirement['minimum'] ) . '</strong>' | |
); | |
} | |
// Output the description | |
echo '<p>' . $text . '</p>'; | |
} | |
/** | |
* Sets up the plugin-agnostic method to output unmet requirements styling | |
* | |
* @since 1.0.0 | |
*/ | |
public function admin_head() { | |
// Get the requirements row name | |
$name = $this->unmet_requirements_name(); ?> | |
<style id="<?php echo esc_attr( $name ); ?>"> | |
.plugins tr[data-plugin="<?php echo esc_html( $this->base ); ?>"] th, | |
.plugins tr[data-plugin="<?php echo esc_html( $this->base ); ?>"] td, | |
.plugins .<?php echo esc_html( $name ); ?>-row th, | |
.plugins .<?php echo esc_html( $name ); ?>-row td { | |
background: #fff5f5; | |
} | |
.plugins tr[data-plugin="<?php echo esc_html( $this->base ); ?>"] th { | |
box-shadow: none; | |
} | |
.plugins .<?php echo esc_html( $name ); ?>-row th span { | |
margin-left: 6px; | |
color: #dc3232; | |
} | |
.plugins tr[data-plugin="<?php echo esc_html( $this->base ); ?>"] th, | |
.plugins .<?php echo esc_html( $name ); ?>-row th.check-column { | |
border-left: 4px solid #dc3232 !important; | |
} | |
.plugins .<?php echo esc_html( $name ); ?>-row .column-description p { | |
margin: 0; | |
padding: 0; | |
} | |
.plugins .<?php echo esc_html( $name ); ?>-row .column-description p:not(:last-of-type) { | |
margin-bottom: 8px; | |
} | |
</style> | |
<?php | |
} | |
/** | |
* Sets up the plugin-agnostic method to add the "Requirements" link to row actions | |
* | |
* @since 1.0.0 | |
* | |
* @param array $links Requirement links. | |
* @return array Requirement links with markup. | |
*/ | |
public function plugin_row_links( $links = array() ) { | |
// Add the Requirements link | |
$links['requirements'] = | |
'<a href="' . esc_url( $this->unmet_requirements_url() ) . '" aria-label="' . esc_attr( $this->unmet_requirements_label() ) . '">' | |
. esc_html( $this->unmet_requirements_link() ) | |
. '</a>'; | |
// Return links with Requirements link | |
return $links; | |
} | |
// | |
// Checkers | |
// | |
/** | |
* Sets up the plugin-specific requirements checker. | |
* | |
* @since 1.0.0 | |
*/ | |
private function check() { | |
// Loop through requirements | |
foreach ( $this->requirements as $dependency => $properties ) { | |
if ( method_exists( $this, 'check_' . $dependency ) ) { | |
$version = call_user_func( array( $this, 'check_' . $dependency ) ); | |
} else { | |
$version = false; | |
} | |
// Merge to original array | |
if ( ! empty( $version ) ) { | |
$this->requirements[ $dependency ] = array_merge( $this->requirements[ $dependency ], array( | |
'current' => $version, | |
'checked' => true, | |
'met' => version_compare( $version, $properties['minimum'], '>=' ) | |
) ); | |
} | |
} | |
} | |
/** | |
* Checks the PHP version. | |
* | |
* @since 1.0.0 | |
* | |
* @return string PHP version. | |
*/ | |
protected function check_php() { | |
return phpversion(); | |
} | |
/** | |
* Checks the WordPress version. | |
* | |
* @since 1.0.0 | |
* | |
* @return string WordPress version. | |
*/ | |
protected function check_wp() { | |
return get_bloginfo( 'version' ); | |
} | |
/** | |
* Determines if all requirements been met. | |
* | |
* @since 1.0.0 | |
* | |
* @return bool True if met, otherwise false. | |
*/ | |
public function met() { | |
// Run the check | |
$this->check(); | |
// Default to true (any false below wins) | |
$retval = true; | |
$to_meet = wp_list_pluck( $this->requirements, 'met' ); | |
// Look for unmet dependencies, and exit if so | |
foreach ( $to_meet as $met ) { | |
if ( empty( $met ) ) { | |
$retval = false; | |
continue; | |
} | |
} | |
// Return | |
return $retval; | |
} | |
// | |
// Translations | |
// | |
/** | |
* Handles loading the plugin-specific text-domain. | |
* | |
* @since 1.0.0 | |
* | |
* @return void | |
*/ | |
public function load_textdomain() { | |
// Set filter for plugin's languages directory. | |
$lang_dir = dirname( plugin_basename( $this->get_file() ) ) . '/languages/'; | |
/** | |
* Filters the languages directory for AffiliateWP - Affiliate Portal plugin. | |
* | |
* @since 1.0 | |
* | |
* @param string $lang_dir Language directory. | |
*/ | |
$lang_dir = apply_filters( $this->base . '_languages_directory', $lang_dir ); | |
// Traditional WordPress plugin locale filter. | |
$locale = apply_filters( 'plugin_locale', get_locale(), $this->slug ); | |
$mofile = sprintf( '%1$s-%2$s.mo', $this->slug, $locale ); | |
// Setup paths to current locale file. | |
$mofile_local = $lang_dir . $mofile; | |
$mofile_global = WP_LANG_DIR . '/' . $lang_dir . '/' . $mofile; | |
if ( file_exists( $mofile_global ) ) { | |
// Look in global /wp-content/languages/{plugin_dir}/ folder. | |
load_textdomain( $this->slug, $mofile_global ); | |
} elseif ( file_exists( $mofile_local ) ) { | |
// Look in local /wp-content/plugins/{plugin_dir}/languages/ folder. | |
load_textdomain( $this->slug, $mofile_local ); | |
} else { | |
// Load the default language files. | |
load_plugin_textdomain( $this->slug, false, $lang_dir ); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: Plugin With Checks | |
* Plugin URI: https://sandhillsdev.com | |
* Description: Example plugin demonstrating stable partial activation and requirements checking. | |
* Author: Sandhills Development, LLC | |
* Author URI: https://sandhillsdev.com | |
* Version: 1.0.0 | |
* Text Domain: plugin-with-checks | |
* Domain Path: languages | |
*/ | |
if ( ! class_exists( 'Sandhills_Requirements_Check' ) ) { | |
require_once dirname( __FILE__ ) . '/class-sandhills-requirements-check.php'; | |
} | |
/** | |
* Class used to check requirements for and bootstrap the plugin. | |
* | |
* @since 1.0.0 | |
* | |
* @see Sandhills_Requirements_Check | |
*/ | |
class Plugin_With_Checks_Requirements extends Sandhills_Requirements_Check { | |
/** | |
* Plugin slug. | |
* | |
* @since 1.0.0 | |
* @var string | |
*/ | |
protected $slug = 'plugin-with-checks'; | |
/** | |
* Add-on requirements. | |
* | |
* @since 1.0.0 | |
* @var array[] | |
*/ | |
protected $addon_requirements = array( | |
// AffiliateWP. | |
'affwp' => array( | |
'minimum' => '2.7', | |
'name' => 'AffiliateWP', | |
'exists' => true, | |
'current' => false, | |
'checked' => false, | |
'met' => false | |
), | |
// WordPress. | |
'wp' => array( | |
'minimum' => '5.7.0', | |
'name' => 'WordPress', | |
'exists' => true, | |
'current' => false, | |
'checked' => false, | |
'met' => false | |
), | |
); | |
/** | |
* Checks the AffiliateWP version. | |
* | |
* @since 1.0.0 | |
* | |
* @return string AffiliateWP version. | |
*/ | |
protected function check_affwp() { | |
return get_option( 'affwp_version' ); | |
} | |
/** | |
* Bootstrap everything. | |
* | |
* @since 1.0.0 | |
*/ | |
public function bootstrap() { | |
\Plugin_With_Checks::instance( __FILE__ ); | |
} | |
/** | |
* Loads the add-on. | |
* | |
* @since 1.0.0 | |
*/ | |
protected function load() { | |
// Maybe include the bundled bootstrapper. | |
if ( ! class_exists( 'Plugin_With_Checks' ) ) { | |
require_once dirname( __FILE__ ) . '/class-plugin-with-checks.php'; | |
} | |
// Maybe hook-in the bootstrapper. | |
if ( class_exists( 'Plugin_With_Checks' ) ) { | |
add_action( 'plugins_loaded', array( $this, 'bootstrap' ), 100 ); | |
// Register the activation hook. | |
register_activation_hook( __FILE__, array( $this, 'install' ) ); | |
} | |
} | |
/** | |
* Install, usually on an activation hook. | |
* | |
* @since 1.0.0 | |
*/ | |
public function install() { | |
// Bootstrap to include all of the necessary files | |
$this->bootstrap(); | |
if ( defined( 'PLUGIN_W_CHECKS_VERSION' ) ) { | |
update_option( 'plugin_w_checks_version', PLUGIN_W_CHECKS_VERSION ); | |
} | |
} | |
/** | |
* Plugin-specific aria label text to describe the requirements link. | |
* | |
* @since 1.0.0 | |
* | |
* @return string Aria label text. | |
*/ | |
protected function unmet_requirements_label() { | |
return esc_html__( 'Plugin With Checks Requirements', 'plugin-with-checks' ); | |
} | |
/** | |
* Plugin-specific text used in CSS to identify attribute IDs and classes. | |
* | |
* @since 1.0.0 | |
* | |
* @return string CSS selector. | |
*/ | |
protected function unmet_requirements_name() { | |
return 'plugin-with-checks-requirements'; | |
} | |
/** | |
* Plugin specific URL for an external requirements page. | |
* | |
* @since 1.0.0 | |
* | |
* @return string Unmet requirements URL. | |
*/ | |
protected function unmet_requirements_url() { | |
return 'https://wiki-or-site.com/with/minimum/requirements'; | |
} | |
} | |
$requirements = new Plugin_With_Checks_Requirements( __FILE__ ); | |
$requirements->maybe_load(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment