| 1 |
<?php |
| 2 |
|
| 3 |
/** |
| 4 |
* Class specifically to update/migrate database values |
| 5 |
* that may have changed over time. Use the version of |
| 6 |
* the plugin that we are migrating from, not the |
| 7 |
* version of the plugin that we are migrating to. |
| 8 |
*/ |
| 9 |
|
| 10 |
namespace Extendify\Shared\Services; |
| 11 |
|
| 12 |
defined('ABSPATH') || die('No direct access.'); |
| 13 |
|
| 14 |
/** |
| 15 |
* Migration class. |
| 16 |
*/ |
| 17 |
|
| 18 |
class VersionMigrator |
| 19 |
{ |
| 20 |
/** |
| 21 |
* Initialize the class. |
| 22 |
* |
| 23 |
* @return void |
| 24 |
*/ |
| 25 |
public function __construct() |
| 26 |
{ |
| 27 |
$targetVersion = $this->getVersion(); |
| 28 |
$migrationMethods = $this->getMigrationMethods(); |
| 29 |
$previousMigrations = get_option('extendify_run_migrations', []); |
| 30 |
|
| 31 |
foreach ($migrationMethods as $method) { |
| 32 |
$version = $this->extractVersion($method); |
| 33 |
|
| 34 |
// Stop if we've reached a version beyond our target. |
| 35 |
if (version_compare($version, $targetVersion) > 0) { |
| 36 |
break; |
| 37 |
} |
| 38 |
|
| 39 |
// Skip if this migration has already been run. |
| 40 |
if (isset($previousMigrations[$version])) { |
| 41 |
continue; |
| 42 |
} |
| 43 |
|
| 44 |
$this->$method(); |
| 45 |
$previousMigrations[$version] = true; |
| 46 |
update_option('extendify_run_migrations', $previousMigrations); |
| 47 |
}//end foreach |
| 48 |
} |
| 49 |
|
| 50 |
/** |
| 51 |
* This method fixes a math bug in the usage data in the database. |
| 52 |
* |
| 53 |
* @return void |
| 54 |
*/ |
| 55 |
private function migrate_1_14_2_fixUsageMathBug() // phpcs:ignore |
| 56 |
{ |
| 57 |
$normalizeMathBug = function ($number) { |
| 58 |
if (is_int($number)) { |
| 59 |
return $number; |
| 60 |
} |
| 61 |
|
| 62 |
$count = substr_count((string) $number, '1'); |
| 63 |
$subNumbers = substr($number, 0, -$count); |
| 64 |
return ((int) $subNumbers + $count); |
| 65 |
}; |
| 66 |
|
| 67 |
$librarySiteData = get_option('extendify_library_site_data', []); |
| 68 |
$state = ($librarySiteData['state'] ?? []); |
| 69 |
if (!empty($state['totalImports'])) { |
| 70 |
$state['totalImports'] = $normalizeMathBug($state['totalImports']); |
| 71 |
$librarySiteData['state'] = $state; |
| 72 |
update_option('extendify_library_site_data', Sanitizer::sanitizeArray($librarySiteData)); |
| 73 |
} |
| 74 |
|
| 75 |
$toursData = get_option('extendify_assist_tour_progress', []); |
| 76 |
$state = ($toursData['state']['progress'] ?? null); |
| 77 |
if ($state) { |
| 78 |
$state = array_map(function ($progress) use ($normalizeMathBug) { |
| 79 |
$progress['openedCount'] = $normalizeMathBug($progress['openedCount']); |
| 80 |
$progress['closedManuallyCount'] = $normalizeMathBug($progress['closedManuallyCount']); |
| 81 |
$progress['completedCount'] = $normalizeMathBug($progress['completedCount']); |
| 82 |
return $progress; |
| 83 |
}, $state); |
| 84 |
|
| 85 |
$toursData['state']['progress'] = $state; |
| 86 |
update_option('extendify_assist_tour_progress', Sanitizer::sanitizeArray($toursData)); |
| 87 |
} |
| 88 |
|
| 89 |
// The following all have a property 'count'. |
| 90 |
$normalizeCount = function ($viewed) use ($normalizeMathBug) { |
| 91 |
$viewed['count'] = $normalizeMathBug($viewed['count']); |
| 92 |
return $viewed; |
| 93 |
}; |
| 94 |
|
| 95 |
$kbData = get_option('extendify_assist_support_articles', []); |
| 96 |
$state = ($kbData['state']['viewedArticles'] ?? null); |
| 97 |
if ($state) { |
| 98 |
$kbData['state']['viewedArticles'] = array_map($normalizeCount, $state); |
| 99 |
update_option('extendify_assist_support_articles', Sanitizer::sanitizeArray($kbData)); |
| 100 |
} |
| 101 |
|
| 102 |
// Each of the routers have the same signature. |
| 103 |
foreach (['assist', 'help_center', 'draft'] as $key) { |
| 104 |
$router = get_option("extendify_{$key}_router", []); |
| 105 |
$state = ($router['state']['viewedPages'] ?? null); |
| 106 |
if ($state) { |
| 107 |
$router['state']['viewedPages'] = array_map($normalizeCount, $state); |
| 108 |
update_option("extendify_{$key}_router", Sanitizer::sanitizeArray($router)); |
| 109 |
} |
| 110 |
} |
| 111 |
} |
| 112 |
|
| 113 |
/** |
| 114 |
* Get the plugin version. |
| 115 |
* |
| 116 |
* @return string |
| 117 |
*/ |
| 118 |
private function getVersion() |
| 119 |
{ |
| 120 |
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents |
| 121 |
$readme = file_get_contents(EXTENDIFY_PATH . 'readme.txt'); |
| 122 |
preg_match('/Stable tag: ([0-9.:]+)/', $readme, $matches); |
| 123 |
return ($matches[1] ?? '0.0.0'); |
| 124 |
} |
| 125 |
|
| 126 |
/** |
| 127 |
* Get migration methods. |
| 128 |
* |
| 129 |
* @return array |
| 130 |
*/ |
| 131 |
private function getMigrationMethods(): array |
| 132 |
{ |
| 133 |
$methods = get_class_methods($this); |
| 134 |
$migrationMethods = array_filter($methods, function ($method) { |
| 135 |
return strpos($method, 'migrate_') === 0; |
| 136 |
}); |
| 137 |
sort($migrationMethods); |
| 138 |
|
| 139 |
return $migrationMethods; |
| 140 |
} |
| 141 |
|
| 142 |
/** |
| 143 |
* Extract version from the method name. |
| 144 |
* |
| 145 |
* @param string $method The method name. |
| 146 |
* @return string |
| 147 |
*/ |
| 148 |
private function extractVersion($method) |
| 149 |
{ |
| 150 |
preg_match('/^migrate_(\d+)_(\d+)_(\d+)/', $method, $matches); |
| 151 |
return $matches ? "{$matches[1]}.{$matches[2]}.{$matches[3]}" : '0.0.0'; |
| 152 |
} |
| 153 |
} |
| 154 |
|