HasAndBelongsToMany::saveConnections()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 7
ccs 0
cts 5
cp 0
crap 6
rs 10
1
<?php
2
3
namespace Nip\Records\Relations;
4
5
use Nip\Database\Query\AbstractQuery;
6
use Nip\Database\Query\Delete as DeleteQuery;
7
use Nip\Database\Query\Insert as InsertQuery;
8
use Nip\Database\Query\Select as SelectQuery;
9
use Nip\HelperBroker;
10
use Nip\Records\Collections\Collection as RecordCollection;
11
use Nip\Records\Record;
12
use Nip\Records\Relations\Traits\HasPivotTable;
13
14
/**
15
 * Class HasAndBelongsToMany
16
 * @package Nip\Records\Relations
17
 */
18
class HasAndBelongsToMany extends HasOneOrMany
19
{
20
    use HasPivotTable;
21
22
    /**
23
     * @var string
24
     */
25
    protected $type = 'hasAndBelongsToMany';
26
27
    /**
28
     * @var null
29
     */
30
    protected $joinFields = null;
31
32
    /**
33
     * @inheritdoc
34
     */
35
    public function addParams($params)
36
    {
37
        parent::addParams($params);
38
        $this->addPivotParams($params);
39
    }
40
41
    /** @noinspection PhpMissingParentCallCommonInspection
42
     * @return SelectQuery
43
     * @throws \Exception
44
     */
45 1
    public function newQuery()
46
    {
47 1
        $query = $this->getDB()->newSelect();
48
49 1
        $query->from($this->getWith()->getFullNameTable());
0 ignored issues
show
Bug introduced by
$this->getWith()->getFullNameTable() of type string is incompatible with the type array expected by parameter $| of Nip\Database\Query\AbstractQuery::from(). ( Ignorable by Annotation )

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

49
        $query->from(/** @scrutinizer ignore-type */ $this->getWith()->getFullNameTable());
Loading history...
50 1
        $query->from($this->getDB()->getDatabase() . '.' . $this->getTable());
51
52 1
        foreach ($this->getWith()->getFields() as $field) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getWith()->getFields() targeting Nip\Records\AbstractMode...ordManager::getFields() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
The expression $this->getWith()->getFields() of type null is not traversable.
Loading history...
53 1
            $query->cols(["{$this->getWith()->getTable()}.$field", $field]);
54
        }
55
56 1
        foreach ($this->getJoinFields() as $field) {
57 1
            $query->cols(["{$this->getTable()}.$field", "__$field"]);
58
        }
59
60 1
        $this->hydrateQueryWithPivotConstraints($query);
61
62 1
        $order = $this->getParam('order');
63 1
        if (is_array($order)) {
0 ignored issues
show
introduced by
The condition is_array($order) is always false.
Loading history...
64
            foreach ($order as $item) {
65
                $query->order([$item[0], $item[1]]);
66
            }
67
        }
68
69 1
        return $query;
70
    }
71
72
    /**
73
     * @return null|array
74
     */
75 1
    protected function getJoinFields()
76
    {
77 1
        if ($this->joinFields == null) {
78
            $this->initJoinFields();
79
        }
80
81 1
        return $this->joinFields;
82
    }
83
84
    /**
85
     * @param null $joinFields
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $joinFields is correct as it would always require null to be passed?
Loading history...
86
     */
87 1
    public function setJoinFields($joinFields)
88
    {
89 1
        $this->joinFields = $joinFields;
90 1
    }
91
92
    protected function initJoinFields()
93
    {
94
        $structure = $this->getDB()->getMetadata()->describeTable($this->getTable());
95
        $this->setJoinFields(array_keys($structure["fields"]));
96
    }
97
98
    /**
99
     * @inheritdoc
100
     */
101
    public function populateQuerySpecific(AbstractQuery $query)
102
    {
103
        $pk1 = $this->getPrimaryKey();
104
        $fk1 = $this->getFK();
105
106
        $query->where("`{$this->getTable()}`.`$fk1` = ?", $this->getItem()->{$pk1});
107
108
        return $query;
109
    }
110
111
    /**
112
     * Simple select query from the link table
113
     * @param bool $specific
114
     * @return SelectQuery
115
     */
116
    public function getLinkQuery($specific = true)
117
    {
118
        $query = $this->getDB()->newSelect();
119
        $query->from($this->getTable());
0 ignored issues
show
Bug introduced by
$this->getTable() of type string is incompatible with the type array expected by parameter $| of Nip\Database\Query\AbstractQuery::from(). ( Ignorable by Annotation )

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

119
        $query->from(/** @scrutinizer ignore-type */ $this->getTable());
Loading history...
120
121
        if ($specific) {
122
            $query = $this->populateQuerySpecific($query);
123
        }
124
125
        return $query;
126
    }
127
128
    /** @noinspection PhpMissingParentCallCommonInspection
129
     * @param RecordCollection $collection
130
     * @return RecordCollection
131
     */
132
    public function getEagerResults($collection)
133
    {
134
        if ($collection->count() < 1) {
135
            return $this->getWith()->newCollection();
136
        }
137
138
        $query = $this->getEagerQuery($collection);
139
140
        $return = $this->newCollection();
141
        $results = $this->getDB()->execute($query);
142
        if ($results->numRows() > 0) {
143
            $i = 1;
144
            $rows = $results->fetchResults();
145
            foreach ($rows as $row) {
146
                $row['relation_key'] = $i++;
147
                $item = $this->getWith()->getNew($row);
148
                $return->add($item, 'relation_key');
149
            }
150
        }
151
152
        return $return;
153
    }
