Issues (65)

src/Connection.php (3 issues)

1
<?php
2
3
/**
4
 * Simple PDO connection wrapper for Crudites
5
 *
6
 * Provides a simple PDO connection wrapper for the Crudites library.
7
 * 
8
 * It encapsulates a PDO instance and provides methods for preparing and executing SQL statements.
9
 * All PDO methods are available through the magic __call method.
10
 * 
11
 * Also provides a Source instance to parse the DSN and a Schema instance to interact with the database schema.
12
 * 
13
 * Sets defaults: ERRMODE_EXCEPTION, CASE_NATURAL, FETCH_ASSOC, required by Crudites
14
 * Sets preferred fetch mode: associative array.
15
 *
16
 * @package HexMakina\Crudites
17
 */
18
19
namespace HexMakina\Crudites;
20
21
use HexMakina\BlackBox\Database\ConnectionInterface;
22
use HexMakina\BlackBox\Database\ResultInterface;
0 ignored issues
show
The type HexMakina\BlackBox\Database\ResultInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use HexMakina\BlackBox\Database\SchemaInterface;
0 ignored issues
show
The type HexMakina\BlackBox\Database\SchemaInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use HexMakina\Crudites\Schema\SchemaLoader;
25
26
class Connection extends \PDO implements ConnectionInterface
27
{
28
    private string $dsn;
29
    private ?string $database = null;
30
    private SchemaInterface $schema;
31
32
    /**
33
     * Constructor. Same as PDO constructor
34
     *
35
     * @throws \PDOException if the attempt to connect to the requested database fails
36
     */
37
    public function __construct(string $dsn, string $username = '', string $password = '', array $driver_options = [])
38
    {
39
        try {
40
            $this->dsn = $dsn;
41
            $options = self::options($driver_options);
42
            parent::__construct($dsn, $username, $password, $options);
43
        } catch (\PDOException $e) {
44
            throw new CruditesException($e->getMessage(), $e->getCode());
45
        }
46
    }
47
    
48
    public function __toString()
49
    {
50
        return $this->dsn;
51
    }
52
53
54
    /**
55
     * Returns the name of the database
56
     * @throws \HexMakina\Crudites\CruditesException if the database name cannot be extracted from the DSN
57
     */
58
    public function database(): string
59
    {
60
        if ($this->database === null) {
61
            $this->database = $this->extractDatabaseNameFromDsn();
62
        }
63
        return $this->database;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->database could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
64
    }
65
66
67
    /**
68
     * Returns a representation the database schema
69
     * @throws \HexMakina\Crudites\CruditesException if the schema cannot be loaded
70
     */
71
    public function schema(): SchemaInterface
72
    {
73
        $database = $this->database();
74
        if (!isset($this->schema)) {
75
            $this->schema = SchemaLoader::cache($database) ?? SchemaLoader::load($database, $this->pdo());
76
        }
77
        return $this->schema;
78
    }
79
80
    public function result($statement, $bindings = []): ResultInterface
81
    {
82
        return new Result($this, $statement, $bindings);
83
    }
84
85
    public function pdo(): \PDO
86
    {
87
        return $this;
88
    }
89
90
    
91
    /**
92
     * Extracts the database name from the DSN
93
     * @throws \HexMakina\Crudites\CruditesException if the database name cannot be extracted from the DSN
94
     */
95
    private function extractDatabaseNameFromDsn(): string
96
    {
97
        $matches = [];
98
        if (1 === preg_match('/dbname=(.+);/', $this->dsn, $matches) && isset($matches[1])) {
99
            return $matches[1];
100
        }
101
        throw new CruditesException('PARSING_DSN_FOR_DATABASE');
102
    }
103
104
105
    /**
106
     * Returns an array of PDO options for database connection.
107
     * all other options can be overridden by the provided array.
108
     * 
109
     * \PDO::ATTR_ERRMODE  is ALWAYS \PDO::ERRMODE_EXCEPTION,
110
     * 
111
     * @param array $provided An array of additional options to merge with the default options.
112
     * @return array The merged array of PDO options.
113
     */
114
    private static function options(array $provided = []): array
115
    {
116
        if (isset($provided[\PDO::ATTR_ERRMODE])) {
117
            unset($provided[\PDO::ATTR_ERRMODE]);          // the one option you cannot change
118
        }
119
120
        return array_merge(
121
            [
122
                \PDO::ATTR_ERRMODE  => \PDO::ERRMODE_EXCEPTION,
123
                \PDO::ATTR_CASE     => \PDO::CASE_NATURAL,
124
                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC
125
            ],
126
            $provided
127
        );
128
    }
129
}
130