PgPhp   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 104
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 42
c 1
b 0
f 0
dl 0
loc 104
rs 10
wmc 19

10 Methods

Rating   Name   Duplication   Size   Complexity  
A sql() 0 9 3
A create() 0 3 1
A __construct() 0 3 1
A query() 0 10 3
A existsDatabase() 0 5 2
A resource() 0 16 3
A isLostConnection() 0 3 1
A listDatabases() 0 8 2
A drop() 0 3 1
A copy() 0 6 2
1
<?php declare(strict_types=1);
2
3
namespace PmgDev\DatabaseReplicator\Database\Postgres;
4
5
use PmgDev\DatabaseReplicator\Config;
6
use PmgDev\DatabaseReplicator\Exceptions\CommandFailedException;
7
use PmgDev\DatabaseReplicator\Exceptions\ConnectionFailedException;
8
use PmgDev\DatabaseReplicator\Exceptions\CopyCommandFailedException;
9
use PmgDev\DatabaseReplicator\Exceptions\LostConnectionException;
10
11
class PgPhp
12
{
13
	/** @var Config */
14
	private $config;
15
16
	/** @var resource */
17
	private $resource;
18
19
20
	public function __construct(Config $adminConfig)
21
	{
22
		$this->config = $adminConfig;
23
	}
24
25
26
	public function copy(Config $source, string $cloneDb): void
27
	{
28
		try {
29
			$this->sql('CREATE DATABASE %s WITH TEMPLATE %s OWNER %s', $cloneDb, $source->database, $source->username);
30
		} catch (CommandFailedException $e) {
31
			throw new CopyCommandFailedException($e->getMessage(), $e->getCode(), $e);
32
		}
33
	}
34
35
36
	public function drop(string $database): void
37
	{
38
		$this->sql('DROP DATABASE IF EXISTS %s', $database);
39
	}
40
41
42
	public function existsDatabase(string $database): bool
43
	{
44
		$resource = $this->sql("SELECT 1 AS exists FROM pg_database WHERE datname = '%s'", $database);
45
		$data = pg_fetch_assoc($resource);
46
		return $data !== FALSE && isset($data['exists']);
47
	}
48
49
50
	public function listDatabases()
51
	{
52
		$resource = $this->sql('SELECT datname FROM pg_database WHERE datistemplate = false');
53
		$databases = [];
54
		while ($row = pg_fetch_assoc($resource)) {
55
			$databases[] = $row['datname'];
56
		}
57
		return $databases;
58
	}
59
60
61
	public function create(Config $config): void
62
	{
63
		$this->sql('CREATE DATABASE %s OWNER %s', $config->database, $config->username);
64
	}
65
66
67
	private function sql(string $command, ...$parameters)
68
	{
69
		try {
70
			return $this->query($command, $parameters);
71
		} catch (LostConnectionException $e) {
72
			if (pg_connection_reset($this->resource) === FALSE) {
73
				throw new ConnectionFailedException('Connection is lost.', 0, $e);
74
			}
75
			return $this->query($command, $parameters);
76
		}
77
	}
78
79
80
	private function resource()
81
	{
82
		if ($this->resource === NULL) {
83
			$resource = @pg_connect(vsprintf('host=%s port=%s dbname=%s user=%s password=%s', [
84
				$this->config->host,
85
				$this->config->port,
86
				$this->config->database,
87
				$this->config->username,
88
				$this->config->password,
89
			]));
90
			if ($resource === FALSE) {
91
				throw new ConnectionFailedException('Check your credentials for database.');
92
			}
93
			$this->resource = $resource;
94
		}
95
		return $this->resource;
96
	}
97
98
99
	private function isLostConnection(): bool
100
	{
101
		return pg_connection_status($this->resource) === PGSQL_CONNECTION_BAD;
102
	}
103
104
105
	private function query(string $command, array $parameters)
106
	{
107
		$resource = @pg_query($this->resource(), vsprintf($command, $parameters));
108
		if ($resource === FALSE) {
109
			if ($this->isLostConnection()) {
110
				throw new LostConnectionException();
111
			}
112
			throw new CommandFailedException(pg_last_error($this->resource));
113
		}
114
		return $resource;
115
	}
116
117
}
118