WPupdatePHP / wp-update-php

Library to be bundled with WordPress plugins to enforce users to upgrade to supported PHP versions.
GNU General Public License v2.0
79 stars 11 forks source link

Multiple classes #35

Closed GaryJones closed 7 years ago

GaryJones commented 9 years ago

More of a thought dump, but one could consider something slightly more OOP: having different types of admin notices as polymorphism with an interface, and individual admin notices as Value Objects.

<?php
/**
 * WPUpdatePHP
 *
 * @package   WPUpdatePhp
 * @author    Coen Jacobs
 * @license   GPLv3
 * @link      https://github.com/WPupdatePHP/wp-update-php
 */

/**
 * WPUpdatePhp.
 */
class WPUpdatePhp {
    /** @var string */
    private $minimum_version;

    /** @var string */
    private $recommended_version;

    /** @var string */
    private $plugin_name = '';

    /**
     * @param string $minimum_version     Minimum version of PHP.
     * @param string $recommended_version Recommended version of PHP.
     */
    public function __construct( $minimum_version, $recommended_version = null ) {
        $this->minimum_version     = $minimum_version;
        $this->recommended_version = $recommended_version;
    }

    /**
     * Set the plugin name for the admin notice.
     *
     * @param string $name Name of the plugin to be used in admin notices.
     */
    public function set_plugin_name( $name ) {
        $this->plugin_name = $name;
    }

    /**
     * Check given PHP version against minimum required version.
     *
     * @param string $version Optional. PHP version to check against.
     *                        Default is the current PHP version as a string in
     *                        "major.minor.release[extra]" notation.
     * @return bool True if supplied PHP version meets minimum required version.
     */
    public function does_it_meet_required_php_version( $version = PHP_VERSION ) {
        if ( $this->version_passes_requirement( $this->minimum_version, $version ) ) {
            return true;
        }

        $notice = new WPUpdatePhp_Notice_Minimum( $version, $this->plugin_name );
        $this->load_version_notice( array( $notice, 'display' ) );

        return false;
    }

    /**
     * Check given PHP version against recommended version.
     *
     * @param string $version Optional. PHP version to check against.
     *                        Default is the current PHP version as a string in
     *                        "major.minor.release[extra]" notation.
     * @return bool True if supplied PHP version meets recommended version.
     */
    public function does_it_meet_recommended_php_version( $version = PHP_VERSION ) {
        if ( $this->version_passes_requirement( $this->recommended_version, $version ) ) {
            return true;
        }

        $notice = new WPUpdatePhp_Notice_Recommended( $version, $this->plugin_name );
        $this->load_version_notice( array( $notice, 'display' ) );

        return false;
    }

    /**
     * Check that one PHP version is less than or equal to another.
     *
     * @param string $requirement The baseline version of PHP.
     * @param string $version     The given version of PHP.
     * @return bool True if the requirement is less than or equal to given version.
     */
    private function version_passes_requirement( $requirement, $version ) {
        return version_compare( $requirement, $version, '<=' );
    }

    /**
     * Conditionally hook in an admin notice.
     *
     * @param callable $callback Callable that displays admin notice.
     */
    private function load_version_notice( $callback ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
            add_action( 'admin_notices', $callback );
            add_action( 'network_admin_notices', $callback );
        }
    }
}

/**
 * Abstract admin notice.
 */
abstract class WPUpdatePhp_Notice {
    /** @var string */
    protected $version;

    /** @var string */
    protected $plugin_name;

    /** @var string */
    protected $url = 'http://www.wpupdatephp.com/update/';

    /**
     * @param string $version     Version of PHP for the admin notice.
     * @param string $plugin_name Plugin name.
     */
    public function __construct( $version, $plugin_name = null ) {
        $this->version     = $version;
        $this->plugin_name = $plugin_name;
    }

    /**
     * Get admin notice.
     *
     * @return string Admin notice markup.
     */
    public function display() {
        return '<div class="error">' . $this->get_notice_text() . '</div>';
    }
}

/**
 * Admin notice interface.
 */
interface WPUpdatePhp_Notice_Interface {
    /**
     * Get notice text.
     *
     * @return string Admin notice text.
     */
    protected function get_notice_text();
}

/**
 * Minimum required PHP version admin notice.
 */
class WPUpdatePhp_Notice_Minimum extends WPUpdatePhp_Notice implements WPUpdatePhp_Notice_Interface {
    /**
     * Get notice text.
     *
     * @return string Admin notice text.
     */
    protected function get_notice_text() {
        $plugin_name = $this->plugin_name ? $this->plugin_name : 'this plugin';

        return '<p>Unfortunately, ' . $plugin_name . ' cannot run on PHP versions older than ' . $this->version . '. Read more information about <a href="' . esc_url( $this->url ) . '">how you can update</a>.</p>';
    }
}

/**
 * Recommended PHP version admin notice.
 */
class WPUpdatePhp_Notice_Recommended extends WPUpdatePhp_Notice implements WPUpdatePhp_Notice_Interface {
    /**
     * Get notice text.
     *
     * @return string Admin notice text.
     */
    protected function get_notice_text() {
        $plugin_name = $this->plugin_name ? $this->plugin_name : 'This plugin';

        return '<p>' . $plugin_name . ' recommends a PHP version higher than ' . $this->version . '. Read more information about <a href="' . esc_url( $this->url ) . '">how you can update</a>.</p>';
    }
}

It could definitely be taken further - fallback_plugin_name() in the notice interface and types for instance.

Use, abuse or ignore as you see fit :-)

coenjacobs commented 9 years ago

I'm absolutely keen on doing this. The reason why I wanted to leave it all in one class at first, was because there are so many developers out there who haven't mastered Composer yet. It might seem like a daunting task to some, if they have to use Composer (or manually download) to get all these files. After rethinking this, I think the pros outweigh the cons and so I'm happy to add this for v1.2.0.

Some important bits to think about:

coenjacobs commented 7 years ago

Thanks @GaryJones, finally finished this up in #41.

Feel free to check out the big-2.0-release branch to test and see how it looks now. :+1: