Completed
Push — master ( a812dc...4bd335 )
by Oscar
02:45
created

SimpleCrud::save()   C

Complexity

Conditions 7
Paths 18

Size

Total Lines 32
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 18
nc 18
nop 2
1
<?php
2
3
namespace Folk\Entities;
4
5
use Folk\SearchQuery;
6
use SimpleCrud\Row;
7
use SimpleCrud\Scheme\Scheme;
8
9
abstract class SimpleCrud extends AbstractEntity implements EntityInterface
10
{
11
    protected $searchFields;
12
    protected $firstField;
13
14
    /**
15
     * Returns the simple-crud table.
16
     * 
17
     * @return \SimpleCrud\Table
18
     */
19
    abstract protected function getTable();
20
21
    /**
22
     * Generates the query to search rows.
23
     * 
24
     * @param SearchQuery $search
25
     * 
26
     * @return \SimpleCrud\Queries\Query
27
     */
28
    protected function getQuery(SearchQuery $search)
29
    {
30
        $table = $this->getTable();
31
32
        $query = $table->select();
33
34
        //Filter by id
35
        if (count($search->getIds())) {
36
            $query->byId($search->getIds());
37
        }
38
39
        if ($search->getPage() !== null) {
40
            $limit = $search->getLimit();
41
42
            $query->offset(($search->getPage() * $limit) - $limit)->limit($limit);
43
        }
44
45
        if ($this->searchFields === null) {
46
            $this->searchFields = [$this->getFirstField()];
47
        }
48
49
        $orderBy = $search->getSort();
50
51
        if (!empty($orderBy) && isset($table->getScheme()['fields'][$orderBy])) {
52
            $query->orderBy("`{$table->name}`.`{$orderBy}`", $search->getDirection());
53
        } else {
54
            $query->orderBy("`{$table->name}`.`id`", 'DESC');
55
        }
56
57
        //Filter by words
58
        foreach ($search->getWords() as $k => $word) {
59
            foreach ($this->searchFields as $field) {
60
                $query->orWhere("`{$table->name}`.`{$field}` LIKE :w{$k}", [":w{$k}" => "%{$word}%"]);
61
            }
62
        }
63
64
        //Filter by relations
65
        $db = $table->getDatabase();
66
67
        foreach ($search->getConditions() as $name => $value) {
68
            $related = $db->$name
69
                ->select()
70
                ->by('id', $value)
71
                ->run();
72
73
            $query->relatedWith($related);
74
        }
75
76
        return $query;
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function search(SearchQuery $search)
83
    {
84
        $result = [];
85
86
        foreach ($this->getQuery($search)->run() as $row) {
87
            $result[$row->id] = $row->toArray();
88
        }
89
90
        return $result;
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96
    public function create(array $data)
97
    {
98
        $row = $this->getTable()->create();
99
100
        $this->save($row, $data);
101
102
        return $row->id;
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108
    public function read($id)
109
    {
110
        $table = $this->getTable();
111
112
        $row = $table[$id];
113
114
        if (empty($row)) {
115
            return;
116
        }
117
118
        $relations = $table->getScheme()['relations'];
119
        $array = $row->toArray();
120
121
        foreach ($relations as $name => $relation) {
122
            if ($relation[0] === Scheme::HAS_MANY || $relation[0] === Scheme::HAS_MANY_TO_MANY) {
123
                $array[$name] = array_values($row->$name->id);
124
            }
125
        }
126
127
        return $array;
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function update($id, array $data)
134
    {
135
        $row = $this->getTable()[$id];
136
137
        $this->save($row, $data);
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143
    public function delete($id)
144
    {
145
        $table = $this->getTable();
146
147
        unset($table[$id]);
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153
    public function getLabel($id, array $data)
154
    {
155
        return "{$id} - ".$data[$this->getFirstField()];
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161
    protected function getFirstField()
162
    {
163
        if ($this->firstField === null) {
164
            foreach (array_keys($this->getTable()->getScheme()['fields']) as $field) {
165
                if ($field !== 'id') {
166
                    return $this->firstField = $field;
167
                }
168
            }
169
        }
170
171
        return $this->firstField;
172
    }
173
174
    /**
175
     * Save the data in the database.
176
     * 
177
     * @param Row   $row
178
     * @param array $data
179
     */
180
    protected function save(Row $row, array $data)
181
    {
182
        $table = $this->getTable();
183
        $db = $table->getDatabase();
184
        $scheme = $table->getScheme();
185
186
        foreach ($data as $name => $value) {
187
            if (isset($scheme['fields'][$name])) {
188
                $row->$name = $value;
189
            }
190
        }
191
192
        foreach ($data as $name => $value) {
193
            if (isset($scheme['relations'][$name])) {
194
                $unrelated = $row->$name()
195
                    ->where("`{$name}`.`id` NOT IN (:ids)", [':ids' => $value])
196
                    ->run();
197
198
                foreach ($unrelated as $r) {
199
                    $row->unrelate($r);
200
                }
201
202
                $rows = $db->$name->select()->by('id', $value)->run();
203
204
                foreach ($rows as $r) {
205
                    $row->relate($r);
206
                }
207
            }
208
        }
209
210
        $row->save();
211
    }
212
}
213