154
155
    /** @noinspection PhpMissingParentCallCommonInspection
156
     * @return $this
157
     */
158
    public function save()
159
    {
160
        $this->deleteConnections();
161
        $this->saveConnections();
162
163
        return $this;
164
    }
165
166
    protected function deleteConnections()
167
    {
168
        $query = $this->newDeleteQuery();
169
        $query->where(
170
            "{$this->getFK()} = ?",
171
            $this->getItemRelationPrimaryKey()
172
        );
173
//        echo $query;
174
        $query->execute();
175
    }
176
177
    /**
178
     * @return DeleteQuery
179
     */
180
    protected function newDeleteQuery()
181
    {
182
        $query = $this->getDB()->newDelete();
183
        $query->table($this->getTable());
0 ignored issues
show
Bug introduced by
$this->getTable() of type string is incompatible with the type array expected by parameter $| of Nip\Database\Query\AbstractQuery::table(). ( Ignorable by Annotation )

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

183
        $query->table(/** @scrutinizer ignore-type */ $this->getTable());
Loading history...
184
        return $query;
185
    }
186
187
    protected function saveConnections()
188
    {
189
        if ($this->hasResults()) {
190
            $query = $this->newInsertQuery();
191
            $this->queryAttachRecords($query, $this->getResults());
192
//            echo $query;
193
            $query->execute();
194
        }
195
    }
196
197
    /**
198
     * @return InsertQuery
199
     */
200
    protected function newInsertQuery()
201
    {
202
        $query = $this->getDB()->newInsert();
203
        $query->table($this->getTable());
0 ignored issues
show
Bug introduced by
$this->getTable() of type string is incompatible with the type array expected by parameter $| of Nip\Database\Query\AbstractQuery::table(). ( Ignorable by Annotation )

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

203
        $query->table(/** @scrutinizer ignore-type */ $this->getTable());
Loading history...
204
        return $query;
205
    }
206
207
    /**
208
     * @param InsertQuery $query
209
     * @param $records
210
     */
211
    protected function queryAttachRecords($query, $records)
212
    {
213
        foreach ($records as $record) {
214
            $data = $this->formatAttachData($record);
215
            foreach ($this->getJoinFields() as $field) {
216
                if ($record->{"__$field"}) {
217
                    $data[$field] = $record->{"__$field"};
218
                } else {
219
                    $data[$field] = $data[$field] ? $data[$field] : false;
220
                }
221
            }
222
            $query->data($data);
223
        }
224
    }
225
226
    /**
227
     * @param $record
228
     * @return array
229
     */
230
    protected function formatAttachData($record)
231
    {
232
        $data = [
233
            $this->getManager()->getPrimaryFK() => $this->getItem()->{$this->getManager()->getPrimaryKey()},
234
            $this->getPivotFK() => $record->{$this->getWith()->getPrimaryKey()},
235
        ];
236
        return $data;
237
    }
238
239
    /**
240
     * @param $model
241
     */
242
    public function attach($model)
243
    {
244
        $query = $this->newInsertQuery();
245
        $this->queryAttachRecords($query, [$model]);
246
//            echo $query;
247
        $query->execute();
248
    }
249
250
    /**
251
     * @param Record $model
252
     */
253
    public function detach($model)
254
    {
255
        $query = $this->newDeleteQuery();
256
        $this->queryDetachRecords($query, [$model]);
257
//        echo $query;
258
        $query->execute();
259
    }
260
261
    /**
262
     * @param DeleteQuery $query
263
     * @param $records
264
     */
265
    protected function queryDetachRecords($query, $records)
266
    {
267
        $ids = HelperBroker::get('Arrays')->pluck($records, $this->getWith()->getPrimaryKey());
0 ignored issues
show
Bug introduced by
The method pluck() does not exist on Nip\Helpers\AbstractHelper. It seems like you code against a sub-type of Nip\Helpers\AbstractHelper such as Nip_Helper_Url or Nip_Helper_Arrays or Nip\Helpers\View\Stylesheets or Nip\Helpers\View\Strings or Nip\Helpers\View\Paginator or Nip\Helpers\View\Arrays or Nip\Helpers\View\Icontext or Nip\Helpers\View\Color or Nip\Helpers\View\Scripts or Nip\Helpers\View\Url. ( Ignorable by Annotation )

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

267
        $ids = HelperBroker::get('Arrays')->/** @scrutinizer ignore-call */ pluck($records, $this->getWith()->getPrimaryKey());
Loading history...
268
        $query->where(
269
            "{$this->getPivotFK()} IN ?",
270
            $ids
271
        );
272
273
        $query->where(
274
            "{$this->getFK()} = ?",
275
            $this->getItemRelationPrimaryKey()
276
        );
277
    }
278
279
280
    /** @noinspection PhpMissingParentCallCommonInspection
281
     * @return mixed
282
     */
283
    public function getWithClass()
284
    {
285
        return $this->getName();
286
    }
287
288
    /** @noinspection PhpMissingParentCallCommonInspection
289
     * @return string
290
     */
291
    protected function getDictionaryKey()
292
    {
293
        return '__' . $this->getFK();
294
    }
295
}
296