ConfigurationUrlParser.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. ], function ($value) {
  61. return ! is_null($value);
  62. });
  63. }
  64. /**
  65. * Get the database driver from the URL.
  66. *
  67. * @param array $url
  68. * @return string|null
  69. */
  70. protected function getDriver($url)
  71. {
  72. $alias = $url['scheme'] ?? null;
  73. if (! $alias) {
  74. return;
  75. }
  76. return static::$driverAliases[$alias] ?? $alias;
  77. }
  78. /**
  79. * Get the database name from the URL.
  80. *
  81. * @param array $url
  82. * @return string|null
  83. */
  84. protected function getDatabase($url)
  85. {
  86. $path = $url['path'] ?? null;
  87. return $path && $path !== '/' ? substr($path, 1) : null;
  88. }
  89. /**
  90. * Get all of the additional database options from the query string.
  91. *
  92. * @param array $url
  93. * @return array
  94. */
  95. protected function getQueryOptions($url)
  96. {
  97. $queryString = $url['query'] ?? null;
  98. if (! $queryString) {
  99. return [];
  100. }
  101. $query = [];
  102. parse_str($queryString, $query);
  103. return $this->parseStringsToNativeTypes($query);
  104. }
  105. /**
  106. * Parse the string URL to an array of components.
  107. *
  108. * @param string $url
  109. * @return array
  110. *
  111. * @throws \InvalidArgumentException
  112. */
  113. protected function parseUrl($url)
  114. {
  115. $url = preg_replace('#^(sqlite3?):///#', '$1://null/', $url);
  116. $parsedUrl = parse_url($url);
  117. if ($parsedUrl === false) {
  118. throw new InvalidArgumentException('The database configuration URL is malformed.');
  119. }
  120. return $parsedUrl;
  121. }
  122. /**
  123. * Convert string casted values to their native types.
  124. *
  125. * @param mixed $value
  126. * @return mixed
  127. */
  128. protected function parseStringsToNativeTypes($value)
  129. {
  130. if (is_array($value)) {
  131. return array_map([$this, 'parseStringsToNativeTypes'], $value);
  132. }
  133. if (! is_string($value)) {
  134. return $value;
  135. }
  136. $parsedValue = json_decode($value, true);
  137. if (json_last_error() === JSON_ERROR_NONE) {
  138. return $parsedValue;
  139. }
  140. return $value;
  141. }
  142. /**
  143. * Get all of the current drivers' aliases.
  144. *
  145. * @return array
  146. */
  147. public static function getDriverAliases()
  148. {
  149. return static::$driverAliases;
  150. }
  151. /**
  152. * Add the given driver alias to the driver aliases array.
  153. *
  154. * @param string $alias
  155. * @param string $driver
  156. * @return void
  157. */
  158. public static function addDriverAlias($alias, $driver)
  159. {
  160. static::$driverAliases[$alias] = $driver;
  161. }
  162. }