Passed
Push — main ( d0474b...4f9f31 )
by Sammy
01:40
created

TableModel::filter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace HexMakina\TightORM;
4
5
use HexMakina\Crudites\Crudites;
6
use HexMakina\Crudites\CruditesException;
7
8
use HexMakina\Crudites\Interfaces\TableManipulationInterface;
9
use HexMakina\Crudites\Interfaces\SelectInterface;
10
11
abstract class TableModel extends Crudites
12
{
13
14
    //check all primary keys are set (FIXME that doesn't work unles AIPK.. nice try)
15
    public function is_new(): bool
16
    {
17
        $match = static::table()->primary_keys_match(get_object_vars($this));
18
        return empty($match);
19
    }
20
21
    public function get_id($mode = null)
22
    {
23
        $primary_key = static::table()->auto_incremented_primary_key();
24
        if (is_null($primary_key) && count($pks = static::table()->primary_keys()) == 1) {
25
            $primary_key = current($pks);
26
        }
27
28
        return $mode === 'name' ? $primary_key->name() : $this->get($primary_key->name());
29
    }
30
31
    public function get($prop_name)
32
    {
33
        if (property_exists($this, $prop_name) === true) {
34
            return $this->$prop_name;
35
        }
36
37
        return null;
38
    }
39
40
    public function set($prop_name, $value)
41
    {
42
        $this->$prop_name = $value;
43
    }
44
45
    public function import($assoc_data)
46
    {
47
        if (!is_array($assoc_data)) {
48
            throw new \Exception(__FUNCTION__ . '(assoc_data) parm is not an array');
49
        }
50
51
        // shove it all up in model, god will sort them out
52
        foreach ($assoc_data as $field => $value) {
53
            $this->set($field, $value);
54
        }
55
56
        return $this;
57
    }
58
59
    public static function table(): TableManipulationInterface
60
    {
61
        $table = static::table_name();
62
        $table = self::inspect($table);
63
64
        return $table;
65
    }
66
67
    public static function table_name(): string
68
    {
69
        $reflect = new \ReflectionClass(get_called_class());
70
71
        $table_name = $reflect->getConstant('TABLE_NAME');
72
73
        if ($table_name === false) {
74
            $calling_class = $reflect->getShortName();
75
            if (defined($const_name = 'TABLE_' . strtoupper($calling_class))) {
76
                $table_name = constant($const_name);
77
            } else {
78
                $table_name = strtolower($calling_class);
79
            }
80
        }
81
82
        return $table_name;
83
    }
84
85
86
    public function to_table_row($operator_id = null)
87
    {
88
        if (!is_null($operator_id) && $this->is_new() && is_null($this->get('created_by'))) {
89
            $this->set('created_by', $operator_id);
90
        }
91
92
        $model_data = get_object_vars($this);
93
94
        // 1. Produce OR restore a row
95
        if ($this->is_new()) {
96
            $table_row = static::table()->produce($model_data);
97
        } else {
98
            $table_row = static::table()->restore($model_data);
99
        }
100
101
        // 2. Apply alterations from form_model data
102
        $table_row->alter($model_data);
103
104
        return $table_row;
105
    }
106
107
    // DEPRECATED, only exist for unit testing vis-a-vis TightModelSelector
108
    public static function query_retrieve($filters = [], $options = []): SelectInterface
109
    {
110
      $class = get_called_class();
111
      $table = $class::table();
112
113
      $Query = $table->select(null, $class::table_alias());
114
115
116
      if(!isset($options['eager']) || $options['eager'] !== false)
117
      {
118
        $Query->eager();
119
      }
120
121
122
      foreach($table->columns() as $column_name => $column)
123
      {
124
        if(isset($filters[$column_name]) && is_string($filters[$column_name]))
125
          $Query->aw_eq($column_name, $filters[$column_name]);
126
      }
127
128
      if(is_subclass_of($event = new $class(), '\HexMakina\kadro\Models\Interfaces\EventInterface'))
129
      {
130
        if(!empty($filters['date_start']))
131
          $Query->aw_gte($event->event_field(), $filters['date_start'], $Query->table_label(), ':filter_date_start');
132
133
        if(!empty($filters['date_stop']))
134
          $Query->aw_lte($event->event_field(), $filters['date_stop'], $Query->table_label(), ':filter_date_stop');
135
136
        if(empty($options['order_by']))
137
          $Query->order_by([$event->event_field(), 'DESC']);
138
      }
139
140
      if(isset($filters['content'])) $Query->aw_filter_content($filters['content']);
141
142
      if(isset($filters['ids']))
143
      {
144
        if(empty($filters['ids']))
145
          $Query->and_where('1=0'); // TODO: this is a new low.. find another way to cancel query
146
        else $Query->aw_numeric_in('id', $filters['ids'], $Query->table_label());
147
      }
148
149
      if(isset($options['order_by'])) // TODO commenting required about the array situation
150
      {
151
        $order_by = $options['order_by'];
152
153
        if(is_string($order_by))
154
          $Query->order_by($order_by);
155
156
        elseif(is_array($order_by))
157
          foreach($options['order_by'] as $order_by)
158
          {
159
            if(!isset($order_by[2]))
160
              array_unshift($order_by, '');
161
162
            list($order_table, $order_field, $order_direction) = $order_by;
163
            $Query->order_by([$order_table ?? '', $order_field, $order_direction]);
164
          }
165
      }
166
167
      if(isset($options['limit']) && is_array($options['limit']))
168
        $Query->limit($options['limit'][1], $options['limit'][0]);
169
170
      return $Query;
171
    }
172
173
174
175
    // success: return PK-indexed array of results (associative array or object)
176
    public static function retrieve(SelectInterface $Query): array
177
    {
178
        $ret = [];
179
        $pk_name = implode('_', array_keys($Query->table()->primary_keys()));
180
181
        if (count($pks = $Query->table()->primary_keys()) > 1) {
182
            $concat_pk = sprintf('CONCAT(%s) as %s', implode(',', $pks), $pk_name);
183
            $Query->select_also([$concat_pk]);
184
        }
185
186
        try {
187
            $Query->run();
188
        } catch (CruditesException $e) {
189
            return [];
190
        }
191
192
        if ($Query->is_success()) {
193
            foreach ($Query->ret_obj(get_called_class()) as $rec) {
194
                  $ret[$rec->get($pk_name)] = $rec;
195
            }
196
        }
197
198
        return $ret;
199
    }
200
201
    /* USAGE
202
    * one($primary_key_value)
203
    * one($unique_column, $value)
204
    */
205
    public static function one($arg1, $arg2 = null)
206
    {
207
        $mixed_info = is_null($arg2) ? $arg1 : [$arg1 => $arg2];
208
209
        $unique_identifiers = get_called_class()::table()->match_uniqueness($mixed_info);
210
211
        if (empty($unique_identifiers)) {
212
            throw new CruditesException('UNIQUE_IDENTIFIER_NOT_FOUND');
213
        }
214
215
        $Query = static::query_retrieve([], ['eager' => true])->aw_fields_eq($unique_identifiers);
216
        switch (count($res = static::retrieve($Query))) {
217
            case 0:
218
                throw new CruditesException('INSTANCE_NOT_FOUND');
219
            case 1:
220
                return current($res);
221
            default:
222
                throw new CruditesException('SINGULAR_INSTANCE_ERROR');
223
        }
224
    }
225
226
    public static function exists($arg1, $arg2 = null)
227
    {
228
        try {
229
            return self::one($arg1, $arg2);
230
        } catch (CruditesException $e) {
231
            return null;
232
        }
233
    }
234
235
236
    public static function any($field_exact_values, $options = [])
237
    {
238
        $Query = static::query_retrieve([], $options)->aw_fields_eq($field_exact_values);
239
        return static::retrieve($Query);
240
    }
241
242
    public static function filter($filters = [], $options = []): array
243
    {
244
        return static::retrieve(static::query_retrieve($filters, $options));
245
    }
246
247
    public static function listing($filters = [], $options = []): array
248
    {
249
        return static::retrieve(static::query_retrieve($filters, $options)); // listing as arrays for templates
250
    }
251
252
253
254
    public static function get_many_by_AIPK($aipk_values)
255
    {
256
        if (!empty($aipk_values) && !is_null($AIPK = static::table()->auto_incremented_primary_key())) {
257
            return static::retrieve(static::table()->select()->aw_numeric_in($AIPK, $aipk_values));
258
        }
259
260
        return null;
261
    }
262
263
264
}
265