Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
wpscholar committed May 21, 2020
0 parents commit b0a7f4c
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 0 deletions.
17 changes: 17 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "wp-forge/wp-upgrade-handler",
"description": "A drop-in library for handling upgrade routines in WordPress plugins and themes.",
"type": "library",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "Micah Wood",
"email": "[email protected]"
}
],
"autoload": {
"psr-4": {
"WP_Forge\\UpgradeHandler\\": "includes"
}
}
}
128 changes: 128 additions & 0 deletions includes/UpgradeHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

namespace WP_Forge\UpgradeHandler;

/**
* Class UpgradeHandler
*
* @package WP_Forge\UpgradeHandler
*/
class UpgradeHandler {

/**
* The previous version.
*
* @var string
*/
protected $old_version;

/**
* The current version.
*
* @var string
*/
protected $new_version;

/**
* The directory containing upgrade routines.
*
* @var string
*/
protected $upgrade_dir;

/**
* Class constructor.
*
* @param string $upgrade_dir The directory containing upgrade routines.
* @param string $old_version The previous version.
* @param string $new_version The current version.
*/
public function __construct( $upgrade_dir, $old_version, $new_version ) {
$this->upgrade_dir = $upgrade_dir;
$this->old_version = $old_version;
$this->new_version = $new_version;
}

/**
* Detect when an upgrade is necessary and run the updates.
*
* @return bool Whether or not an upgrade routine ran.
*/
public function maybe_upgrade() {
$should_upgrade = $this->should_upgrade();
if ( $should_upgrade ) {
$available_routines = $this->get_available_upgrade_routines();
$required_routines = $this->get_required_upgrade_routines( $available_routines );
$this->run_upgrade_routines( $required_routines );
}

return $should_upgrade;
}

/**
* Check if we should upgrade.
*
* @return bool
*/
public function should_upgrade() {
return $this->old_version !== $this->new_version;
}

/**
* Get a collection of available upgrade routines.
*
* @return array A collection of filepaths indexed by versions.
*/
public function get_available_upgrade_routines() {
$routines = array();
$filepaths = glob( rtrim( $this->upgrade_dir, '/' ) . '/*.php' );
if ( $filepaths ) {
$versions = str_replace( '.php', '', array_map( 'basename', $filepaths ) );
$routines = array_combine( $versions, $filepaths );
}

return $routines;
}

/**
* Get a collection of the required upgrade routines.
*
* @param array $available_routines A collection of available upgrade routines.
*
* @return array A collection of filepaths indexed by versions.
*/
public function get_required_upgrade_routines( array $available_routines ) {
$routines = array();
$required = array_filter( array_keys( $available_routines ), array( $this, 'filter_upgrade_routines' ) );
if ( $required ) {
$routines = array_intersect_key( $available_routines, array_combine( $required, $required ) );
}

return $routines;
}

/**
* Run an ordered set of upgrade routines.
*
* @param array $routines A collection of filepaths indexed by versions.
*/
public function run_upgrade_routines( array $routines ) {
foreach ( $routines as $file ) {
if ( file_exists( $file ) ) {
require $file;
}
}
}

/**
* Filter to find the versions for which we need to run an upgrade routine.
*
* @param string $version The current version.
*
* @return bool Whether or not to keep the routine.
*/
protected function filter_upgrade_routines( $version ) {
return version_compare( $this->old_version, $version, '<' ) && version_compare( $this->new_version, $version, '>=' );
}

}
59 changes: 59 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# WordPress Upgrade Handler

A drop-in library for handling upgrade routines in WordPress plugins and themes.

## Installation

- Run `composer require wp-forge/wp-upgrade-handler`
- Make sure you require the `vendor/autoload.php` file in your project.

## Usage

Here is an example of how to use this library in a WordPress plugin or theme:

```php
<?php

use WP_Forge\UpgradeHandler\UpgradeHandler;

// Define the current plugin version in the code
define( 'MY_PLUGIN_VERSION', '1.4.1' );

// Only handle upgrades in the admin
if ( is_admin() ) {

// Handle plugin upgrades
$upgrade_handler = new UpgradeHandler(
__DIR__ . '/upgrades', // Directory where upgrade routines live
get_option( 'my_plugin_version' ), // Old plugin version (from database)
MY_PLUGIN_VERSION // New plugin version (from code)
);

// Returns true if the old version doesn't match the new version
$did_upgrade = $upgrade_handler->maybe_upgrade();

if ( $did_upgrade ) {
// If an upgrade occurred, update the new version in the database to prevent running the routine(s) again.
update_option( 'my_plugin_version', MY_PLUGIN_VERSION, true );
}
}
```

If you just released version `1.4.1` of your plugin, but created upgrade routines for `1.4.1` and `1.3.9`, anyone upgrading from version `1.3.8` or earlier would have both of those upgrade routines run automatically. If someone is upgrading from version `1.3.9` or greater, then only the `1.4.1` upgrade routine would be run.

### Creating an Upgrade Routine
As an example, let's assume I just released version `1.4.1` of my plugin. The upgrade routine needs to change an option name in the database. All I need to do after adding the previous code from above is to create a file named `1.4.1.php` in my `upgrades` directory.

The following would be the contents of that file:

```php
<?php

// Rename 'old_option' to 'new_option', if necessary.
$old_option = get_option( 'old_option' );
if( $old_option ) {
update_option( 'new_option', get_option( 'old_option' ) );
delete_option( 'old_option' );
}

```

0 comments on commit b0a7f4c

Please sign in to comment.