1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Framework\Module\Plugin;
use Magento\Framework\Cache\FrontendInterface as FrontendCacheInterface;
use Magento\Framework\Module\DbVersionInfo;
use Magento\Framework\App\FrontController;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Phrase;
/**
* Validation of DB up to date state
*/
class DbStatusValidator
{
/**
* @var FrontendCacheInterface
*/
private $cache;
/**
* @var DbVersionInfo
*/
private $dbVersionInfo;
/**
* @param FrontendCacheInterface $cache
* @param DbVersionInfo $dbVersionInfo
*/
public function __construct(FrontendCacheInterface $cache, DbVersionInfo $dbVersionInfo)
{
$this->cache = $cache;
$this->dbVersionInfo = $dbVersionInfo;
}
/**
* Perform check if DB is up to date
*
* @param FrontController $subject
* @param RequestInterface $request
* @return void
* @throws LocalizedException
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function beforeDispatch(FrontController $subject, RequestInterface $request)
{
if (!$this->cache->load('db_is_up_to_date')) {
list($versionTooLowErrors, $versionTooHighErrors) = array_values($this->getGroupedDbVersionErrors());
if ($versionTooHighErrors) {
$message = 'Please update your modules: '
. "Run \"composer install\" from the Magento root directory.\n"
. "The following modules are outdated:\n%1";
throw new LocalizedException(
new Phrase($message, [implode("\n", $this->formatVersionTooHighErrors($versionTooHighErrors))])
);
} elseif ($versionTooLowErrors) {
$message = 'Please upgrade your database: '
. "Run \"bin/magento setup:upgrade\" from the Magento root directory.\n"
. "The following modules are outdated:\n%1";
throw new LocalizedException(
new Phrase($message, [implode("\n", $this->formatVersionTooLowErrors($versionTooLowErrors))])
);
} else {
$this->cache->save('true', 'db_is_up_to_date');
}
}
}
/**
* Format each error in the error data from getOutOfDataDbErrors into a single message
*
* @param array $errorsData array of error data from getOutOfDateDbErrors
* @return array Messages that can be used to log the error
*/
private function formatVersionTooLowErrors($errorsData)
{
$formattedErrors = [];
foreach ($errorsData as $error) {
$formattedErrors[] = $error[DbVersionInfo::KEY_MODULE] . ' ' . $error[DbVersionInfo::KEY_TYPE]
. ': current version - ' . $error[DbVersionInfo::KEY_CURRENT]
. ', required version - ' . $error[DbVersionInfo::KEY_REQUIRED];
}
return $formattedErrors;
}
/**
* Format each error in the error data from getOutOfDataDbErrors into a single message
*
* @param array $errorsData array of error data from getOutOfDateDbErrors
* @return array Messages that can be used to log the error
*/
private function formatVersionTooHighErrors($errorsData)
{
$formattedErrors = [];
foreach ($errorsData as $error) {
$formattedErrors[] = $error[DbVersionInfo::KEY_MODULE] . ' ' . $error[DbVersionInfo::KEY_TYPE]
. ': code version - ' . $error[DbVersionInfo::KEY_REQUIRED]
. ', database version - ' . $error[DbVersionInfo::KEY_CURRENT];
}
return $formattedErrors;
}
/**
* Return DB version errors grouped by 'version_too_low' and 'version_too_high'
*
* @return mixed
*/
private function getGroupedDbVersionErrors()
{
$allDbVersionErrors = $this->dbVersionInfo->getDbVersionErrors();
return array_reduce(
(array)$allDbVersionErrors,
function ($carry, $item) {
if ($item[DbVersionInfo::KEY_CURRENT] === 'none'
|| version_compare($item[DbVersionInfo::KEY_CURRENT], $item[DbVersionInfo::KEY_REQUIRED], '<')
) {
$carry['version_too_low'][] = $item;
} else {
$carry['version_too_high'][] = $item;
}
return $carry;
},
[
'version_too_low' => [],
'version_too_high' => [],
]
);
}
}