11<?php
22/**
3- * Database Class
3+ * Upgrade Class
44 *
55 * @package Webmention
66 */
77namespace Webmention ;
88
99/**
10- * Database Class
10+ * Upgrade Class
1111 *
1212 * @package Webmention
1313 */
14- class DB {
14+ class Upgrade {
1515 /**
16- * Which internal datastructure version we are running on.
17- *
18- * @var int
16+ * Initialize the upgrade class.
1917 */
20- private static $ target_version = '1.0.1 ' ;
21-
22- public static function get_target_version () {
23- return self ::$ target_version ;
18+ public static function init () {
19+ add_action ( 'init ' , array ( self ::class, 'maybe_upgrade ' ) );
2420 }
2521
22+ /**
23+ * Get the current version.
24+ *
25+ * @return int
26+ */
2627 public static function get_version () {
2728 return get_option ( 'webmention_db_version ' , 0 );
2829 }
2930
3031 /**
3132 * Whether the database structure is up to date.
3233 *
33- * @return bool
34+ * @return bool True if the database structure is up to date, false otherwise.
3435 */
3536 public static function is_latest_version () {
36- return (bool ) version_compare (
37+ return (bool ) \ version_compare (
3738 self ::get_version (),
38- self :: get_target_version () ,
39+ WEBMENTION_VERSION ,
3940 '== '
4041 );
4142 }
4243
44+ /**
45+ * Locks the database migration process to prevent simultaneous migrations.
46+ *
47+ * @return bool|int True if the lock was successful, timestamp of existing lock otherwise.
48+ */
49+ public static function lock () {
50+ global $ wpdb ;
51+
52+ // Try to lock.
53+ $ lock_result = (bool ) $ wpdb ->query ( $ wpdb ->prepare ( "INSERT IGNORE INTO ` $ wpdb ->options ` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'no') /* LOCK */ " , 'webmention_migration_lock ' , \time () ) ); // phpcs:ignore WordPress.DB
54+
55+ if ( ! $ lock_result ) {
56+ $ lock_result = \get_option ( 'webmention_migration_lock ' );
57+ }
58+
59+ return $ lock_result ;
60+ }
61+
62+ /**
63+ * Unlocks the database migration process.
64+ */
65+ public static function unlock () {
66+ \delete_option ( 'webmention_migration_lock ' );
67+ }
68+
69+ /**
70+ * Whether the database migration process is locked.
71+ *
72+ * @return boolean
73+ */
74+ public static function is_locked () {
75+ $ lock = \get_option ( 'webmention_migration_lock ' );
76+
77+ if ( ! $ lock ) {
78+ return false ;
79+ }
80+
81+ $ lock = (int ) $ lock ;
82+
83+ if ( $ lock < \time () - 1800 ) {
84+ self ::unlock ();
85+ return false ;
86+ }
87+
88+ return true ;
89+ }
90+
4391 /**
4492 * Updates the database structure if necessary.
4593 */
46- public static function update_database () {
94+ public static function maybe_upgrade () {
4795 if ( self ::is_latest_version () ) {
4896 return ;
4997 }
5098
99+ if ( self ::is_locked () ) {
100+ return ;
101+ }
102+
103+ self ::lock ();
104+
51105 $ version_from_db = self ::get_version ();
52106
53107 if ( version_compare ( $ version_from_db , '1.0.0 ' , '< ' ) ) {
@@ -57,7 +111,17 @@ public static function update_database() {
57111 self ::migrate_to_1_0_1 ();
58112 }
59113
60- update_option ( 'webmention_db_version ' , self ::$ target_version );
114+ /**
115+ * Fires when the system has to be migrated.
116+ *
117+ * @param string $version_from_db The version from which to migrate.
118+ * @param string $target_version The target version to migrate to.
119+ */
120+ \do_action ( 'webmention_migrate ' , $ version_from_db , WEBMENTION_VERSION );
121+
122+ \update_option ( 'webmention_db_version ' , WEBMENTION_VERSION );
123+
124+ self ::unlock ();
61125 }
62126
63127 /**
0 commit comments