1<?php
2
3declare(strict_types=1);
4
5/*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18namespace TYPO3\CMS\Core\Database\Driver\PDOSqlsrv;
19
20/**
21 * This is a full "clone" of the class of package doctrine/dbal. Scope is to use the PDOConnection of TYPO3.
22 * All private methods have to be checked on every release of doctrine/dbal.
23 */
24class Driver extends \Doctrine\DBAL\Driver\PDOSqlsrv\Driver
25{
26    /**
27     * {@inheritdoc}
28     */
29    public function connect(array $params, $username = null, $password = null, array $driverOptions = [])
30    {
31        [$driverOptions, $connectionOptions] = $this->splitOptions($driverOptions);
32
33        return new Connection(
34            $this->_constructPdoDsn($params, $connectionOptions),
35            $username,
36            $password,
37            $driverOptions
38        );
39    }
40
41    /**
42     * {@inheritdoc}
43     */
44    private function _constructPdoDsn(array $params, array $connectionOptions)
45    {
46        $dsn = 'sqlsrv:server=';
47
48        if (isset($params['host'])) {
49            $dsn .= $params['host'];
50        }
51
52        if (isset($params['port']) && ! empty($params['port'])) {
53            $dsn .= ',' . $params['port'];
54        }
55
56        if (isset($params['dbname'])) {
57            $connectionOptions['Database'] = $params['dbname'];
58        }
59
60        if (isset($params['MultipleActiveResultSets'])) {
61            $connectionOptions['MultipleActiveResultSets'] = $params['MultipleActiveResultSets'] ? 'true' : 'false';
62        }
63
64        return $dsn . $this->getConnectionOptionsDsn($connectionOptions);
65    }
66
67    /**
68     * {@inheritdoc}
69     */
70    private function splitOptions(array $options): array
71    {
72        $driverOptions     = [];
73        $connectionOptions = [];
74
75        foreach ($options as $optionKey => $optionValue) {
76            if (is_int($optionKey)) {
77                $driverOptions[$optionKey] = $optionValue;
78            } else {
79                $connectionOptions[$optionKey] = $optionValue;
80            }
81        }
82
83        return [$driverOptions, $connectionOptions];
84    }
85
86    /**
87     * {@inheritdoc}
88     */
89    private function getConnectionOptionsDsn(array $connectionOptions): string
90    {
91        $connectionOptionsDsn = '';
92
93        foreach ($connectionOptions as $paramName => $paramValue) {
94            $connectionOptionsDsn .= sprintf(';%s=%s', $paramName, $paramValue);
95        }
96
97        return $connectionOptionsDsn;
98    }
99
100    /**
101     * {@inheritdoc}
102     */
103    public function getName()
104    {
105        return parent::getName();
106    }
107}
108