SimpleDBALPool::detach()   B
last analyzed

Complexity

Conditions 7
Paths 36

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.5866
c 0
b 0
f 0
cc 7
nc 36
nop 1
1
<?php
2
3
namespace BenTools\SimpleDBAL\Model;
4
5
use BenTools\SimpleDBAL\Contract\ConnectionInterface;
6
use BenTools\SimpleDBAL\Contract\ResultInterface;
7
use BenTools\SimpleDBAL\Contract\StatementInterface;
8
9
class SimpleDBALPool
10
{
11
12
    const READ_WRITE = 1;
13
    const READ_ONLY  = 2;
14
    const WRITE_ONLY = 3;
15
16
    protected $rConnections  = [];
17
    protected $wConnections  = [];
18
19
    /**
20
     * @param ConnectionInterface $connection
21
     * @param int $access
22
     * @param int $weight
23
     */
24
    public function attach(ConnectionInterface $connection, int $access = self::READ_WRITE, int $weight = 1)
25
    {
26
        if ($weight >= 1) {
27
            switch ($access) {
28
                case self::READ_ONLY:
29
                    $this->rConnections[] = ['c' => $connection, 'w' => $weight];
30
                    break;
31
                case self::WRITE_ONLY:
32
                    $this->wConnections[] = ['c' => $connection, 'w' => $weight];
33
                    break;
34
                case self::READ_WRITE:
35
                    $this->rConnections[] = ['c' => $connection, 'w' => $weight];
36
                    $this->wConnections[] = ['c' => $connection, 'w' => $weight];
37
                    break;
38
                default:
39
                    throw new \InvalidArgumentException("Invalid access argument.");
40
            }
41
        }
42
    }
43
44
    /**
45
     * @param ConnectionInterface $connection
46
     */
47
    public function detach(ConnectionInterface $connection)
48
    {
49
        $reorderReadConnections = false;
50
        $reorderWriteConnections = false;
51
        foreach ($this->rConnections as $c => $connectionBag) {
52
            if ($connectionBag['c'] === $connection) {
53
                unset($this->rConnections[$c]);
54
                $reorderReadConnections = true;
55
            }
56
        }
57
        foreach ($this->wConnections as $c => $connectionBag) {
58
            if ($connectionBag['c'] === $connection) {
59
                unset($this->wConnections[$c]);
60
                $reorderWriteConnections = true;
61
            }
62
        }
63
64
        if ($reorderReadConnections) {
65
            $this->rConnections = array_values($this->rConnections);
66
        }
67
68
        if ($reorderWriteConnections) {
69
            $this->wConnections = array_values($this->wConnections);
70
        }
71
    }
72
73
    /**
74
     * @inheritDoc
75
     */
76
    public function prepareReadStmt(string $query, array $values = null): StatementInterface
77
    {
78
        return $this->selectReadConnection()->prepare($query, $values);
79
    }
80
81
    /**
82
     * @inheritDoc
83
     */
84
    public function prepareWriteStmt(string $query, array $values = null): StatementInterface
85
    {
86
        return $this->selectWriteConnection()->prepare($query, $values);
87
    }
88
89
    /**
90
     * @inheritdoc
91
     */
92
    public function read($stmt, array $values = null): ResultInterface
93
    {
94
        if ($stmt instanceof StatementInterface) {
95
            return $stmt->getConnection()->execute($stmt);
96
        } else {
97
            return $this->selectReadConnection()->execute($stmt, $values);
98
        }
99
    }
100
101
    /**
102
     * @inheritdoc
103
     */
104
    public function write($stmt, array $values = null): ResultInterface
105
    {
106
        if ($stmt instanceof StatementInterface) {
107
            return $stmt->getConnection()->execute($stmt);
108
        } else {
109
            return $this->selectWriteConnection()->execute($stmt, $values);
110
        }
111
    }
112
113
    /**
114
     * @return ConnectionInterface
115
     */
116
    private function selectReadConnection(): ConnectionInterface
117
    {
118
        $nbConnections = count($this->rConnections);
119
        switch ($nbConnections) {
120
            case 0:
121
                throw new \RuntimeException("No connection available to read database.");
122
            case 1:
123
                return $this->rConnections[0];
124
            default:
125
                $fill = [];
126
                foreach ($this->rConnections as $c => $connection) {
127
                    $fill = array_merge($fill, array_fill(0, $connection['w'], $c));
128
                }
129
                $cnt = count($fill);
130
                return $this->rConnections[$fill[random_int(0, $cnt)]];
131
        }
132
    }
133
134
    /**
135
     * @return ConnectionInterface
136
     */
137
    private function selectWriteConnection(): ConnectionInterface
138
    {
139
        $nbConnections = count($this->wConnections);
140
        switch ($nbConnections) {
141
            case 0:
142
                throw new \RuntimeException("No connection available to write on database.");
143
            case 1:
144
                return $this->wConnections[0];
145
            default:
146
                $fill = [];
147
                foreach ($this->wConnections as $c => $connection) {
148
                    $fill = array_merge($fill, array_fill(0, $connection['w'], $c));
149
                }
150
                $cnt = count($fill);
151
                return $this->wConnections[$fill[random_int(0, $cnt)]];
152
        }
153
    }
154
}
155