public static function getConnection(
        array $params,
        ?Configuration $config = null,
        ?EventManager $eventManager = null
    ) : Connection {
        // create default config and event manager, if not set
        if (! $config) {
            $config = new Configuration();
        }
        if (! $eventManager) {
            $eventManager = new EventManager();
        }

        $params = self::parseDatabaseUrl($params);

        // URL support for MasterSlaveConnection
        if (isset($params['master'])) {
            $params['master'] = self::parseDatabaseUrl($params['master']);
        }

        if (isset($params['slaves'])) {
            foreach ($params['slaves'] as $key => $slaveParams) {
                $params['slaves'][$key] = self::parseDatabaseUrl($slaveParams);
            }
        }

        // URL support for PoolingShardConnection
        if (isset($params['global'])) {
            $params['global'] = self::parseDatabaseUrl($params['global']);
        }

        if (isset($params['shards'])) {
            foreach ($params['shards'] as $key => $shardParams) {
                $params['shards'][$key] = self::parseDatabaseUrl($shardParams);
            }
        }

        // check for existing pdo object
        if (isset($params['pdo']) && ! $params['pdo'] instanceof PDO) {
            throw DBALException::invalidPdoInstance();
        }

        if (isset($params['pdo'])) {
            $params['pdo']->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $params['driver'] = 'pdo_' . $params['pdo']->getAttribute(PDO::ATTR_DRIVER_NAME);
        } else {
            self::_checkParams($params);
        }

        $className = $params['driverClass'] ?? self::$_driverMap[$params['driver']];

        $driver = new $className();

        $wrapperClass = Connection::class;
        if (isset($params['wrapperClass'])) {
            if (! is_subclass_of($params['wrapperClass'], $wrapperClass)) {
                throw DBALException::invalidWrapperClass($params['wrapperClass']);
            }

            $wrapperClass = $params['wrapperClass'];
        }

        return new $wrapperClass($params, $driver, $config, $eventManager);
    }