Skip to content

Commit b0a7f4c

Browse files
committed
Initial commit
0 parents  commit b0a7f4c

File tree

3 files changed

+204
-0
lines changed

3 files changed

+204
-0
lines changed

composer.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "wp-forge/wp-upgrade-handler",
3+
"description": "A drop-in library for handling upgrade routines in WordPress plugins and themes.",
4+
"type": "library",
5+
"license": "GPL-2.0-or-later",
6+
"authors": [
7+
{
8+
"name": "Micah Wood",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"autoload": {
13+
"psr-4": {
14+
"WP_Forge\\UpgradeHandler\\": "includes"
15+
}
16+
}
17+
}

includes/UpgradeHandler.php

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
namespace WP_Forge\UpgradeHandler;
4+
5+
/**
6+
* Class UpgradeHandler
7+
*
8+
* @package WP_Forge\UpgradeHandler
9+
*/
10+
class UpgradeHandler {
11+
12+
/**
13+
* The previous version.
14+
*
15+
* @var string
16+
*/
17+
protected $old_version;
18+
19+
/**
20+
* The current version.
21+
*
22+
* @var string
23+
*/
24+
protected $new_version;
25+
26+
/**
27+
* The directory containing upgrade routines.
28+
*
29+
* @var string
30+
*/
31+
protected $upgrade_dir;
32+
33+
/**
34+
* Class constructor.
35+
*
36+
* @param string $upgrade_dir The directory containing upgrade routines.
37+
* @param string $old_version The previous version.
38+
* @param string $new_version The current version.
39+
*/
40+
public function __construct( $upgrade_dir, $old_version, $new_version ) {
41+
$this->upgrade_dir = $upgrade_dir;
42+
$this->old_version = $old_version;
43+
$this->new_version = $new_version;
44+
}
45+
46+
/**
47+
* Detect when an upgrade is necessary and run the updates.
48+
*
49+
* @return bool Whether or not an upgrade routine ran.
50+
*/
51+
public function maybe_upgrade() {
52+
$should_upgrade = $this->should_upgrade();
53+
if ( $should_upgrade ) {
54+
$available_routines = $this->get_available_upgrade_routines();
55+
$required_routines = $this->get_required_upgrade_routines( $available_routines );
56+
$this->run_upgrade_routines( $required_routines );
57+
}
58+
59+
return $should_upgrade;
60+
}
61+
62+
/**
63+
* Check if we should upgrade.
64+
*
65+
* @return bool
66+
*/
67+
public function should_upgrade() {
68+
return $this->old_version !== $this->new_version;
69+
}
70+
71+
/**
72+
* Get a collection of available upgrade routines.
73+
*
74+
* @return array A collection of filepaths indexed by versions.
75+
*/
76+
public function get_available_upgrade_routines() {
77+
$routines = array();
78+
$filepaths = glob( rtrim( $this->upgrade_dir, '/' ) . '/*.php' );
79+
if ( $filepaths ) {
80+
$versions = str_replace( '.php', '', array_map( 'basename', $filepaths ) );
81+
$routines = array_combine( $versions, $filepaths );
82+
}
83+
84+
return $routines;
85+
}
86+
87+
/**
88+
* Get a collection of the required upgrade routines.
89+
*
90+
* @param array $available_routines A collection of available upgrade routines.
91+
*
92+
* @return array A collection of filepaths indexed by versions.
93+
*/
94+
public function get_required_upgrade_routines( array $available_routines ) {
95+
$routines = array();
96+
$required = array_filter( array_keys( $available_routines ), array( $this, 'filter_upgrade_routines' ) );
97+
if ( $required ) {
98+
$routines = array_intersect_key( $available_routines, array_combine( $required, $required ) );
99+
}
100+
101+
return $routines;
102+
}
103+
104+
/**
105+
* Run an ordered set of upgrade routines.
106+
*
107+
* @param array $routines A collection of filepaths indexed by versions.
108+
*/
109+
public function run_upgrade_routines( array $routines ) {
110+
foreach ( $routines as $file ) {
111+
if ( file_exists( $file ) ) {
112+
require $file;
113+
}
114+
}
115+
}
116+
117+
/**
118+
* Filter to find the versions for which we need to run an upgrade routine.
119+
*
120+
* @param string $version The current version.
121+
*
122+
* @return bool Whether or not to keep the routine.
123+
*/
124+
protected function filter_upgrade_routines( $version ) {
125+
return version_compare( $this->old_version, $version, '<' ) && version_compare( $this->new_version, $version, '>=' );
126+
}
127+
128+
}

readme.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# WordPress Upgrade Handler
2+
3+
A drop-in library for handling upgrade routines in WordPress plugins and themes.
4+
5+
## Installation
6+
7+
- Run `composer require wp-forge/wp-upgrade-handler`
8+
- Make sure you require the `vendor/autoload.php` file in your project.
9+
10+
## Usage
11+
12+
Here is an example of how to use this library in a WordPress plugin or theme:
13+
14+
```php
15+
<?php
16+
17+
use WP_Forge\UpgradeHandler\UpgradeHandler;
18+
19+
// Define the current plugin version in the code
20+
define( 'MY_PLUGIN_VERSION', '1.4.1' );
21+
22+
// Only handle upgrades in the admin
23+
if ( is_admin() ) {
24+
25+
// Handle plugin upgrades
26+
$upgrade_handler = new UpgradeHandler(
27+
__DIR__ . '/upgrades', // Directory where upgrade routines live
28+
get_option( 'my_plugin_version' ), // Old plugin version (from database)
29+
MY_PLUGIN_VERSION // New plugin version (from code)
30+
);
31+
32+
// Returns true if the old version doesn't match the new version
33+
$did_upgrade = $upgrade_handler->maybe_upgrade();
34+
35+
if ( $did_upgrade ) {
36+
// If an upgrade occurred, update the new version in the database to prevent running the routine(s) again.
37+
update_option( 'my_plugin_version', MY_PLUGIN_VERSION, true );
38+
}
39+
}
40+
```
41+
42+
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.
43+
44+
### Creating an Upgrade Routine
45+
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.
46+
47+
The following would be the contents of that file:
48+
49+
```php
50+
<?php
51+
52+
// Rename 'old_option' to 'new_option', if necessary.
53+
$old_option = get_option( 'old_option' );
54+
if( $old_option ) {
55+
update_option( 'new_option', get_option( 'old_option' ) );
56+
delete_option( 'old_option' );
57+
}
58+
59+
```

0 commit comments

Comments
 (0)