Completed
Push — master ( 7dd226...34aa18 )
by
unknown
10s
created

AssetFormFactory   B

Complexity

Total Complexity 34

Size/Duplication

Total Lines 300
Duplicated Lines 6 %

Coupling/Cohesion

Components 1
Dependencies 17

Importance

Changes 0
Metric Value
wmc 34
lcom 1
cbo 17
dl 18
loc 300
rs 7.2285
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B getForm() 0 32 5
A getValidator() 0 6 1
A getFormType() 0 4 2
A getFormFieldTabs() 0 10 1
A getSaveAction() 8 8 4
A getDeleteAction() 10 10 4
B getFormActions() 0 16 5
B getFormFields() 0 24 4
A getPopoverMenu() 0 15 2
A getPopoverActions() 0 9 1
A getFormFieldDetailsTab() 0 7 1
B getFormFieldSecurityTab() 0 39 2
A getRequiredContext() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace SilverStripe\AssetAdmin\Forms;
4
5
use InvalidArgumentException;
6
use SilverStripe\Assets\File;
7
use SilverStripe\Control\RequestHandler;
8
use SilverStripe\Core\Config\Configurable;
9
use SilverStripe\Core\Extensible;
10
use SilverStripe\Core\Injector\Injectable;
11
use SilverStripe\Forms\CheckboxSetField;
12
use SilverStripe\Forms\FieldList;
13
use SilverStripe\Forms\Form;
14
use SilverStripe\Forms\FormAction;
15
use SilverStripe\Forms\FormFactory;
16
use SilverStripe\Forms\HeaderField;
17
use SilverStripe\Forms\HiddenField;
18
use SilverStripe\Forms\OptionsetField;
19
use SilverStripe\Forms\PopoverField;
20
use SilverStripe\Forms\RequiredFields;
21
use SilverStripe\Forms\Tab;
22
use SilverStripe\Forms\TabSet;
23
use SilverStripe\Forms\TextField;
24
use SilverStripe\Security\Group;
25
26
abstract class AssetFormFactory implements FormFactory
27
{
28
    use Extensible;
29
    use Injectable;
30
    use Configurable;
31
32
    /**
33
     * Insert into HTML content area
34
     */
35
    const TYPE_INSERT = 'insert';
36
37
    /**
38
     * Select file by ID only
39
     */
40
    const TYPE_SELECT = 'select';
41
42
    /**
43
     * Edit form: Default
44
     */
45
    const TYPE_ADMIN = 'admin';
46
47
    public function __construct()
48
    {
49
        $this->constructExtensions();
50
    }
51
52
    /**
53
     * @param RequestHandler $controller
54
     * @param string $name
55
     * @param array $context
56
     * @return Form
57
     */
58
    public function getForm(RequestHandler $controller = null, $name = FormFactory::DEFAULT_NAME, $context = [])
59
    {
60
        // Validate context
61
        foreach ($this->getRequiredContext() as $required) {
62
            if (!isset($context[$required])) {
63
                throw new InvalidArgumentException("Missing required context $required");
64
            }
65
        }
66
67
        $fields = $this->getFormFields($controller, $name, $context);
68
        $actions = $this->getFormActions($controller, $name, $context);
69
        $validator = $this->getValidator($controller, $name, $context);
70
        $form = Form::create($controller, $name, $fields, $actions, $validator);
71
72
        // Extend form
73
        $this->invokeWithExtensions('updateForm', $form, $controller, $name, $context);
74
75
        // Populate form from record
76
        if (isset($context['Record'])) {
77
            /** @var File $record */
78
            $record = $context['Record'];
79
            $form->loadDataFrom($record);
80
81
            if (!$record->canEdit()) {
82
                $form->makeReadonly();
83
            }
84
        }
85
86
        $form->addExtraClass('form--fill-height form--padded');
87
88
        return $form;
89
    }
90
91
    /**
92
     * Get the validator for the form to be built
93
     *
94
     * @param RequestHandler $controller
95
     * @param $formName
96
     * @param $context
97
     * @return RequiredFields
98
     */
99
    protected function getValidator(RequestHandler $controller = null, $formName, $context = [])
0 ignored issues
show
Unused Code introduced by
The parameter $controller is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $formName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
100
    {
101
        $validator = new RequiredFields('Name');
102
103
        return $validator;
104
    }
105
106
    /**
107
     * Get form type from 'type' context
108
     *
109
     * @param array $context
110
     * @return string
111
     */
112
    protected function getFormType($context)
113
    {
114
        return empty($context['Type']) ? static::TYPE_ADMIN : $context['Type'];
115
    }
116
117
    /**
118
     * Gets the main tabs for the file edit form
119
     *
120
     * @param File $record
121
     * @param array $context
122
     * @return TabSet
123
     */
124
    protected function getFormFieldTabs($record, $context = [])
125
    {
126
        return TabSet::create(
127
            'Editor',
128
            [
129
                $this->getFormFieldDetailsTab($record, $context),
130
                $this->getFormFieldSecurityTab($record, $context),
131
            ]
132
        );
133
    }
134
135
    /**
136
     * @param File $record
137
     * @return FormAction
138
     */
139 View Code Duplication
    protected function getSaveAction($record)
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...
140
    {
141
        if ($record && $record->isInDB() && $record->canEdit()) {
142
            return FormAction::create('save', _t('SilverStripe\\CMS\\Controllers\\CMSMain.SAVE', 'Save'))
143
                ->setIcon('save');
144
        }
145
        return null;
146
    }
147
148
    /**
149
     * Get delete action, if this record is deletable
150
     *
151
     * @param File $record
152
     * @return FormAction
153
     */
154 View Code Duplication
    protected function getDeleteAction($record)
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...
155
    {
156
        // Delete action
157
        if ($record && $record->isInDB() && $record->canDelete()) {
158
            $deleteText = _t('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin.DELETE_BUTTON', 'Delete');
159
            return FormAction::create('delete', $deleteText)
160
                ->setIcon('trash-bin');
161
        }
162
        return null;
163
    }
164
165
    /**
166
     * @param RequestHandler $controller
167
     * @param $formName
168
     * @param array $context
169
     * @return FieldList
170
     */
171
    protected function getFormActions(RequestHandler $controller = null, $formName, $context = [])
172
    {
173
        $record = isset($context['Record']) ? $context['Record'] : null;
174
175
        $actions = new FieldList();
176
        if ($saveAction = $this->getSaveAction($record)) {
177
            $actions->push($saveAction);
178
        }
179
        $menu = $this->getPopoverMenu($record);
180
        if ($menu && $menu->FieldList()->count()) {
181
            $actions->push($menu);
182
        }
183
184
        $this->invokeWithExtensions('updateFormActions', $actions, $controller, $formName, $context);
185
        return $actions;
186
    }
187
188
    /**
189
     * Get fields for this form
190
     *
191
     * @param RequestHandler $controller
192
     * @param string $formName
193
     * @param array $context
194
     * @return FieldList
195
     */
196
    protected function getFormFields(RequestHandler $controller = null, $formName, $context = [])
197
    {
198
        $record = isset($context['Record']) ? $context['Record'] : null;
199
200
        // Build standard fields for all folders / files
201
        /** @var File $record */
202
        $fields = new FieldList(
203
            HeaderField::create('TitleHeader', $record ? $record->Title : null, 1)
204
                ->addExtraClass('editor__heading'),
205
            $this->getFormFieldTabs($record, $context)
206
        );
207
        if ($record) {
208
            $fields->push(HiddenField::create('ID', $record->ID));
209
            $fields->insertAfter(
210
                'TitleHeader',
211
                PreviewImageField::create('PreviewImage')
212
                    ->setRecordID($record->ID)
213
                    ->addExtraClass('editor__file-preview')
214
            );
215
        }
216
217
        $this->invokeWithExtensions('updateFormFields', $fields, $controller, $formName, $context);
218
        return $fields;
219
    }
220
221
    /**
222
     * Build popup menu
223
     *
224
     * @param File $record
225
     * @return PopoverField
226
     */
227
    protected function getPopoverMenu($record)
228
    {
229
        // Build popover actions
230
        $popoverActions = $this->getPopoverActions($record);
231
        if ($popoverActions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $popoverActions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
232
            return PopoverField::create($popoverActions)
233
                ->setPlacement('top')
234
                ->setName('PopoverActions')
235
                ->setButtonTooltip(_t(
236
                    'SilverStripe\\AssetAdmin\\Forms\\FileFormFactory.OTHER_ACTIONS',
237
                    'Other actions'
238
                ));
239
        }
240
        return null;
241
    }
242
243
    /**
244
     * Get actions that go into the Popover menu
245
     *
246
     * @param File $record
247
     * @return array
248
     */
249
    protected function getPopoverActions($record)
250
    {
251
        $actions = [
252
            $this->getDeleteAction($record)
253
        ];
254
255
        $this->invokeWithExtensions('updatePopoverActions', $actions, $record);
256
        return array_filter($actions);
257
    }
258
259
    /**
260
     * Build "details" formfield tab
261
     *
262
     * @param File $record
263
     * @param array $context
264
     * @return Tab
265
     */
266
    protected function getFormFieldDetailsTab($record, $context = [])
267
    {
268
        return Tab::create(
269
            'Details',
270
            TextField::create('Name', File::singleton()->fieldLabel('Filename'))
271
        );
272
    }
273
274
    /**
275
     * Build security tab
276
     *
277
     * @param File $record
278
     * @param array $context
279
     * @return Tab
280
     */
281
    protected function getFormFieldSecurityTab($record, $context = [])
0 ignored issues
show
Unused Code introduced by
The parameter $record is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
282
    {
283
        // Get groups
284
        $groupsMap = array();
285
        foreach (Group::get() as $group) {
286
            $groupsMap[$group->ID] = $group->getBreadcrumbs(' > ');
287
        }
288
        asort($groupsMap);
289
290
        // Get permissions
291
        $viewersOptionsField = [
292
            'Inherit' => _t(__CLASS__.'.INHERIT', 'Inherit from parent folder'),
293
            'Anyone' => _t(__CLASS__.'.ANYONE', 'Anyone'),
294
            'LoggedInUsers' => _t(__CLASS__.'.LOGGED_IN', 'Logged-in users'),
295
            'OnlyTheseUsers' => _t(__CLASS__.'.ONLY_GROUPS', 'Only these people (choose from list)')
296
        ];
297
298
        // No "Anyone" editors option
299
        $editorsOptionsField = $viewersOptionsField;
300
        unset($editorsOptionsField['Anyone']);
301
302
        return Tab::create(
303
            'Permissions',
304
            OptionsetField::create(
305
                'CanViewType',
306
                _t(__CLASS__.'.ACCESSHEADER', 'Who can view this file?')
307
            )
308
                ->setSource($viewersOptionsField),
309
            CheckboxSetField::create('ViewerGroups', _t(__CLASS__.'.VIEWERGROUPS', 'Viewer Groups'))
310
                ->setSource($groupsMap),
311
            OptionsetField::create(
312
                "CanEditType",
313
                _t(__CLASS__.'.EDITHEADER', 'Who can edit this file?')
314
            )
315
                ->setSource($editorsOptionsField),
316
            CheckboxSetField::create('EditorGroups', _t(__CLASS__.'.EDITORGROUPS', 'Editor Groups'))
317
                ->setSource($groupsMap)
318
        );
319
    }
320
321
    public function getRequiredContext()
322
    {
323
        return ['Record'];
324
    }
325
}
326