Completed
Pull Request — master (#24)
by Alexander
02:04
created

Model::table()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 1
nop 0
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace alkemann\h2l\traits;
4
5
use alkemann\h2l\Connections;
6
use alkemann\h2l\exceptions;
7
use alkemann\h2l\exceptions\ConfigMissing;
8
use alkemann\h2l\interfaces\Source;
9
10
/**
11
 * Class Model
12
 *
13
 * Use this for prototyping only, use a real ORM for production studd
14
 *
15
 * Depends on \alkemann\h2l\Entity trait
16
 *
17
 * @package alkemann\h2l
18
 */
19
trait Model
20
{
21
    /**
22
     * @throws ConfigMissing
23
     */
24
    public static function db(): Source
25
    {
26
        $name = isset(static::$connection) ? static::$connection : 'default';
0 ignored issues
show
Bug Best Practice introduced by
The property connection does not exist on alkemann\h2l\traits\Model. Did you maybe forget to declare it?
Loading history...
27
        return Connections::get($name);
28
    }
29
30
    private static function pk(): string
31
    {
32
        return isset(static::$pk) ? static::$pk : 'id';
0 ignored issues
show
Bug Best Practice introduced by
The property pk does not exist on alkemann\h2l\traits\Model. Did you maybe forget to declare it?
Loading history...
33
    }
34
35
    public function exists(): bool
36
    {
37
        // @TODO set a "read from db" property?
38
        $pk = static::pk();
39
        return isset($this->$pk) && $this->$pk;
40
    }
41
42
    private static function table(): string
43
    {
44
        if (!isset(static::$table)) {
45
            throw new ConfigMissing(
46
                get_called_class() . ' is missing static::$table',
0 ignored issues
show
Unused Code introduced by
The call to alkemann\h2l\exceptions\...gMissing::__construct() has too many arguments starting with get_called_class() . ' is missing static::$table'. ( Ignorable by Annotation )

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

46
            throw /** @scrutinizer ignore-call */ new ConfigMissing(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
47
                ConfigMissing::MISSING_TABLE
48
            );
49
        }
50
        return static::$table;
0 ignored issues
show
Bug Best Practice introduced by
The property table does not exist on alkemann\h2l\traits\Model. Did you maybe forget to declare it?
Loading history...
51
    }
52
53
    /**
54
     * @throws ConfigMissing
55
     * @throws \InvalidArgumentException
56
     */
57
    public static function get($id, array $conditions = [], array $options = []) //: ?Model
58
    {
59
        if (empty($conditions) === false) {
60
            throw new \InvalidArgumentException("Conditions is not implemented on get");
61
        }
62
        $pk = static::pk();
63
        $conditions[$pk] = $id;
64
        $result = static::db()->one(static::table(), $conditions, $options);
65
        if ($result) {
66
            return new static($result);
0 ignored issues
show
Unused Code introduced by
The call to alkemann\h2l\traits\Model::__construct() has too many arguments starting with $result. ( Ignorable by Annotation )

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

66
            return /** @scrutinizer ignore-call */ new static($result);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
67
        }
68
        return null;
69
    }
70
71
    /**
72
     * Find all records matching $conditions, returns a generator
73
     *
74
     * @throws ConfigMissing
75
     */
76
    public static function find(array $conditions = [], array $options = []): \Generator
77
    {
78
        $conditions = self::filterByFields($conditions);
79
        $with = array_key_exists('with', $options) ? (array)$options['with'] : false;
80
        unset($options['with']);
81
        $result = static::db()->find(static::table(), $conditions, $options);
82
        $pk = static::pk();
83
        $gen = function () use ($result, $pk, $with) {
84
            foreach ($result as $row) {
85
                $model = new static($row);
0 ignored issues
show
Unused Code introduced by
The call to alkemann\h2l\traits\Model::__construct() has too many arguments starting with $row. ( Ignorable by Annotation )

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

85
                $model = /** @scrutinizer ignore-call */ new static($row);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
86
                if ($with) {
87
                    $model->with(...$with);
88
                }
89
                $id = $row[$pk];
90
                yield $id => $model;
91
            }
92
        };
93
        return $gen();
94
    }
95
96
    /**
97
     * The implementation of this method will come from the Entity trait.
98
     *
99
     * @param string[] ...$relation_names list of names of relationships
100
     * @return object Instance of class that uses this trait
101
     */
102
    abstract public function with(string ...$relation_names);
103
    abstract public function reset(): void;
104
    abstract public function data(array $data = null): array;
105
106
    /**
107
     * Find all records matching `$conditions`, returns an array with key being the pk value
108
     *
109
     * @throws ConfigMissing
110
     */
111
    public static function findAsArray(array $conditions = [], array $options = []): array
112
    {
113
        $generator = static::find($conditions, $options);
114
        return iterator_to_array($generator);
115
    }
116
117
    public static function fields(): ?array
118
    {
119
        return isset(static::$fields) ? static::$fields : null;
0 ignored issues
show
Bug Best Practice introduced by
The property fields does not exist on alkemann\h2l\traits\Model. Did you maybe forget to declare it?
Loading history...
120
    }
121
122
    private static function filterByFields(array $data): array
123
    {
124
        $fields = static::fields();
125
        if (empty($fields) === false) {
126
            $data = array_filter(
127
                $data,
128
                function ($key) use ($fields) {
129
                    return in_array($key, $fields);
130
                },
131
                ARRAY_FILTER_USE_KEY
0 ignored issues
show
Bug introduced by
alkemann\h2l\traits\ARRAY_FILTER_USE_KEY of type integer is incompatible with the type integer expected by parameter $flag of array_filter(). ( Ignorable by Annotation )

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

131
                /** @scrutinizer ignore-type */ ARRAY_FILTER_USE_KEY
Loading history...
132
            );
133
        }
134
        return $data;
135
    }
136
137
    /**
138
     * @throws ConfigMissing
139
     */
140
    public function save(array $data = [], array $options = []): bool
141
    {
142
        $pk = static::pk();
143
        $db = static::db();
144
        $table = static::table();
145
146
        if ($this->exists()) {
147
            $id = $this->$pk;
148
            $data = self::filterByFields($data);
149
            unset($data[$pk]);
150
            $rows = $db->update($table, [$pk => $id], $data, $options);
151
            if (!$rows) {
152
                return false;
153
            }
154
        } else {
155
            $data += $this->data;
0 ignored issues
show
Bug Best Practice introduced by
The property data does not exist on alkemann\h2l\traits\Model. Did you maybe forget to declare it?
Loading history...
156
            $data = self::filterByFields($data);
157
            $id = $db->insert($table, $data, $options);
158
            if (!$id) {
159
                return false;
160
            }
161
        }
162
163
        $result = $db->one($table, [$pk => $id]);
164
        $this->reset();
165
        $this->data($result);
166
        return true;
167
    }
168
169
    /**
170
     * @throws exceptions\ConfigMissing
171
     */
172
    public function delete(array $options = []): bool
173
    {
174
        $pk = static::pk();
175
        return static::db()->delete(static::table(), [$pk => $this->$pk], $options);
176
    }
177
}
178