PageRenderTime 38ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/setup/src/Magento/Setup/Validator/DbValidator.php

https://gitlab.com/axeltizon/magento-demopoweraccess
PHP | 198 lines | 115 code | 19 blank | 64 comment | 14 complexity | 2afb61143ea9f9af0abef82bc580bdf2 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright © 2016 Magento. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Setup\Validator;
  7. use Magento\Framework\Config\ConfigOptionsListConstants;
  8. use Magento\Setup\Model\Installer;
  9. use Magento\Setup\Module\ConnectionFactory;
  10. /**
  11. * Class DbValidator - validates DB related settings
  12. */
  13. class DbValidator
  14. {
  15. /**
  16. * Db prefix max length
  17. */
  18. const DB_PREFIX_LENGTH = 5;
  19. /**
  20. * DB connection factory
  21. *
  22. * @var ConnectionFactory
  23. */
  24. private $connectionFactory;
  25. /**
  26. * Constructor
  27. *
  28. * @param ConnectionFactory $connectionFactory
  29. */
  30. public function __construct(ConnectionFactory $connectionFactory)
  31. {
  32. $this->connectionFactory = $connectionFactory;
  33. }
  34. /**
  35. * Check if database table prefix is valid
  36. *
  37. * @param string $prefix
  38. * @return boolean
  39. * @throws \InvalidArgumentException
  40. */
  41. public function checkDatabaseTablePrefix($prefix)
  42. {
  43. //The table prefix should contain only letters (a-z), numbers (0-9) or underscores (_);
  44. // the first character should be a letter.
  45. if ($prefix !== '' && !preg_match('/^([a-zA-Z])([[:alnum:]_]+)$/', $prefix)) {
  46. throw new \InvalidArgumentException(
  47. 'Please correct the table prefix format, should contain only numbers, letters or underscores.'
  48. .' The first character should be a letter.'
  49. );
  50. }
  51. if (strlen($prefix) > self::DB_PREFIX_LENGTH) {
  52. throw new \InvalidArgumentException(
  53. 'Table prefix length can\'t be more than ' . self::DB_PREFIX_LENGTH . ' characters.'
  54. );
  55. }
  56. return true;
  57. }
  58. /**
  59. * Checks Database Connection
  60. *
  61. * @param string $dbName
  62. * @param string $dbHost
  63. * @param string $dbUser
  64. * @param string $dbPass
  65. * @return boolean
  66. * @throws \Magento\Setup\Exception
  67. */
  68. public function checkDatabaseConnection($dbName, $dbHost, $dbUser, $dbPass = '')
  69. {
  70. // establish connection to information_schema view to retrieve information about user and table privileges
  71. $connection = $this->connectionFactory->create([
  72. ConfigOptionsListConstants::KEY_NAME => 'information_schema',
  73. ConfigOptionsListConstants::KEY_HOST => $dbHost,
  74. ConfigOptionsListConstants::KEY_USER => $dbUser,
  75. ConfigOptionsListConstants::KEY_PASSWORD => $dbPass,
  76. ConfigOptionsListConstants::KEY_ACTIVE => true,
  77. ]);
  78. if (!$connection) {
  79. throw new \Magento\Setup\Exception('Database connection failure.');
  80. }
  81. $mysqlVersion = $connection->fetchOne('SELECT version()');
  82. if ($mysqlVersion) {
  83. if (preg_match('/^([0-9\.]+)/', $mysqlVersion, $matches)) {
  84. if (isset($matches[1]) && !empty($matches[1])) {
  85. if (version_compare($matches[1], Installer::MYSQL_VERSION_REQUIRED) < 0) {
  86. throw new \Magento\Setup\Exception(
  87. 'Sorry, but we support MySQL version ' . Installer::MYSQL_VERSION_REQUIRED . ' or later.'
  88. );
  89. }
  90. }
  91. }
  92. }
  93. return $this->checkDatabaseName($connection, $dbName) && $this->checkDatabasePrivileges($connection, $dbName);
  94. }
  95. /**
  96. * Checks if specified database exists and visible to current user
  97. *
  98. * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection
  99. * @param string $dbName
  100. * @return bool
  101. * @throws \Magento\Setup\Exception
  102. */
  103. private function checkDatabaseName(\Magento\Framework\DB\Adapter\AdapterInterface $connection, $dbName)
  104. {
  105. $query = "SHOW DATABASES";
  106. $accessibleDbs = $connection->query($query)->fetchAll(\PDO::FETCH_COLUMN, 0);
  107. foreach ($accessibleDbs as $accessibleDbName) {
  108. if ($dbName == $accessibleDbName) {
  109. return true;
  110. }
  111. }
  112. throw new \Magento\Setup\Exception(
  113. "Database '{$dbName}' does not exist "
  114. ."or specified database server user does not have privileges to access this database."
  115. );
  116. }
  117. /**
  118. * Checks database privileges
  119. *
  120. * @param \Magento\Framework\DB\Adapter\AdapterInterface $connection
  121. * @param string $dbName
  122. * @return bool
  123. * @throws \Magento\Setup\Exception
  124. */
  125. private function checkDatabasePrivileges(\Magento\Framework\DB\Adapter\AdapterInterface $connection, $dbName)
  126. {
  127. $requiredPrivileges = [
  128. 'SELECT',
  129. 'INSERT',
  130. 'UPDATE',
  131. 'DELETE',
  132. 'CREATE',
  133. 'DROP',
  134. 'REFERENCES',
  135. 'INDEX',
  136. 'ALTER',
  137. 'CREATE TEMPORARY TABLES',
  138. 'LOCK TABLES',
  139. 'EXECUTE',
  140. 'CREATE VIEW',
  141. 'SHOW VIEW',
  142. 'CREATE ROUTINE',
  143. 'ALTER ROUTINE',
  144. 'EVENT',
  145. 'TRIGGER'
  146. ];
  147. // check global privileges
  148. $userPrivilegesQuery = "SELECT PRIVILEGE_TYPE FROM USER_PRIVILEGES "
  149. . "WHERE REPLACE(GRANTEE, '\'', '') = current_user()";
  150. $grantInfo = $connection->query($userPrivilegesQuery)->fetchAll(\PDO::FETCH_NUM);
  151. if (empty(array_diff($requiredPrivileges, $this->parseGrantInfo($grantInfo)))) {
  152. return true;
  153. }
  154. // check table privileges
  155. $schemaPrivilegesQuery = "SELECT PRIVILEGE_TYPE FROM SCHEMA_PRIVILEGES " .
  156. "WHERE '$dbName' LIKE TABLE_SCHEMA AND REPLACE(GRANTEE, '\'', '') = current_user()";
  157. $grantInfo = $connection->query($schemaPrivilegesQuery)->fetchAll(\PDO::FETCH_NUM);
  158. if (empty(array_diff($requiredPrivileges, $this->parseGrantInfo($grantInfo)))) {
  159. return true;
  160. }
  161. $errorMessage = 'Database user does not have enough privileges. Please make sure '
  162. . implode(', ', $requiredPrivileges) . " privileges are granted to table '{$dbName}'.";
  163. throw new \Magento\Setup\Exception($errorMessage);
  164. }
  165. /**
  166. * Parses query result
  167. *
  168. * @param array $grantInfo
  169. * @return array
  170. */
  171. private function parseGrantInfo(array $grantInfo)
  172. {
  173. $result = [];
  174. foreach ($grantInfo as $grantRow) {
  175. $result[] = $grantRow[0];
  176. }
  177. return $result;
  178. }
  179. }