Passed
Branch main (5746ae)
by Sammy
02:23
created

Crudites   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 65
dl 0
loc 149
rs 10
c 1
b 0
f 0
wmc 25

10 Methods

Rating   Name   Duplication   Size   Complexity  
A inspect() 0 10 3
A raw() 0 12 2
A count() 0 8 2
A setDatabase() 0 3 1
A retrieve() 0 13 3
A connect() 0 13 3
A tableNameToTable() 0 3 2
A distinctForWithId() 0 16 3
A distinctFor() 0 19 3
A toggleBoolean() 0 23 3
1
<?php
2
3
/**
4
 * Crudités, it's a cup of carrots sticks (but are they organic ?)
5
 * Codd's Relational model, Unicity, Definitions, Introspection, Tests, Execution & Sets
6
 * Create - Retrieve - Update - Delete
7
 * API for writing and running SQL queries
8
 */
9
10
namespace HexMakina\Crudites;
11
12
use HexMakina\Crudites\Queries\BaseQuery;
13
use HexMakina\BlackBox\Database\SelectInterface;
14
use HexMakina\BlackBox\Database\DatabaseInterface;
15
use HexMakina\Crudites\CruditesException;
16
17
class Crudites
18
{
19
    private static $database = null;
20
21
    public static function setDatabase(DatabaseInterface $db)
22
    {
23
        self::$database = $db;
24
    }
25
26
    public static function inspect($table_name)
27
    {
28
        if (is_null(self::$database)) {
29
            throw new CruditesException('NO_DATABASE');
30
        }
31
32
        try {
33
            return self::$database->inspect($table_name);
34
        } catch (\Exception $e) {
35
            throw new CruditesException('TABLE_INTROSPECTION::' . $table_name);
36
        }
37
    }
38
39
    public static function connect($dsn = null, $user = null, $pass = null)
40
    {
41
        // no props, means connection already exists, verify and return
42
        if (!isset($dsn, $user, $pass)) {
43
            if (is_null(self::$database)) {
44
                throw new CruditesException('CONNECTION_MISSING');
45
            }
46
47
            return self::$database->connection();
48
        }
49
50
        $conx = new Connection($dsn, $user, $pass);
51
        return $conx;
52
    }
53
54
    //------------------------------------------------------------  DataRetrieval
55
    // success: return AIPK-indexed array of results (associative array or object)
56
    public static function count(SelectInterface $Query)
57
    {
58
        $Query->selectAlso(['COUNT(*) as count']);
59
        $res = $Query->retCol();
60
        if (is_array($res)) {
61
            return intval(current($res));
62
        }
63
        return null;
64
    }
65
66
    // success: return AIPK-indexed array of results (associative array or object)
67
    public static function retrieve(SelectInterface $Query): array
68
    {
69
        $pk_name = implode('_', array_keys($Query->table()->primaryKeys()));
70
71
        $ret = [];
72
73
        if ($Query->run()->isSuccess()) {
74
            foreach ($Query->retAss() as $rec) {
75
                $ret[$rec[$pk_name]] = $rec;
76
            }
77
        }
78
79
        return $ret;
80
    }
81
82
    public static function raw($sql, $dat_ass = [])
83
    {
84
        $conx = self::connect();
85
        if (empty($dat_ass)) {
86
            $res = $conx->query($sql);
87
            //TODO query | alter !
88
            //$res = $conx->alter($sql);
89
        } else {
90
            $stmt = $conx->prepare($sql);
91
            $res = $stmt->execute($dat_ass);
92
        }
93
        return $res;
94
    }
95
96
    public static function distinctFor($table, $column_name, $filter_by_value = null)
97
    {
98
        $table = self::tableNameToTable($table);
99
100
        if (is_null($table->column($column_name))) {
101
            throw new CruditesException('TABLE_REQUIRES_COLUMN');
102
        }
103
104
        $Query = $table->select(["DISTINCT `$column_name`"])
105
          ->whereNotEmpty($column_name)
106
          ->orderBy([$table->name(), $column_name, 'ASC']);
107
108
        if (!is_null($filter_by_value)) {
109
            $Query->whereLike($column_name, "%$filter_by_value%");
110
        }
111
112
        $Query->orderBy($column_name, 'DESC');
113
        // ddt($Query);
114
        return $Query->retCol();
115
    }
116
117
    public static function distinctForWithId($table, $column_name, $filter_by_value = null)
118
    {
119
        $table = self::tableNameToTable($table);
120
121
        if (is_null($table->column($column_name))) {
122
            throw new CruditesException('TABLE_REQUIRES_COLUMN');
123
        }
124
125
        $Query = $table->select(["DISTINCT `id`,`$column_name`"])
126
          ->whereNotEmpty($column_name)->orderBy([$table->name(), $column_name, 'ASC']);
127
128
        if (!is_null($filter_by_value)) {
129
            $Query->whereLike($column_name, "%$filter_by_value%");
130
        }
131
132
        return $Query->retPar();
133
    }
134
135
    //------------------------------------------------------------  DataManipulation Helpers
136
    // returns true on success, false on failure or throws an exception
137
    // throws Exception on failure
138
    public static function toggleBoolean($table, $boolean_column_name, $id): bool
139
    {
140
141
        $table = self::tableNameToTable($table);
142
143
        if (is_null($column = $table->column($boolean_column_name)) || !$column->type()->isBoolean()) {
144
            return false;
145
        }
146
147
        // TODO: still using 'id' instead of table->primaries
148
        // TODO: not using the QueryInterface Way of binding stuff
149
        $Query = $table->update();
150
        $statement = sprintf(
151
            "UPDATE %s SET %s = !%s WHERE id=:id",
152
            $table->name(),
153
            $boolean_column_name,
154
            $boolean_column_name
155
        );
156
        $Query->statement($statement);
157
        $Query->setBindings([':id' => $id]);
158
        $Query->run();
159
160
        return $Query->isSuccess();
161
    }
162
163
    private static function tableNameToTable($table)
164
    {
165
        return is_string($table) ? self::inspect($table) : $table;
166
    }
167
}
168