ConfigurationUrlParser.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. namespace Illuminate\Support;
  3. use InvalidArgumentException;
  4. class ConfigurationUrlParser
  5. {
  6. /**
  7. * The drivers aliases map.
  8. *
  9. * @var array
  10. */
  11. protected static $driverAliases = [
  12. 'mssql' => 'sqlsrv',
  13. 'mysql2' => 'mysql', // RDS
  14. 'postgres' => 'pgsql',
  15. 'postgresql' => 'pgsql',
  16. 'sqlite3' => 'sqlite',
  17. 'redis' => 'tcp',
  18. 'rediss' => 'tls',
  19. ];
  20. /**
  21. * Parse the database configuration, hydrating options using a database configuration URL if possible.
  22. *
  23. * @param array|string $config
  24. * @return array
  25. */
  26. public function parseConfiguration($config)
  27. {
  28. if (is_string($config)) {
  29. $config = ['url' => $config];
  30. }
  31. $url = Arr::pull($config, 'url');
  32. if (! $url) {
  33. return $config;
  34. }
  35. $rawComponents = $this->parseUrl($url);
  36. $decodedComponents = $this->parseStringsToNativeTypes(
  37. array_map('rawurldecode', $rawComponents)
  38. );
  39. return array_merge(
  40. $config,
  41. $this->getPrimaryOptions($decodedComponents),
  42. $this->getQueryOptions($rawComponents)
  43. );
  44. }
  45. /**
  46. * Get the primary database connection options.
  47. *
  48. * @param array $url
  49. * @return array
  50. */
  51. protected function getPrimaryOptions($url)
  52. {
  53. return array_filter([
  54. 'driver' => $this->getDriver($url),
  55. 'database' => $this->getDatabase($url),
  56. 'host' => $url['host'] ?? null,
  57. 'port' => $url['port'] ?? null,
  58. 'username' => $url['user'] ?? null,
  59. 'password' => $url['pass'] ?? null,
  60. ], fn ($value) => ! is_null($value));
  61. }
  62. /**
  63. * Get the database driver from the URL.
  64. *
  65. * @param array $url
  66. * @return string|null
  67. */
  68. protected function getDriver($url)
  69. {
  70. $alias = $url['scheme'] ?? null;
  71. if (! $alias) {
  72. return;
  73. }
  74. return static::$driverAliases[$alias] ?? $alias;
  75. }
  76. /**
  77. * Get the database name from the URL.
  78. *
  79. * @param array $url
  80. * @return string|null
  81. */
  82. protected function getDatabase($url)
  83. {
  84. $path = $url['path'] ?? null;
  85. return $path && $path !== '/' ? substr($path, 1) : null;
  86. }
  87. /**
  88. * Get all of the additional database options from the query string.
  89. *
  90. * @param array $url
  91. * @return array
  92. */
  93. protected function getQueryOptions($url)
  94. {
  95. $queryString = $url['query'] ?? null;
  96. if (! $queryString) {
  97. return [];
  98. }
  99. $query = [];
  100. parse_str($queryString, $query);
  101. return $this->parseStringsToNativeTypes($query);
  102. }
  103. /**
  104. * Parse the string URL to an array of components.
  105. *
  106. * @param string $url
  107. * @return array
  108. *
  109. * @throws \InvalidArgumentException
  110. */
  111. protected function parseUrl($url)
  112. {
  113. $url = preg_replace('#^(sqlite3?):///#', '$1://null/', $url);
  114. $parsedUrl = parse_url($url);
  115. if ($parsedUrl === false) {
  116. throw new InvalidArgumentException('The database configuration URL is malformed.');
  117. }
  118. return $parsedUrl;
  119. }
  120. /**
  121. * Convert string casted values to their native types.
  122. *
  123. * @param mixed $value
  124. * @return mixed
  125. */
  126. protected function parseStringsToNativeTypes($value)
  127. {
  128. if (is_array($value)) {
  129. return array_map([$this, 'parseStringsToNativeTypes'], $value);
  130. }
  131. if (! is_string($value)) {
  132. return $value;
  133. }
  134. $parsedValue = json_decode($value, true);
  135. if (json_last_error() === JSON_ERROR_NONE) {
  136. return $parsedValue;
  137. }
  138. return $value;
  139. }
  140. /**
  141. * Get all of the current drivers' aliases.
  142. *
  143. * @return array
  144. */
  145. public static function getDriverAliases()
  146. {
  147. return static::$driverAliases;
  148. }
  149. /**
  150. * Add the given driver alias to the driver aliases array.
  151. *
  152. * @param string $alias
  153. * @param string $driver
  154. * @return void
  155. */
  156. public static function addDriverAlias($alias, $driver)
  157. {
  158. static::$driverAliases[$alias] = $driver;
  159. }
  160. }