FileWidget::processEditAction()   D
last analyzed

Complexity

Conditions 41
Paths 27

Size

Total Lines 130
Code Lines 83

Duplication

Lines 17
Ratio 13.08 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 41
eloc 83
nc 27
nop 0
dl 17
loc 130
rs 4.1818
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace DigitalWand\AdminHelper\Widget;
4
5
use Bitrix\Main\Localization\Loc;
6
use Bitrix\Main\UI\FileInput;
7
8
/**
9
 * Для множественного поля в таблице должен быть столбец FILE_ID.
10
 * Настройки класса:
11
 * <ul>
12
 * <li><b>DESCRIPTION_FIELD</b> - bool нужно ли поле описания</li>
13
 * <li><b>MULTIPLE</b> - bool является ли поле множественным</li>
14
 * <li><b>IMAGE</b> - bool отображать ли изображение файла, для старого вида отображения</li>
15
 * </ul>
16
 */
17
class FileWidget extends HelperWidget
18
{
19
    protected static $defaults = array(
20
        'IMAGE' => false,
21
        'DESCRIPTION_FIELD' => false,
22
        'EDIT_IN_LIST' => false,
23
        'FILTER' => false,
24
        'UPLOAD' => true,
25
        'MEDIALIB' => true,
26
        'FILE_DIALOG' => true,
27
        'CLOUD' => true,
28
        'DELETE' => true,
29
        'EDIT' => true,
30
    );
31
32
    /**
33
     * {@inheritdoc}
34
     */
35
    public function __construct(array $settings = array())
36
    {
37
        Loc::loadMessages(__FILE__);
38
        
39
        parent::__construct($settings);
40
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    protected function getEditHtml()
46
    {
47
        if (class_exists('\Bitrix\Main\UI\FileInput', true) && $this->getSettings('IMAGE') === true) {
48
            $html = FileInput::createInstance(array(
49
                'name' => $this->getEditInputName('_FILE'),
50
                'description' => $this->getSettings('DESCRIPTION_FIELD'),
51
                'upload' => $this->getSettings('UPLOAD'),
52
                'allowUpload' => 'I',
53
                'medialib' => $this->getSettings('MEDIALIB'),
54
                'fileDialog' => $this->getSettings('FILE_DIALOG'),
55
                'cloud' => $this->getSettings('CLOUD'),
56
                'delete' => $this->getSettings('DELETE'),
57
                'edit' => $this->getSettings('EDIT'),
58
                'maxCount' => 1
59
            ))->show($this->getValue());
60
        } else {
61
            $html = \CFileInput::Show($this->getEditInputName('_FILE'), ($this->getValue() > 0 ? $this->getValue() : 0),
62
                array(
63
                    'IMAGE' => $this->getSettings('IMAGE') === true ? 'Y' : 'N',
64
                    'PATH' => 'Y',
65
                    'FILE_SIZE' => 'Y',
66
                    'ALLOW_UPLOAD' => 'I',
67
                ), array(
68
                    'upload' => $this->getSettings('UPLOAD'),
69
                    'medialib' => $this->getSettings('MEDIALIB'),
70
                    'file_dialog' => $this->getSettings('FILE_DIALOG'),
71
                    'cloud' => $this->getSettings('CLOUD'),
72
                    'del' => $this->getSettings('DELETE'),
73
                    'description' => $this->getSettings('DESCRIPTION_FIELD'),
74
                )
75
            );
76
        }
77
78
        if ($this->getValue()) {
79
            $html .= '<input type="hidden" name="' . $this->getEditInputName() . '" value=' . $this->getValue() . '>';
80
        }
81
82
        return $html;
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    protected function getMultipleEditHtml()
89
    {
90
        $inputHidden = array();
91
        $inputName = array();
92
        
93
        if (!empty($this->data['ID'])) {
94
            $entityName = $this->entityName;
95
            
96
            $rsEntityData = $entityName::getList(array(
97
                'select' => array('REFERENCE_' => $this->getCode() . '.*'),
98
                'filter' => array('=ID' => $this->data['ID'])
99
            ));
100
101
            while ($referenceData = $rsEntityData->fetch()) {
102
                $inputName[$this->code . '[' . $referenceData['REFERENCE_ID'] . ']'] = $referenceData['REFERENCE_VALUE'];
103
                $inputHidden[$referenceData['REFERENCE_ID']] = $referenceData['REFERENCE_VALUE'];
104
            }
105
        }
106
107
        if (class_exists('\Bitrix\Main\UI\FileInput', true) && $this->getSettings('IMAGE') === true) {
108
            $html = \Bitrix\Main\UI\FileInput::createInstance(array(
109
                'name' => $this->code . '[n#IND#]',
110
                'description' => $this->getSettings('DESCRIPTION_FIELD'),
111
                'upload' => $this->getSettings('UPLOAD'),
112
                'allowUpload' => 'I',
113
                'medialib' => $this->getSettings('MEDIALIB'),
114
                'fileDialog' => $this->getSettings('FILE_DIALOG'),
115
                'cloud' => $this->getSettings('CLOUD'),
116
                'delete' => $this->getSettings('DELETE'),
117
                'edit' => $this->getSettings('EDIT')
118
            ))->show($inputName);
119
        } else {
120
            $html = \CFileInput::ShowMultiple($inputName, $this->code . '[n#IND#]',
121
                array(
122
                    'IMAGE' => $this->getSettings('IMAGE') === true ? 'Y' : 'N',
123
                    'PATH' => 'Y',
124
                    'FILE_SIZE' => 'Y',
125
                    'DIMENSIONS' => 'Y',
126
                    'IMAGE_POPUP' => 'Y',
127
                ), 
128
                false, 
129
                array(
130
                    'upload' => $this->getSettings('UPLOAD'),
131
                    'medialib' => $this->getSettings('MEDIALIB'),
132
                    'file_dialog' => $this->getSettings('FILE_DIALOG'),
133
                    'cloud' => $this->getSettings('CLOUD'),
134
                    'del' => $this->getSettings('DELETE'),
135
                    'description' => $this->getSettings('DESCRIPTION_FIELD'),
136
                )
137
            );
138
        }
139
140
        foreach ($inputHidden as $key => $input) {
141
            if (!empty($input)) {
142
                $html .= '<input type="hidden" name="' . $this->code . '[' . $key . '][ID]" value=' . $key . '>
143
					<input type="hidden" name="' . $this->code . '[' . $key . '][VALUE]" value=' . $input . '>';
144
            }
145
        }
146
147
        return $html;
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153
    public function generateRow(&$row, $data)
154
    {
155
        $html = '';
156
        
157
        if ($this->getSettings('MULTIPLE')) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
158
            
159
        } else {
160
            $path = \CFile::GetPath($data[$this->code]);
161
            $rsFile = \CFile::GetByID($data[$this->code]);
162
            $file = $rsFile->Fetch();
163
164
            if ($path) {
165
                $html = '<a href="' . $path . '" >' . $file['FILE_NAME'] . ' (' . $file['FILE_DESCRIPTION'] . ')' . '</a>';
166
            }
167
            
168
            $row->AddViewField($this->code, $html);
169
        }
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175
    public function showFilterHtml()
176
    {
177
        // TODO: Implement genFilterHTML() method.
178
    }
179
180
    /**
181
     * {@inheritdoc}
182
     */
183
    public function processEditAction()
0 ignored issues
show
Coding Style introduced by
processEditAction uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
processEditAction uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
184
    {
185
        if ($this->getSettings('MULTIPLE')) {
186
            if ($this->getSettings('READONLY') === true) {
187
                //удаляем все добавленные файлы в режиме только для чтения
188
                foreach ($this->data[$this->code] as $key => $value) {
189
                    if (!is_array($value)) {
190
                        unset($this->data[$this->code][$key]);
191
                    }
192
                }
193
                return false;
194
            }
195
196
            if (class_exists('\Bitrix\Main\UI\FileInput', true) && $this->getSettings('IMAGE') === true) {
197
                foreach ($this->data[$this->code] as $key => $value) {
198
                    if (is_array($value) && ($value['name'] || $value['tmp_name'])) {
199
                        $_FILES[$this->code]['name'][$key] = $value['name'];
200
                        $_FILES[$this->code]['type'][$key] = $value['type'];
201
                        $_FILES[$this->code]['tmp_name'][$key] = $value['tmp_name'];
202
                        $_FILES[$this->code]['error'][$key] = $value['error'];
203
                        $_FILES[$this->code]['size'][$key] = $value['size'];
204
                        unset($this->data[$this->code][$key]);
205
                    } else {
206
                        $_FILES[$this->code]['name'][$key] = '';
207
                    }
208
                }
209
                if (!count($this->data[$this->code])) {
210
                    unset($this->data[$this->code]);
211
                }
212
            }
213
214
            if (!empty($_FILES[$this->getCode()])) {
215
                foreach ($_FILES[$this->getCode()]['name'] as $key => $fileName) {
216
                    if (empty($fileName)
217
                        || empty($_FILES[$this->getCode()]['tmp_name'][$key])
218
                        || !empty($_FILES[$this->getCode()]['error'][$key])
219
                    ) {
220
                        if (isset($_REQUEST[$this->getCode() . '_del'][$key])) {
221 View Code Duplication
                            if (is_array($this->data[$this->getCode()][$key]) &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
222
                                !empty($this->data[$this->getCode()][$key]['VALUE'])
223
                            ) {
224
                                \CFile::Delete(intval($this->data[$this->getCode()][$key]['VALUE']));
225
                            } else {
226
                                \CFile::Delete(intval($this->data[$this->getCode()][$key]));
227
                            }
228
                            unset($this->data[$this->getCode()][$key]);
229
                        } elseif ($this->data[$this->getCode()][$key]['VALUE']) {
230
                            \CFile::UpdateDesc($this->data[$this->getCode()][$key]['VALUE'],
231
                                $_REQUEST[$this->getCode() . '_descr'][$key]);
232
                        }
233
                        continue;
234 View Code Duplication
                    } elseif (is_int($key)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
235
                        //Удаляем старый файл при замене
236
                        if (is_array($this->data[$this->getCode()][$key]) &&
237
                            !empty($this->data[$this->getCode()][$key]['VALUE'])
238
                        ) {
239
                            \CFile::Delete(intval($this->data[$this->getCode()][$key]['VALUE']));
240
                        } else {
241
                            \CFile::Delete(intval($this->data[$this->getCode()][$key]));
242
                        }
243
                    }
244
245
                    $description = null;
246
247
                    if (isset($_REQUEST[$this->getCode() . '_descr'][$key])) {
248
                        $description = $_REQUEST[$this->getCode() . '_descr'][$key];
249
                    }
250
251
                    if (empty($this->data[$this->getCode()][$key])) {
252
                        unset($this->data[$this->getCode()][$key]);
253
                    }
254
255
                    $fileId = $this->saveFile($fileName, $_FILES[$this->getCode()]['tmp_name'][$key], false, $description);
256
257
                    if ($fileId) {
258
                        $this->data[$this->getCode()][$key] = array('VALUE' => $fileId);
259
                    } else {
260
                        $this->addError('DIGITALWAND_AH_FAIL_ADD_FILE', array(
261
                            'FILE_NAME' => $_FILES[$this->getCode()]['name'][$key]
262
                        ));
263
                    }
264
                }
265
            }
266
        } else {
267
            if (class_exists('\Bitrix\Main\UI\FileInput', true) && $this->getSettings('IMAGE') === true) {
268
                if (is_array($this->data[$this->code . '_FILE']) && ($this->data[$this->code . '_FILE']['name'] ||
269
                        $this->data[$this->code . '_FILE']['tmp_name'])
270
                ) {
271
                    $_FILES['FIELDS']['name'][$this->code . '_FILE'] = $this->data[$this->code . '_FILE']['name'];
272
                    $_FILES['FIELDS']['type'][$this->code . '_FILE'] = $this->data[$this->code . '_FILE']['type'];
273
                    $_FILES['FIELDS']['tmp_name'][$this->code . '_FILE'] = $this->data[$this->code . '_FILE']['tmp_name'];
274
                    $_FILES['FIELDS']['error'][$this->code . '_FILE'] = $this->data[$this->code . '_FILE']['error'];
275
                    $_FILES['FIELDS']['size'][$this->code . '_FILE'] = $this->data[$this->code . '_FILE']['size'];
276
                }
277
            }
278
279
            unset($this->data[$this->code . '_FILE']);
280
            
281
            if ($this->getSettings('READONLY') === true) {
282
                return false;
283
            }
284
285
            if (empty($_FILES['FIELDS']['name'][$this->code . '_FILE'])
286
                || empty($_FILES['FIELDS']['tmp_name'][$this->code . '_FILE'])
287
                || !empty($_FILES['FIELDS']['error'][$this->code . '_FILE'])
288
            ) {
289
                if (isset($_REQUEST['FIELDS_del'][$this->code . '_FILE']) AND $_REQUEST['FIELDS_del'][$this->code . '_FILE'] == 'Y') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
290
                    \CFile::Delete(intval($this->data[$this->code]));
291
                    $this->data[$this->code] = 0;
292
                } elseif ($this->data[$this->code] && isset($_REQUEST['FIELDS_descr'][$this->code . '_FILE'])) {
293
                    \CFile::UpdateDesc($this->data[$this->code],
294
                        $_REQUEST['FIELDS_descr'][$this->code . '_FILE']);
295
                }
296
                return false;
297
            }
298
299
            $description = null;
300
301
            if (isset($_REQUEST['FIELDS_descr'][$this->code . '_FILE'])) {
302
                $description = $_REQUEST['FIELDS_descr'][$this->code . '_FILE'];
303
            }
304
305
            $name = $_FILES['FIELDS']['name'][$this->code . '_FILE'];
306
            $path = $_FILES['FIELDS']['tmp_name'][$this->code . '_FILE'];
307
            $type = $_FILES['FIELDS']['type'][$this->code . '_FILE'];
308
309
            $this->saveFile($name, $path, $type, $description);
310
        }
311
        parent::processEditAction();
312
    }
313
314
    protected function saveFile($name, $path, $type = false, $description = null)
315
    {
316
        if (!$path) {
317
            return false;
318
        }
319
320
        $file = \CFile::MakeFileArray($path, $type);
321
322
        if (!$file) {
323
            return false;
324
        }
325
326
        if (!empty($description)) {
327
            $file['description'] = $description;
328
        }
329
330
        if ($this->getSettings('IMAGE') === true && stripos($file['type'], "image") === false) {
331
            $this->addError('FILE_FIELD_TYPE_ERROR');
332
333
            return false;
334
        }
335
336
        $file['name'] = $name;
337
338
        $moduleId = $this->helper->getModule();
339
        $file['MODULE_ID'] = $moduleId;
340
341
        $fileId = \CFile::SaveFile($file, $moduleId);
342
343
        if (!$this->getSettings('MULTIPLE')) {
344
            $code = $this->code;
345
            
346
            if (isset($this->data[$code])) {
347
                \CFile::Delete($this->data[$code]);
348
            }
349
350
            $this->data[$code] = $fileId;
351
        }
352
353
        return $fileId;
354
    }
355
356
    /**
357
     * {@inheritdoc}
358
     */
359 View Code Duplication
    protected function getValueReadonly()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
360
    {
361
        $this->setSetting('UPLOAD', false);
362
        $this->setSetting('MEDIALIB', false);
363
        $this->setSetting('FILE_DIALOG', false);
364
        $this->setSetting('CLOUD', false);
365
        $this->setSetting('DELETE', false);
366
        $this->setSetting('EDIT', false);
367
368
        return $this->getEditHtml();
369
    }
370
371
    /**
372
     * {@inheritdoc}
373
     */
374 View Code Duplication
    protected function getMultipleValueReadonly()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
375
    {
376
        $this->setSetting('UPLOAD', false);
377
        $this->setSetting('MEDIALIB', false);
378
        $this->setSetting('FILE_DIALOG', false);
379
        $this->setSetting('CLOUD', false);
380
        $this->setSetting('DELETE', false);
381
        $this->setSetting('EDIT', false);
382
383
        return $this->getMultipleEditHtml();
384
    }
385
}