DbStatusValidator.php 4.7 KB

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