ConnectionFactory   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 117
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 5
dl 0
loc 117
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
C createConnection() 0 51 11
A getDatabasePlatform() 0 15 2
A initializeTypes() 0 12 3
1
<?php
2
3
namespace Doctrine\Bundle\DoctrineBundle;
4
5
use Doctrine\Common\EventManager;
6
use Doctrine\DBAL\Configuration;
7
use Doctrine\DBAL\Connection;
8
use Doctrine\DBAL\DBALException;
9
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
10
use Doctrine\DBAL\DriverManager;
11
use Doctrine\DBAL\Exception\DriverException;
12
use Doctrine\DBAL\Platforms\AbstractPlatform;
13
use Doctrine\DBAL\Types\Type;
14
use function is_subclass_of;
15
16
class ConnectionFactory
17
{
18
    /** @var mixed[][] */
19
    private $typesConfig = [];
20
21
    /** @var bool */
22
    private $initialized = false;
23
24
    /**
25
     * @param mixed[][] $typesConfig
26
     */
27
    public function __construct(array $typesConfig)
28
    {
29
        $this->typesConfig = $typesConfig;
30
    }
31
32
    /**
33
     * Create a connection by name.
34
     *
35
     * @param mixed[]         $params
36
     * @param string[]|Type[] $mappingTypes
37
     *
38
     * @return Connection
39
     */
40
    public function createConnection(array $params, Configuration $config = null, EventManager $eventManager = null, array $mappingTypes = [])
41
    {
42
        if (! $this->initialized) {
43
            $this->initializeTypes();
44
        }
45
46
        if (! isset($params['pdo']) && ! isset($params['charset'])) {
47
            $wrapperClass = null;
48
            if (isset($params['wrapperClass'])) {
49
                if (! is_subclass_of($params['wrapperClass'], Connection::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Doctrine\DBAL\Connection::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
50
                    throw DBALException::invalidWrapperClass($params['wrapperClass']);
51
                }
52
53
                $wrapperClass           = $params['wrapperClass'];
54
                $params['wrapperClass'] = null;
55
            }
56
57
            $connection = DriverManager::getConnection($params, $config, $eventManager);
58
            $params     = $connection->getParams();
59
            $driver     = $connection->getDriver();
60
61
            if ($driver instanceof AbstractMySQLDriver) {
62
                $params['charset'] = 'utf8mb4';
63
64
                if (! isset($params['defaultTableOptions']['collate'])) {
65
                    $params['defaultTableOptions']['collate'] = 'utf8mb4_unicode_ci';
66
                }
67
            } else {
68
                $params['charset'] = 'utf8';
69
            }
70
71
            if ($wrapperClass !== null) {
72
                $params['wrapperClass'] = $wrapperClass;
73
            } else {
74
                $wrapperClass = Connection::class;
75
            }
76
77
            $connection = new $wrapperClass($params, $driver, $config, $eventManager);
78
        } else {
79
            $connection = DriverManager::getConnection($params, $config, $eventManager);
80
        }
81
82
        if (! empty($mappingTypes)) {
83
            $platform = $this->getDatabasePlatform($connection);
84
            foreach ($mappingTypes as $dbType => $doctrineType) {
85
                $platform->registerDoctrineTypeMapping($dbType, $doctrineType);
0 ignored issues
show
Bug introduced by
It seems like $doctrineType defined by $doctrineType on line 84 can also be of type object<Doctrine\DBAL\Types\Type>; however, Doctrine\DBAL\Platforms\...erDoctrineTypeMapping() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
86
            }
87
        }
88
89
        return $connection;
90
    }
91
92
    /**
93
     * Try to get the database platform.
94
     *
95
     * This could fail if types should be registered to an predefined/unused connection
96
     * and the platform version is unknown.
97
     * For details have a look at DoctrineBundle issue #673.
98
     *
99
     * @throws DBALException
100
     */
101
    private function getDatabasePlatform(Connection $connection) : AbstractPlatform
102
    {
103
        try {
104
            return $connection->getDatabasePlatform();
105
        } catch (DriverException $driverException) {
106
            throw new DBALException(
107
                'An exception occurred while establishing a connection to figure out your platform version.' . PHP_EOL .
108
                "You can circumvent this by setting a 'server_version' configuration value" . PHP_EOL . PHP_EOL .
109
                'For further information have a look at:' . PHP_EOL .
110
                'https://github.com/doctrine/DoctrineBundle/issues/673',
111
                0,
112
                $driverException
113
            );
114
        }
115
    }
116
117
    /**
118
     * initialize the types
119
     */
120
    private function initializeTypes() : void
121
    {
122
        foreach ($this->typesConfig as $typeName => $typeConfig) {
123
            if (Type::hasType($typeName)) {
124
                Type::overrideType($typeName, $typeConfig['class']);
125
            } else {
126
                Type::addType($typeName, $typeConfig['class']);
127
            }
128
        }
129
130
        $this->initialized = true;
131
    }
132
}
133