Completed
Push — master ( 498b52...c403d6 )
by Igor
01:18
created

FileBind::updateFiles()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 5

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 23
ccs 20
cts 20
cp 1
rs 8.5906
cc 5
eloc 15
nc 8
nop 3
crap 5
1
<?php
2
3
/**
4
 * @link https://github.com/rkit/filemanager-yii2
5
 * @copyright Copyright (c) 2015 Igor Romanov
6
 * @license [MIT](http://opensource.org/licenses/MIT)
7
 */
8
9
namespace rkit\filemanager\behaviors;
10
11
use Yii;
12
use yii\helpers\ArrayHelper;
13
use yii\db\Query;
14
15
class FileBind
16
{
17 21
    public function bind($model, $attribute, $files)
18
    {
19 21
        $newFiles = $this->newFiles($model, $attribute, $files);
20 21
        if (!count($newFiles)) {
21 2
            return false;
22
        }
23
24 20
        $currentFiles = $this->files($model, $attribute);
25 20
        $currentRelations = $this->relations($model, $attribute);
26 20
        $insertData = $this->prepareInsertRelations($model, $attribute, $newFiles);
27 20
        $updateData = $this->prepareUpdateRelations($model, $attribute, $newFiles, $currentRelations);
28
29 20
        $resultFiles = $insertData['files'] + $updateData['files'];
30 20
        if (!count($resultFiles)) {
31
            return false;
32
        }
33
34 20
        $this->delete($model, $attribute, array_diff_key($currentFiles, $resultFiles));
35 20
        $this->save($model, $attribute, $insertData, $updateData, $resultFiles);
36
37 20
        return $resultFiles;
38
    }
39
40 20
    private function save($model, $attribute, $insertData, $updateData, $resultFiles)
41
    {
42 20
        if (count($insertData['rows'])) {
43 20
            $this->insertRelations($model, $attribute, $insertData['rows'], $insertData['columns']);
44 20
        }
45 20
        if (count($updateData['rows'])) {
46 2
            $this->updateRelations($model, $attribute, $updateData['rows']);
47 2
        }
48 20
        if (count($resultFiles)) {
49 20
            $this->updateFiles($model, $attribute, $resultFiles);
50 20
        }
51 20
    }
52
53 21
    private function newFiles($model, $attribute, $fileIds)
54
    {
55 21
        $relation = $model->fileRelation($attribute);
56 21
        $fileModel = $relation->modelClass;
57
58 21
        return $fileModel::find()
59 21
            ->where([key($relation->link) => $fileIds])
60 21
            ->indexBy(key($relation->link))
61 21
            ->all();
62
    }
63
64 20
    private function prepareInsertRelations($model, $attribute, $newFiles)
65
    {
66 20
        $ownerId = $model->getPrimaryKey();
67 20
        $relation = $model->fileRelation($attribute);
68 20
        $uploadedFiles = $model->fileState($attribute);
69 20
        $handlerExtraFields = $model->fileOption($attribute, 'extraFields');
70
71 20
        $files = [];
72 20
        $rows = [];
73 20
        $extraFields = [];
74 20
        foreach ($uploadedFiles as $fileId) {
75 20
            if (isset($newFiles[$fileId])) {
76 20
                $file = $newFiles[$fileId];
77 20
                $row = [$ownerId, $fileId];
78 20
                if ($handlerExtraFields) {
79
                    $fields = [
80 20
                        key($relation->via->link) => $ownerId,
81 20
                        current($relation->link) => $fileId,
82 20
                    ];
83 20
                    $extraFields = $handlerExtraFields($file, $fields);
84 20
                    $row = array_merge($row, array_values($extraFields));
85 20
                }
86 20
                $rows[] = $row;
87 20
                $files[$file->getPrimaryKey()] = $file;
88 20
            }
89 20
        }
90
91 20
        $columns = [key($relation->via->link), current($relation->link)];
92 20
        $columns = array_merge($columns, array_keys($extraFields));
93
94 20
        return ['rows' => $rows, 'files' => $files, 'columns' => $columns];
95
    }
96
97 20
    private function prepareUpdateRelations($model, $attribute, $newFiles, $currentRelations)
98
    {
99 20
        $relation = $model->fileRelation($attribute);
100 20
        $handlerExtraFields = $model->fileOption($attribute, 'extraFields');
101
102 20
        $files = [];
103 20
        $rows = [];
104 20
        foreach ($currentRelations as $fields) {
105 4
            if (isset($newFiles[$fields[current($relation->link)]])) {
106 3
                $file = $newFiles[$fields[current($relation->link)]];
107 3
                if ($handlerExtraFields) {
108 3
                    $extraFields = $handlerExtraFields($file, $fields);
109 3
                    $fieldChanged = (bool)count(array_diff_assoc($extraFields, $fields));
110 3
                    if ($fieldChanged) {
111 2
                        $rows[$file->getPrimaryKey()] = $extraFields;
112 2
                    }
113 3
                }
114 3
                $files[$file->getPrimaryKey()] = $file;
115 3
            }
116 20
        }
117 20
        return ['rows' => $rows, 'files' => $files];
118
    }
119
120 20
    private function insertRelations($model, $attribute, $rows, $columns)
121
    {
122 20
        $relation = $model->fileRelation($attribute);
123 20
        Yii::$app->getDb()->createCommand()
124 20
            ->batchInsert($relation->via->from[0], $columns, $rows)
125 20
            ->execute();
126 20
    }
127
128 2
    private function updateRelations($model, $attribute, $rows)
129
    {
130 2
        $relation = $model->fileRelation($attribute);
131 2
        $ownerId = $model->getPrimaryKey();
132 2
        $db = Yii::$app->getDb()->createCommand();
133
134 2
        foreach ($rows as $fileId => $row) {
135 2
            $db->update($relation->via->from[0], $row, [
136 2
                key($relation->via->link) => $ownerId,
137 2
                current($relation->link) => $fileId
138 2
            ])->execute();
139 2
        }
140 2
    }
141
142 20
    private function updateFiles($model, $attribute, $files)
143
    {
144 20
        $handlerUpdateFile = $model->fileOption($attribute, 'updateFile');
145 20
        $relation = $model->fileOption($attribute, 'relation');
146 20
        $isMultiple = $model->fileOption($attribute, 'multiple');
147
148 20
        $relationValue = [];
149 20
        foreach ($files as $file) {
150 20
            $relationValue[] = $file;
151 20
            if ($handlerUpdateFile) {
152 20
                $fileUpd = $handlerUpdateFile($file);
153 20
                $dirtyAttributes = $fileUpd->getDirtyAttributes();
154 20
                if (count($dirtyAttributes)) {
155 1
                    $fileUpd->updateAttributes($dirtyAttributes);
156 1
                }
157 20
            }
158 20
        }
159
160 20
        if (!$isMultiple) {
161 14
            $relationValue = array_shift($relationValue);
162 14
        }
163 20
        $model->populateRelation($relation, $relationValue);
164 20
    }
165
166 21
    public function delete($model, $attribute, $files)
167
    {
168 21
        $relation = $model->fileRelation($attribute);
169 21
        $storage = $model->fileStorage($attribute);
170 21
        $presets = array_keys($model->fileOption($attribute, 'preset', []));
171 21
        $handlerTemplatePath = $model->fileOption($attribute, 'templatePath');
172
173 21
        $db = Yii::$app->getDb()->createCommand();
174 21
        foreach ($files as $file) {
175 5
            foreach ($presets as $preset) {
176 4
                $thumbPath = $model->thumbPath($attribute, $preset, $file);
177 4
                $filePath = str_replace($storage->path, '', $thumbPath);
178 4
                if ($storage->has($filePath)) {
179 4
                    $storage->delete($filePath);
180 4
                }
181 4
            }
182
183 4
            if ($file->delete()) {
184 4
                $db->delete($relation->via->from[0], [
185 4
                    current($relation->link) => $file->getPrimaryKey()
186 4
                ])->execute();
187 4
                $filePath = $handlerTemplatePath($file);
188 4
                if ($storage->has($filePath)) {
189 4
                    $storage->delete($filePath);
190 4
                }
191 4
            }
192 21
        }
193 21
    }
194
195 20
    public function relations($model, $attribute)
196
    {
197 20
        $relation = $model->fileRelation($attribute);
198
199 20
        return (new Query())
200 20
            ->from($relation->via->from[0])
201 20
            ->andWhere([key($relation->via->link) => $model->getPrimaryKey()])
202 20
            ->indexBy(current($relation->link))
0 ignored issues
show
Documentation introduced by
current($relation->link) is of type *, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
203 20
            ->all();
204
    }
205
206 22
    public function files($model, $attribute)
207
    {
208 22
        $relation = $model->fileRelation($attribute);
209 22
        $relationName = $model->fileOption($attribute, 'relation');
210
211 22
        $query = call_user_func([$model, 'get' . $relationName]);
212 22
        return $query->indexBy(key($relation->link))->all();
213
    }
214
215 12
    public function file($model, $attribute)
216
    {
217 12
        $relation = $model->fileOption($attribute, 'relation');
218 12
        return $model->$relation;
219
    }
220
}
221