Passed
Push — main ( 793b19...197711 )
by Sammy
07:50 queued 14s
created

TableModel::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 5
c 1
b 0
f 1
dl 0
loc 7
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
namespace HexMakina\TightORM;
4
5
use HexMakina\Crudites\Crudites;
6
use HexMakina\Crudites\CruditesException;
7
use HexMakina\BlackBox\Database\TableInterface;
0 ignored issues
show
Bug introduced by
The type HexMakina\BlackBox\Database\TableInterface 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...
8
use HexMakina\BlackBox\Database\SelectInterface;
9
10
abstract class TableModel extends Crudites
11
{
12
13
    protected static TableInterface $table;
14
15
16
    //check all primary keys are set (FIXME that doesn't work unles AIPK.. nice try)
17
    public function isNew(): bool
18
    {
19
        $match = static::table()->primaryKeysMatch(get_object_vars($this));
20
        return empty($match);
21
    }
22
23
    public function getId($mode = null)
24
    {
25
        trigger_error('getId() is deprecated and should not be used anymore. Please use the id() or pk() instead.', E_USER_DEPRECATED);
26
    
27
        $primary_key = static::table()->autoIncrementedPrimaryKey();
28
        if (is_null($primary_key) && count($pks = static::table()->primaryKeys()) == 1) {
29
            $primary_key = current($pks);
30
        }
31
32
        return $mode === 'name' ? $primary_key->name() : $this->get($primary_key->name());
33
    }
34
35
    public function pk()
36
    {
37
        $primary_key = static::table()->autoIncrementedPrimaryKey();
38
        if (is_null($primary_key) && count($pks = static::table()->primaryKeys()) == 1) {
39
            $primary_key = current($pks);
40
        }
41
42
        return $this->get($primary_key->name());
43
    }
44
45
    public function id()
46
    {
47
        return $this->get('id');
48
    }
49
50
    public function get($prop_name)
51
    {
52
        if (property_exists($this, $prop_name)) {
53
            return $this->$prop_name;
54
        }
55
56
        return null;
57
    }
58
59
    public function set($prop_name, $value): void
60
    {
61
        $this->$prop_name = $value;
62
    }
63
64
    public function import($assoc_data): self
65
    {
66
        if (!is_array($assoc_data)) {
67
            throw new \Exception(__FUNCTION__ . '(assoc_data) parm is not an array');
68
        }
69
70
        // shove it all up in model, god will sort them out
71
        foreach ($assoc_data as $field => $value) {
72
            $this->set($field, $value);
73
        }
74
75
        return $this;
76
    }
77
78
79
    public static function table(): TableInterface
80
    {
81
        return static::$database->table(static::relationalMappingName());
0 ignored issues
show
Bug introduced by
The property database is declared private in HexMakina\Crudites\Crudites and cannot be accessed from this context.
Loading history...
82
    }
83
84
    /**
85
     * The relationalMappingName() function returns a string, the the name of 
86
     * the table in the database that corresponds to the current model
87
     * 
88
     * The function returns one of the following:
89
     *  - The value of the TABLE_NAME constant, if it is defined in the model class
90
     *  - The value of a constant named TABLE_<ClassName>, if it is defined()
91
     *  - The lowercase name of the model class if neither constants are defined
92
     */
93
    public static function relationalMappingName(): string
94
    {
95
        $reflectionClass = new \ReflectionClass(get_called_class());
96
        $called_class = new \ReflectionClass(get_called_class());
0 ignored issues
show
Unused Code introduced by
The assignment to $called_class is dead and can be removed.
Loading history...
97
98
        $table_name = $reflectionClass->getConstant('TABLE_NAME');
99
100
        if ($table_name === false) {
101
            $shortName = $reflectionClass->getShortName();
102
            $table_name = defined($const_name = 'TABLE_' . strtoupper($shortName)) ? constant($const_name) : strtolower($shortName);
103
        }
104
105
        return $table_name;
106
        $table_name = $called_class->getConstant('TABLE_NAME');
0 ignored issues
show
Unused Code introduced by
$table_name = $called_cl...tConstant('TABLE_NAME') is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
107
        if($table_name !== false)
108
            return $table_name;
109
110
        $class_name = $called_class->getShortName();
111
        
112
        if (defined($const_name = 'TABLE_' . strtoupper($class_name)))
113
            return constant($const_name);
114
        
115
        return strtolower($class_name);
116
    }
117
118
119
    public function to_table_row($operator_id = null)
120
    {
121
        if (!is_null($operator_id) && $this->isNew() && is_null($this->get('created_by'))) {
122
            $this->set('created_by', $operator_id);
123
        }
124
125
        $model_data = get_object_vars($this);
126
127
        // 1. Produce OR restore a row
128
        $table_row = $this->isNew() ? static::table()->produce($model_data) : static::table()->restore($model_data);
129
130
        // 2. Apply alterations from form_model data
131
        $table_row->alter($model_data);
132
133
        return $table_row;
134
    }
135
136
    // success: return PK-indexed array of results (associative array or object)
137
    public static function retrieve(SelectInterface $select): array
138
    {
139
        $ret = [];
140
        $pk_name = implode('_', array_keys($select->table()->primaryKeys()));
141
142
        if (count($pks = $select->table()->primaryKeys()) > 1) {
143
            $concat_pk = sprintf('CONCAT(%s) as %s', implode(',', $pks), $pk_name);
144
            $select->selectAlso([$concat_pk]);
145
        }
146
147
        try {
148
            $select->run();
149
        } catch (CruditesException $e) {
150
            return [];
151
        }
152
153
        if ($select->isSuccess()) {
154
            foreach ($select->retObj(get_called_class()) as $rec) {
155
                  $ret[$rec->get($pk_name)] = $rec;
156
            }
157
        }
158
159
        return $ret;
160
    }
161
162
163
    private static function actionnableParams($arg1, $arg2 = null): array
164
    {
165
        $unique_identifiers = null;
166
        
167
        $table = get_called_class()::table();
168
169
        // case 3
170
        if(is_array($arg1) && !empty($arg1))
171
        {
172
            $unique_identifiers = $arg1;
173
        }
174
175
        // case 2
176
        else if (is_string($arg1) && is_scalar($arg2))
177
        {   
178
            $unique_identifiers = [$arg1 => $arg2];
179
        }
180
181
        // case 1
182
        else if (is_scalar($arg1) && count($table->primaryKeys()) === 1)
183
        {   
184
            $pk = current($table->primaryKeys())->name();
185
            $unique_identifiers = [$pk => $arg1];
186
        } 
187
        else
188
            throw new CruditesException('ARGUMENTS_ARE_NOT_ACTIONNABLE');
189
190
191
        // Find the unique identifier(s) in the database.
192
        $unique_identifiers = $table->matchUniqueness($unique_identifiers);
193
        if (empty($unique_identifiers)) {
194
            throw new CruditesException('UNIQUE_IDENTIFIER_NOT_FOUND');
195
        }
196
197
        return $unique_identifiers;
198
    }
199
200
201
    /**
202
     * Retrieve a single instance of the model by its unique identifier(s).
203
     * Throws CruditesException if the unique identifier yields no or multiple instances.
204
     *
205
     * @param mixed $arg1 The value of the primary key or an array of column-value pairs.
206
     * @param mixed|null $arg2 The value of the primary key if $arg1 is a string, otherwise null.
207
     * 
208
     * @return mixed The retrieved instance of the model.
209
     * 
210
     * @throws CruditesException If the arguments are not actionable, the unique identifier is not found, or multiple instances are found.
211
     * 
212
     * USAGE
213
     *  Case 1:  Class::one($primary_key_value)
214
     *  Case 2:  Class::one($unique_column, $value)
215
     *  Case 3:  Class::one([$unique_column => $value, $unique_column2 => $value2])
216
     * 
217
     */
218
    public static function one($arg1, $arg2 = null): self
219
    {
220
        $unique_identifiers = static::actionnableParams($arg1, $arg2);
221
        // vd($arg1, 'arg1');
222
        // vd($arg2, 'arg2');
223
        // vd($unique_identifiers, static::class);
224
225
        $records = static::any($unique_identifiers);
226
        switch (count($records)) {
227
            case 0:
228
                throw new CruditesException('NO_INSTANCE_MATCH_UNIQUE_IDENTIFIERS');
229
230
            case 1:
231
                return current($records);
232
233
            default:
234
                throw new CruditesException('MULTIPLE_INSTANCES_MATCH_UNIQUE_IDENTIFIERS');
235
        }
236
    }
237
238
    /**
239
     * Attempts to retrieve a single instance of the model by its unique identifier(s).
240
     * If no instance is found, returns null.
241
     */
242
243
    public static function exists($arg1, $arg2 = null): ?self
244
    {
245
        try {
246
            return self::one($arg1, $arg2);
247
        } 
248
        catch (CruditesException $e) {
249
            return null;
250
        }
251
    }
252
253
    public static function any($field_exact_values=[], $options = [])
254
    {
255
        $select = static::filter($field_exact_values, $options);
256
        return static::retrieve($select);
257
    }
258
259
    
260
    public static function filter($filters = [], $options = []): SelectInterface
261
    {
262
        $query = (new TableModelSelector(get_called_class()))->select($filters, $options);
263
        return $query;
264
265
        // $query = static::query_retrieve($filters, $options);
266
        // return static::retrieve($query);
267
    }
268
269
    public static function count($filters = [], $options = []): int
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

269
    public static function count($filters = [], /** @scrutinizer ignore-unused */ $options = []): int

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
270
    {
271
        $query = static::filter($filters, ['eager' => false]);
272
        $query->columns(['COUNT(*) as counter']);
273
        $res = static::retrieve($query);
274
        $res = array_pop($res);
275
        return (int)$res->counter;
276
    }
277
278
    public static function listing($filters = [], $options = []): array
279
    {
280
        return static::retrieve(static::filter($filters, $options)); // listing as arrays for templates
281
    }
282
283
284
285
    public static function get_many_by_AIPK($aipk_values): ?array
286
    {
287
        if (empty($aipk_values)) {
288
            return null;
289
        }
290
        if (is_null($AIPK = static::table()->autoIncrementedPrimaryKey())) {
291
            return null;
292
        }
293
        return static::retrieve(static::table()->select()->whereNumericIn($AIPK, $aipk_values));
294
    }
295
}
296