SessionHandlerFactory.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
  11. use Doctrine\DBAL\Configuration;
  12. use Doctrine\DBAL\DriverManager;
  13. use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory;
  14. use Doctrine\DBAL\Tools\DsnParser;
  15. use Relay\Relay;
  16. use Symfony\Component\Cache\Adapter\AbstractAdapter;
  17. /**
  18. * @author Nicolas Grekas <p@tchwork.com>
  19. */
  20. class SessionHandlerFactory
  21. {
  22. public static function createHandler(object|string $connection, array $options = []): AbstractSessionHandler
  23. {
  24. if ($query = \is_string($connection) ? parse_url($connection) : false) {
  25. parse_str($query['query'] ?? '', $query);
  26. if (($options['ttl'] ?? null) instanceof \Closure) {
  27. $query['ttl'] = $options['ttl'];
  28. }
  29. }
  30. $options = ($query ?: []) + $options;
  31. switch (true) {
  32. case $connection instanceof \Redis:
  33. case $connection instanceof Relay:
  34. case $connection instanceof \RedisArray:
  35. case $connection instanceof \RedisCluster:
  36. case $connection instanceof \Predis\ClientInterface:
  37. return new RedisSessionHandler($connection);
  38. case $connection instanceof \Memcached:
  39. return new MemcachedSessionHandler($connection);
  40. case $connection instanceof \PDO:
  41. return new PdoSessionHandler($connection);
  42. case !\is_string($connection):
  43. throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', get_debug_type($connection)));
  44. case str_starts_with($connection, 'file://'):
  45. $savePath = substr($connection, 7);
  46. return new StrictSessionHandler(new NativeFileSessionHandler('' === $savePath ? null : $savePath));
  47. case str_starts_with($connection, 'redis:'):
  48. case str_starts_with($connection, 'rediss:'):
  49. case str_starts_with($connection, 'memcached:'):
  50. if (!class_exists(AbstractAdapter::class)) {
  51. throw new \InvalidArgumentException('Unsupported Redis or Memcached DSN. Try running "composer require symfony/cache".');
  52. }
  53. $handlerClass = str_starts_with($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class;
  54. $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]);
  55. return new $handlerClass($connection, array_intersect_key($options, ['prefix' => 1, 'ttl' => 1]));
  56. case str_starts_with($connection, 'pdo_oci://'):
  57. if (!class_exists(DriverManager::class)) {
  58. throw new \InvalidArgumentException('Unsupported PDO OCI DSN. Try running "composer require doctrine/dbal".');
  59. }
  60. $connection[3] = '-';
  61. $params = class_exists(DsnParser::class) ? (new DsnParser())->parse($connection) : ['url' => $connection];
  62. $config = new Configuration();
  63. if (class_exists(DefaultSchemaManagerFactory::class)) {
  64. $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory());
  65. }
  66. $connection = DriverManager::getConnection($params, $config);
  67. // The condition should be removed once support for DBAL <3.3 is dropped
  68. $connection = method_exists($connection, 'getNativeConnection') ? $connection->getNativeConnection() : $connection->getWrappedConnection();
  69. // no break;
  70. case str_starts_with($connection, 'mssql://'):
  71. case str_starts_with($connection, 'mysql://'):
  72. case str_starts_with($connection, 'mysql2://'):
  73. case str_starts_with($connection, 'pgsql://'):
  74. case str_starts_with($connection, 'postgres://'):
  75. case str_starts_with($connection, 'postgresql://'):
  76. case str_starts_with($connection, 'sqlsrv://'):
  77. case str_starts_with($connection, 'sqlite://'):
  78. case str_starts_with($connection, 'sqlite3://'):
  79. return new PdoSessionHandler($connection, $options);
  80. }
  81. throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', $connection));
  82. }
  83. }