PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.1.0
WP 2FA – Two-factor authentication for WordPress v2.1.0
4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Utils / AbstractMigration.php
wp-2fa / includes / classes / Utils Last commit date
AbstractMigration.php 4 years ago DateTimeUtils.php 4 years ago Debugging.php 5 years ago GenerateModal.php 4 years ago Migration.php 4 years ago RequestUtils.php 4 years ago SettingsUtils.php 4 years ago UserUtils.php 4 years ago index.php 5 years ago
AbstractMigration.php
180 lines
1 <?php
2 namespace WP2FA\Utils;
3
4 use WP2FA\Utils\SettingsUtils as SettingsUtils;
5
6 defined( 'ABSPATH' ) || exit; // Exit if accessed directly
7
8 /**
9 * Abstract AMigration class
10 */
11 if ( ! class_exists( '\WP2FA\Utils\AbstractMigration' ) ) {
12
13 /**
14 * Utility class to ease the migration process.
15 *
16 * Every migration must go in its own method
17 * The naming convention is migrateUpTo_XXX where XXX is the number of the version,
18 * format is numbers only.
19 * Example: migration for version upto 1.4 must be in migrateUpTo_14 method
20 *
21 * The numbers in the names of the methods must have exact numbers count as in the selected
22 * version in use, even if there are silent numbers for some of the major versions as 1, 2, 3 etc. (the .0.0 is skipped / silent)
23 * Example:
24 * - if X.X.X is selected for version number, then for version 1.1 method must have "...migrateUpTo_110..." in its name
25 * - if X.X is selected for version number, then for version 1, method must have "...migrateUpTo_10..." in its name
26 *
27 * Note: you can add prefix to the migration method, if that is necessary, but "migrateUpTo_" is a must -
28 * the name must contain that @see getAllMigrationMethodsAsNumbers of that class.
29 * For version extraction the number following the last '_' will be used
30 * TODO: the mandatory part of the method name can be a setting in the class, but is that a good idea?
31 *
32 * Note: order of the methods is not preserved - version numbers will be used for ordering
33 *
34 * @package WP2FA\Utils
35 * @since 1.6
36 */
37 class AbstractMigration {
38
39 /**
40 * Extracted version from the DB (WP option)
41 */
42 protected static $storedVersion = '';
43
44 /**
45 * The name of the option from which we should extact version
46 * Note: version is expected in version format - 1.0.0; 1; 1.0; 1.0.0.0
47 * Note: only numbers will be processed
48 */
49 protected static $versionOptionName = '';
50
51 /**
52 * The constant name where the plugin version is stored
53 * Note: version is expected in version format - 1.0.0; 1; 1.0; 1.0.0.0
54 * Note: only numbers will be processed
55 */
56 protected static $constNameOfPluginVersion = '';
57
58 /**
59 * Used for adding proper pads for the missing numbers
60 * Version number format used here depends on selection for how many numbers will be used for representing version
61 *
62 * for X.X use 2;
63 * for X.X.X use 3;
64 * for X.X.X.X use 4;
65 *
66 * etc.
67 *
68 * Example: if selected version format is X.X.X that means that 3 digits are used for versioning.
69 * And current version is stored as 2 (no suffix 0.0) that means that it will be normalized as 200.
70 */
71 protected static $padLength = 3;
72
73 /**
74 * Collects all the migration methods which needs to be executed in order and executes them
75 *
76 * @return void
77 */
78 public static function migrate() {
79
80 if ( version_compare( static::getStoredVersion(), \constant( static::$constNameOfPluginVersion ), '<' ) ) {
81
82 $storedVersionAsNumber = static::normalizeVersion( static::getStoredVersion() );
83 $targetVersionAsNumber = static::normalizeVersion( \constant( static::$constNameOfPluginVersion ) );
84 $methodAsVersionNumbers = static::getAllMigrationMethodsAsNumbers();
85
86 $migrateMethods = array_filter(
87 $methodAsVersionNumbers,
88 function( $method, $key ) use ( &$storedVersionAsNumber, &$targetVersionAsNumber ) {
89 if ( $targetVersionAsNumber > $storedVersionAsNumber ) {
90 return ( in_array( $key, range( $storedVersionAsNumber, $targetVersionAsNumber ) ) );
91 }
92
93 return false;
94 },
95 ARRAY_FILTER_USE_BOTH
96 );
97
98 if ( ! empty( $migrateMethods ) ) {
99 \ksort( $migrateMethods );
100 foreach ( $migrateMethods as $method ) {
101 static::{$method}();
102 }
103 }
104
105 self::storeUpdatedVersion();
106 }
107 }
108
109 /**
110 * Extracts currently stored version from the DB
111 *
112 * @return string
113 */
114 private static function getStoredVersion() {
115
116 if ( '' === trim( static::$storedVersion ) ) {
117 static::$storedVersion = SettingsUtils::get_option( static::$versionOptionName, '0.0.0' );
118 }
119
120 return static::$storedVersion;
121 }
122
123 /**
124 * Stores the version to which we migrated
125 *
126 * @return void
127 */
128 private static function storeUpdatedVersion() {
129 SettingsUtils::update_option( static::$versionOptionName, \constant( static::$constNameOfPluginVersion ) );
130 }
131
132 /**
133 * Normalized the version numbers to numbers
134 *
135 * Version format is expected to be as follows:
136 * X.X.X
137 *
138 * All non numeric values will be removed from the version string
139 *
140 * Note: version is expected in version format - 1.0.0; 1; 1.0; 1.0.0.0
141 * Note: only numbers will be processed
142 *
143 * @param string $version
144 *
145 * @return string
146 */
147 private static function normalizeVersion( string $version ) {
148 $versionAsNumber = (int) filter_var( $version, FILTER_SANITIZE_NUMBER_INT );
149
150 if ( self::$padLength > strlen( $versionAsNumber ) ) {
151 $versionAsNumber = str_pad( $versionAsNumber, static::$padLength, '0', STR_PAD_RIGHT );
152 }
153
154 return $versionAsNumber;
155 }
156
157 /**
158 * Collects all the migration methods from the class and stores them in the array
159 * Array is in following format:
160 * key - number of the version
161 * value - name of the method
162 *
163 * @return array
164 */
165 private static function getAllMigrationMethodsAsNumbers() {
166 $classMethods = \get_class_methods( get_called_class() );
167
168 $methodAsVersionNumbers = [];
169 foreach ( $classMethods as $method ) {
170 if ( false !== \strpos( $method, 'migrateUpTo_' ) ) {
171 $ver = \substr( $method, \strrpos( $method, '_' ) + 1, \strlen( $method ) );
172 $methodAsVersionNumbers[ $ver ] = $method;
173 }
174 }
175
176 return $methodAsVersionNumbers;
177 }
178 }
179 }
180