]> git.mxchange.org Git - friendica.git/blob - tests/Util/Database/StaticDatabase.php
Merge pull request #10094 from urbalazs/license-20210328
[friendica.git] / tests / Util / Database / StaticDatabase.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2020, Friendica
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Test\Util\Database;
23
24 use Friendica\Database\Database;
25 use Friendica\Database\DatabaseException;
26 use PDO;
27 use PDOException;
28
29 /**
30  * Overrides the Friendica database class for re-using the connection
31  * for different tests
32  *
33  * Overrides functionality to enforce one transaction per call (for nested transactions)
34  */
35 class StaticDatabase extends Database
36 {
37         /**
38          * @var ExtendedPDO
39          */
40         private static $staticConnection;
41
42         /**
43          * Override the behaviour of connect, due there is just one, static connection at all
44          *
45          * @return bool|void
46          */
47         public function connect()
48         {
49                 if (!is_null($this->connection) && $this->connected()) {
50                         return true;
51                 }
52
53                 if (!isset(self::$staticConnection)) {
54                         self::statConnect($_SERVER);
55                 }
56
57                 $this->driver = 'pdo';
58                 $this->connection = self::$staticConnection;
59                 $this->connected = true;
60                 $this->emulate_prepares = false;
61
62                 return $this->connected;
63         }
64
65         /**
66          * Override the transaction since there are now hierachical transactions possible
67          *
68          * @return bool
69          */
70         public function transaction()
71         {
72                 if (!$this->in_transaction && !$this->connection->beginTransaction()) {
73                         return false;
74                 }
75
76                 $this->in_transaction = true;
77                 return true;
78         }
79
80         /**
81          * Does a commit
82          *
83          * @return bool Was the command executed successfully?
84          */
85         public function commit()
86         {
87                 if (!$this->performCommit()) {
88                         return false;
89                 }
90                 $this->in_transaction = false;
91                 return true;
92         }
93
94         /**
95          * Setup of the global, static connection
96          * Either through explicit calling or through implicit using the Database
97          *
98          * @param array $server $_SERVER variables
99          *
100          * @throws \Exception
101          */
102         public static function statConnect(array $server)
103         {
104                 // Use environment variables for mysql if they are set beforehand
105                 if (!empty($server['MYSQL_HOST'])
106                     && (!empty($server['MYSQL_USERNAME']) || !empty($server['MYSQL_USER']))
107                     && $server['MYSQL_PASSWORD'] !== false
108                     && !empty($server['MYSQL_DATABASE']))
109                 {
110                         $db_host = $server['MYSQL_HOST'];
111                         if (!empty($server['MYSQL_PORT'])) {
112                                 $db_host .= ':' . $server['MYSQL_PORT'];
113                         }
114
115                         if (!empty($server['MYSQL_USERNAME'])) {
116                                 $db_user = $server['MYSQL_USERNAME'];
117                         } else {
118                                 $db_user = $server['MYSQL_USER'];
119                         }
120                         $db_pw = (string) $server['MYSQL_PASSWORD'];
121                         $db_data = $server['MYSQL_DATABASE'];
122                 }
123
124                 if (empty($db_host) || empty($db_user) || empty($db_data)) {
125                         throw new DatabaseException('Either one of the following settings are missing: Host, User or Database', 999, 'CONNECT');
126                 }
127
128                 $port       = 0;
129                 $serveraddr = trim($db_host);
130                 $serverdata = explode(':', $serveraddr);
131                 $server     = $serverdata[0];
132                 if (count($serverdata) > 1) {
133                         $port = trim($serverdata[1]);
134                 }
135                 $server  = trim($server);
136                 $user    = trim($db_user);
137                 $pass    = trim($db_pw ?? '');
138                 $db      = trim($db_data);
139
140                 if (!(strlen($server) && strlen($user))) {
141                         return;
142                 }
143
144                 $connect = "mysql:host=" . $server . ";dbname=" . $db;
145
146                 if ($port > 0) {
147                         $connect .= ";port=" . $port;
148                 }
149
150                 try {
151                         self::$staticConnection = @new ExtendedPDO($connect, $user, $pass);
152                         self::$staticConnection->setAttribute(PDO::ATTR_AUTOCOMMIT,0);
153                 } catch (PDOException $e) {
154                         /// @TODO At least log exception, don't ignore it!
155                 }
156         }
157
158         /**
159          * @return ExtendedPDO The global, static connection
160          */
161         public static function getGlobConnection()
162         {
163                 return self::$staticConnection;
164         }
165
166         /**
167          * Perform a global commit for every nested transaction of the static connection
168          */
169         public static function statCommit()
170         {
171                 if (isset(self::$staticConnection)) {
172                         while (self::$staticConnection->getTransactionDepth() > 0) {
173                                 self::$staticConnection->commit();
174                         }
175                 }
176         }
177
178         /**
179          * Perform a global rollback for every nested transaction of the static connection
180          */
181         public static function statRollback()
182         {
183                 if (isset(self::$staticConnection)) {
184                         while (self::$staticConnection->getTransactionDepth() > 0) {
185                                 self::$staticConnection->rollBack();
186                         }
187                 }
188         }
189 }