Passed
Push — master ( 9315e3...6f7c4e )
by Paul
05:59
created

Migrate::currentVersion()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 0
dl 0
loc 12
ccs 0
cts 9
cp 0
crap 12
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules;
4
5
use DirectoryIterator;
6
use GeminiLabs\SiteReviews\Database;
7
use GeminiLabs\SiteReviews\Database\OptionManager;
8
use GeminiLabs\SiteReviews\Helper;
9
use GeminiLabs\SiteReviews\Helpers\Arr;
10
11
class Migrate
12
{
13
    /**
14
     * @var string
15
     */
16
    public $currentVersion;
17
18
    /**
19
     * @var string[]
20
     */
21
    public $migrations;
22
23
    /**
24
     * @var string
25
     */
26
    public $migrationsKey;
27
28
    public function __construct()
29
    {
30
        $this->currentVersion = $this->currentVersion();
31
        $this->migrations = $this->availableMigrations();
32
        $this->migrationsKey = glsr()->prefix.'migrations';
33
    }
34
35
    /**
36
     * @return bool
37
     */
38
    public function isMigrationNeeded()
39
    {
40
        if (empty($this->migrations)) {
41
            return false;
42
        }
43
        if (!empty($this->pendingMigrations())) {
44
            // check if this is a fresh install of the plugin
45
            return glsr(OptionManager::class)->get('version_upgraded_from') !== '0.0.0';
46
        }
47
        return false;
48
    }
49
50
    /**
51
     * @return void
52
     */
53
    public function reset()
54
    {
55
        delete_option($this->migrationsKey);
56
    }
57
58
    /**
59
     * @return void
60
     */
61
    public function run()
62
    {
63
        if (glsr(Database::class)->isMigrationNeeded()) {
64
            $this->runAll();
65
        } else {
66
            $this->runMigrations();
67
        }
68
    }
69
70
    /**
71
     * @return void
72
     */
73
    public function runAll()
74
    {
75
        $this->reset();
76
        $this->runMigrations();
77
    }
78
79
    /**
80
     * @return array
81
     */
82
    protected function availableMigrations()
83
    {
84
        $migrations = [];
85
        $dir = glsr()->path('plugin/Modules/Migrations');
86
        if (is_dir($dir)) {
87
            $iterator = new DirectoryIterator($dir);
88
            foreach ($iterator as $fileinfo) {
89
                if ($fileinfo->isFile()) {
90
                    $migrations[] = str_replace('.php', '', $fileinfo->getFilename());
91
                }
92
            }
93
            natsort($migrations);
94
        }
95
        return Arr::reindex($migrations);
96
    }
97
98
    /**
99
     * @return array
100
     */
101
    protected function createMigrations()
102
    {
103
        $migrations = [];
104
        foreach ($this->migrations as $migration) {
105
            $migrations[$migration] = false;
106
        }
107
        return $migrations;
108
    }
109
110
    /**
111
     * @return string
112
     */
113
    protected function currentVersion()
114
    {
115
        $fallback = '0.0.0';
116
        $majorVersions = range(glsr()->version('major'), 1);
117
        foreach ($majorVersions as $majorVersion) {
118
            $settings = get_option(OptionManager::databaseKey($majorVersion));
119
            $version = Arr::get($settings, 'version', $fallback);
120
            if (Helper::isGreaterThan($version, $fallback)) {
121
                return $version;
122
            }
123
        }
124
        return $fallback;
125
    }
126
127
    /**
128
     * @return string[]
129
     */
130
    protected function pendingMigrations(array $migrations = [])
131
    {
132
        if (empty($migrations)) {
133
            $migrations = $this->storedMigrations();
134
        }
135
        return array_keys(array_filter($migrations, function ($hasRun) {
136
            return !$hasRun;
137
        }));
138
    }
139
140
    /**
141
     * @return void
142
     */
143
    protected function runMigrations()
144
    {
145
        wp_raise_memory_limit('admin');
146
        $migrations = $this->storedMigrations();
147
        glsr()->action('migration/start', $migrations);
148
        foreach ($this->pendingMigrations($migrations) as $migration) {
149
            if (class_exists($classname = __NAMESPACE__.'\Migrations\\'.$migration)) {
150
                glsr($classname)->run();
151
                $migrations[$migration] = true;
152
                glsr_log()->debug("[$migration] has run successfully.");
153
            }
154
        }
155
        $this->storeMigrations($migrations);
156
        if ($this->currentVersion !== glsr()->version) {
157
            $this->updateVersionFrom($this->currentVersion);
158
        }
159
        glsr(OptionManager::class)->set('last_migration_run', current_time('timestamp'));
160
        glsr()->action('migration/end', $migrations);
161
    }
162
163
    /**
164
     * @return void
165
     */
166
    protected function storeMigrations(array $migrations)
167
    {
168
        update_option($this->migrationsKey, $migrations);
169
    }
170
171
    /**
172
     * @return array
173
     */
174
    protected function storedMigrations()
175
    {
176
        $migrations = Arr::consolidate(get_option($this->migrationsKey));
177
        if (!Arr::compare(array_keys($migrations), array_values($this->migrations))) {
178
            $newMigrations = $this->createMigrations();
179
            foreach ($newMigrations as $migration => &$hasRun) {
180
                $hasRun = Arr::get($migrations, $migration, false);
181
            }
182
            $migrations = $newMigrations;
183
            $this->storeMigrations($migrations);
184
        }
185
        return array_map('wp_validate_boolean', $migrations);
186
    }
187
188
    /**
189
     * @param string $previousVersion
190
     * @return void
191
     */
192
    protected function updateVersionFrom($previousVersion)
193
    {
194
        glsr(OptionManager::class)->set('version', glsr()->version);
195
        glsr(OptionManager::class)->set('version_upgraded_from', $previousVersion);
196
    }
197
}
198