Completed
Pull Request — master (#4)
by
unknown
02:11
created

FileBind   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 206
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 20.3%

Importance

Changes 0
Metric Value
wmc 34
lcom 1
cbo 2
dl 0
loc 206
ccs 27
cts 133
cp 0.203
rs 9.68
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A bind() 0 22 3
A save() 0 12 4
A newFiles() 0 10 1
A prepareInsertRelations() 0 32 4
A prepareUpdateRelations() 0 22 5
A insertRelations() 0 7 1
A updateRelations() 0 13 2
A updateFiles() 0 23 5
B delete() 0 28 6
A relations() 0 10 1
A files() 0 8 1
A file() 0 5 1
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 1
    public function bind($model, $attribute, $files)
18
    {
19 1
        $newFiles = $this->newFiles($model, $attribute, $files);
20 1
        if (!count($newFiles)) {
21 1
            return false;
22
        }
23
24
        $currentFiles = $this->files($model, $attribute);
25
        $currentRelations = $this->relations($model, $attribute);
26
        $insertData = $this->prepareInsertRelations($model, $attribute, $newFiles);
27
        $updateData = $this->prepareUpdateRelations($model, $attribute, $newFiles, $currentRelations);
28
29
        $resultFiles = $insertData['files'] + $updateData['files'];
30
        if (!count($resultFiles)) {
31
            return false;
32
        }
33
34
        $this->delete($model, $attribute, array_diff_key($currentFiles, $resultFiles));
35
        $this->save($model, $attribute, $insertData, $updateData, $resultFiles);
36
37
        return $resultFiles;
38
    }
39
40
    private function save($model, $attribute, $insertData, $updateData, $resultFiles)
41
    {
42
        if (count($insertData['rows'])) {
43
            $this->insertRelations($model, $attribute, $insertData['rows'], $insertData['columns']);
44
        }
45
        if (count($updateData['rows'])) {
46
            $this->updateRelations($model, $attribute, $updateData['rows']);
47
        }
48
        if (count($resultFiles)) {
49
            $this->updateFiles($model, $attribute, $resultFiles);
50
        }
51
    }
52
53 1
    private function newFiles($model, $attribute, $fileIds)
54
    {
55 1
        $relation = $model->fileRelation($attribute);
56 1
        $fileModel = $relation->modelClass;
57
58 1
        return $fileModel::find()
59 1
            ->where([key($relation->link) => $fileIds])
60 1
            ->indexBy(key($relation->link))
61 1
            ->all();
62
    }
63
64
    private function prepareInsertRelations($model, $attribute, $newFiles)
65
    {
66
        $ownerId = $model->getPrimaryKey();
67
        $relation = $model->fileRelation($attribute);
68
        $uploadedFiles = $model->fileState($attribute);
69
        $handlerExtraFields = $model->fileOption($attribute, 'extraFields');
70
71
        $files = [];
72
        $rows = [];
73
        $extraFields = [];
74
        foreach ($uploadedFiles as $fileId) {
75
            if (isset($newFiles[$fileId])) {
76
                $file = $newFiles[$fileId];
77
                $row = [$ownerId, $fileId];
78
                if ($handlerExtraFields) {
79
                    $fields = [
80
                        key($relation->via->link) => $ownerId,
81
                        current($relation->link) => $fileId,
82
                    ];
83
                    $extraFields = $handlerExtraFields($file, $fields);
84
                    $row = array_merge($row, array_values($extraFields));
85
                }
86
                $rows[] = $row;
87
                $files[$file->getPrimaryKey()] = $file;
88
            }
89
        }
90
91
        $columns = [key($relation->via->link), current($relation->link)];
92
        $columns = array_merge($columns, array_keys($extraFields));
93
94
        return ['rows' => $rows, 'files' => $files, 'columns' => $columns];
95
    }
96
97
    private function prepareUpdateRelations($model, $attribute, $newFiles, $currentRelations)
98
    {
99
        $relation = $model->fileRelation($attribute);
100
        $handlerExtraFields = $model->fileOption($attribute, 'extraFields');
101
102
        $files = [];
103
        $rows = [];
104
        foreach ($currentRelations as $fields) {
105
            if (isset($newFiles[$fields[current($relation->link)]])) {
106
                $file = $newFiles[$fields[current($relation->link)]];
107
                if ($handlerExtraFields) {
108
                    $extraFields = $handlerExtraFields($file, $fields);
109
                    $fieldChanged = (bool)count(array_diff_assoc($extraFields, $fields));
110
                    if ($fieldChanged) {
111
                        $rows[$file->getPrimaryKey()] = $extraFields;
112
                    }
113
                }
114
                $files[$file->getPrimaryKey()] = $file;
115
            }
116
        }
117
        return ['rows' => $rows, 'files' => $files];
118
    }
119
120
    private function insertRelations($model, $attribute, $rows, $columns)
121
    {
122
        $relation = $model->fileRelation($attribute);
123
        Yii::$app->getDb()->createCommand()
124
            ->batchInsert($relation->via->from[0], $columns, $rows)
125
            ->execute();
126
    }
127
128
    private function updateRelations($model, $attribute, $rows)
129
    {
130
        $relation = $model->fileRelation($attribute);
131
        $ownerId = $model->getPrimaryKey();
132
        $db = Yii::$app->getDb()->createCommand();
133
134
        foreach ($rows as $fileId => $row) {
135
            $db->update($relation->via->from[0], $row, [
136
                key($relation->via->link) => $ownerId,
137
                current($relation->link) => $fileId
138
            ])->execute();
139
        }
140
    }
141
142
    private function updateFiles($model, $attribute, $files)
143
    {
144
        $handlerUpdateFile = $model->fileOption($attribute, 'updateFile');
145
        $relation = $model->fileOption($attribute, 'relation');
146
        $isMultiple = $model->fileOption($attribute, 'multiple');
147
148
        $relationValue = [];
149
        foreach ($files as $file) {
150
            $relationValue[] = $file;
151
            if ($handlerUpdateFile) {
152
                $fileUpd = $handlerUpdateFile($file);
153
                $dirtyAttributes = $fileUpd->getDirtyAttributes();
154
                if (count($dirtyAttributes)) {
155
                    $fileUpd->updateAttributes($dirtyAttributes);
156
                }
157
            }
158
        }
159
160
        if (!$isMultiple) {
161
            $relationValue = array_shift($relationValue);
162
        }
163
        $model->populateRelation($relation, $relationValue);
164
    }
165
166 1
    public function delete($model, $attribute, $files)
167
    {
168 1
        $relation = $model->fileRelation($attribute);
169 1
        $storage = $model->fileStorage($attribute);
170 1
        $presets = array_keys($model->fileOption($attribute, 'preset', []));
171 1
        $handlerTemplatePath = $model->fileOption($attribute, 'templatePath');
172
173 1
        $db = Yii::$app->getDb()->createCommand();
174 1
        foreach ($files as $file) {
175
            foreach ($presets as $preset) {
176
                $thumbPath = $model->thumbPath($attribute, $preset, $file);
177
                $filePath = str_replace($storage->path, '', $thumbPath);
178
                if ($storage->has($filePath)) {
179
                    $storage->delete($filePath);
180
                }
181
            }
182
183
            if ($file->delete()) {
184
                $db->delete($relation->via->from[0], [
185
                    current($relation->link) => $file->getPrimaryKey()
186
                ])->execute();
187
                $filePath = $handlerTemplatePath($file);
188
                if ($storage->has($filePath)) {
189
                    $storage->delete($filePath);
190
                }
191
            }
192
        }
193 1
    }
194
195
    public function relations($model, $attribute)
196
    {
197
        $relation = $model->fileRelation($attribute);
198
199
        return (new Query())
200
            ->from($relation->via->from[0])
201
            ->andWhere([key($relation->via->link) => $model->getPrimaryKey()])
202
            ->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
            ->all();
204
    }
205
206 2
    public function files($model, $attribute)
207
    {
208 2
        $relation = $model->fileRelation($attribute);
209 2
        $relationName = $model->fileOption($attribute, 'relation');
210
211 2
        $query = call_user_func([$model, 'get' . $relationName]);
212 2
        return $query->indexBy(key($relation->link))->all();
213
    }
214
215 1
    public function file($model, $attribute)
216
    {
217 1
        $relation = $model->fileOption($attribute, 'relation');
218 1
        return $model->$relation;
219
    }
220
}
221