Passed
Push — master ( 157485...b7615a )
by Nikolaos
09:23
created

ConnectionLocator   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 194
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 33
dl 0
loc 194
rs 10
c 0
b 0
f 0
wmc 14

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getConnection() 0 44 5
A setRead() 0 7 1
A __construct() 0 13 3
A setWrite() 0 7 1
A setMaster() 0 5 1
A getWrite() 0 3 1
A getRead() 0 3 1
A getMaster() 0 3 1
1
<?php
2
3
/**
4
 * This file is part of the Phalcon Framework.
5
 *
6
 * (c) Phalcon Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.txt
9
 * file that was distributed with this source code.
10
 *
11
 * Implementation of this file has been influenced by AtlasPHP
12
 *
13
 * @link    https://github.com/atlasphp/Atlas.Pdo
14
 * @license https://github.com/atlasphp/Atlas.Pdo/blob/1.x/LICENSE.md
15
 */
16
17
declare(strict_types=1);
18
19
namespace Phalcon\DataMapper\Pdo;
20
21
use Phalcon\DataMapper\Pdo\Connection\ConnectionInterface;
22
use Phalcon\DataMapper\Pdo\Exception\ConnectionNotFound;
23
24
use function array_rand;
25
use function call_user_func;
26
27
/**
28
 * Manages Connection instances for default, read, and write connections.
29
 *
30
 * @property ConnectionInterface $master
31
 * @property array               $read
32
 * @property array               $write
33
 * @property array               $instances
34
 */
35
class ConnectionLocator implements ConnectionLocatorInterface
36
{
37
    /**
38
     * A default Connection connection factory/instance.
39
     *
40
     * @var ConnectionInterface
41
     */
42
    protected $master;
43
44
    /**
45
     * A registry of Connection "read" factories/instances.
46
     *
47
     * @var array
48
     */
49
    protected $read = [];
50
51
    /**
52
     * A registry of Connection "write" factories/instances.
53
     *
54
     * @var array
55
     */
56
    protected $write = [];
57
58
    /**
59
     * A collection of resolved instances
60
     *
61
     * @var array
62
     */
63
    private $instances = [];
64
65
    /**
66
     * Constructor.
67
     *
68
     * @param ConnectionInterface $master
69
     * @param array               $read
70
     * @param array               $write
71
     */
72
    public function __construct(
73
        ConnectionInterface $master,
74
        array $read = [],
75
        array $write = []
76
    ) {
77
        $this->setMaster($master);
78
79
        foreach ($read as $name => $callableObject) {
80
            $this->setRead($name, $callableObject);
81
        }
82
83
        foreach ($write as $name => $callableObject) {
84
            $this->setWrite($name, $callableObject);
85
        }
86
    }
87
88
    /**
89
     * Returns the default connection object.
90
     *
91
     * @return ConnectionInterface
92
     */
93
    public function getMaster(): ConnectionInterface
94
    {
95
        return $this->master;
96
    }
97
98
    /**
99
     * Returns a read connection by name; if no name is given, picks a
100
     * random connection; if no read connections are present, returns the
101
     * default connection.
102
     *
103
     * @param string $name
104
     *
105
     * @return ConnectionInterface
106
     * @throws ConnectionNotFound
107
     */
108
    public function getRead(string $name = ""): ConnectionInterface
109
    {
110
        return $this->getConnection("read", $name);
111
    }
112
113
    /**
114
     * Returns a write connection by name; if no name is given, picks a
115
     * random connection; if no write connections are present, returns the
116
     * default connection.
117
     *
118
     * @param string $name
119
     *
120
     * @return ConnectionInterface
121
     * @throws ConnectionNotFound
122
     */
123
    public function getWrite(string $name = ""): ConnectionInterface
124
    {
125
        return $this->getConnection("write", $name);
126
    }
127
128
    /**
129
     * Sets the default connection factory.
130
     *
131
     * @param ConnectionInterface $callableObject
132
     *
133
     * @return ConnectionLocatorInterface
134
     */
135
    public function setMaster(ConnectionInterface $callableObject): ConnectionLocatorInterface
136
    {
137
        $this->master = $callableObject;
138
139
        return $this;
140
    }
141
142
    /**
143
     * Sets a read connection factory by name.
144
     *
145
     * @param string   $name
146
     * @param callable $callableObject
147
     *
148
     * @return ConnectionLocatorInterface
149
     */
150
    public function setRead(
151
        string $name,
152
        callable $callableObject
153
    ): ConnectionLocatorInterface {
154
        $this->read[$name] = $callableObject;
155
156
        return $this;
157
    }
158
159
    /**
160
     * Sets a write connection factory by name.
161
     *
162
     * @param string   $name
163
     * @param callable $callableObject
164
     *
165
     * @return ConnectionLocatorInterface
166
     */
167
    public function setWrite(
168
        string $name,
169
        callable $callableObject
170
    ): ConnectionLocatorInterface {
171
        $this->write[$name] = $callableObject;
172
173
        return $this;
174
    }
175
176
    /**
177
     * Returns a connection by name.
178
     *
179
     * @param string $type
180
     * @param string $name
181
     *
182
     * @return ConnectionInterface
183
     * @throws ConnectionNotFound
184
     */
185
    protected function getConnection(
186
        string $type,
187
        string $name = ""
188
    ): ConnectionInterface {
189
        $collection = $this->{$type};
190
        $requested  = $name;
191
        $instances  = $this->instances;
192
193
        /**
194
         * No collection returns the master
195
         */
196
        if (empty($collection)) {
197
            return $this->getMaster();
198
        }
199
200
        /**
201
         * If the requested name is empty, get a random connection
202
         */
203
        if ("" === $requested) {
204
            $requested = array_rand($collection);
205
        }
206
207
        /**
208
         * If the connection name does not exist, send an exception back
209
         */
210
        if (!isset($collection[$requested])) {
211
            throw new ConnectionNotFound(
212
                "Connection not found: " . $type . ":" . $requested
213
            );
214
        }
215
216
        /**
217
         * Check if the connection has been resolved already, if yes return
218
         * it, otherwise resolve it. The keys in the `resolved` array are
219
         * formatted as "type-name"
220
         */
221
        $instanceName = $type . "-" . $name;
222
223
        if (!isset($instances[$instanceName])) {
224
            $instances[$instanceName] = call_user_func($collection[$requested]);
225
            $this->instances          = $instances;
226
        }
227
228
        return $instances[$instanceName];
229
    }
230
}
231