Completed
Pull Request — master (#406)
by
unknown
02:23
created

RemoteFileFormFactory   B

Complexity

Total Complexity 22

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 18
dl 0
loc 169
rs 7.3333
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getForm() 0 23 3
A getRequiredContext() 0 4 1
B getFormFields() 0 63 6
A getFormActions() 0 21 3
C validateUrl() 0 26 8
A getEmbed() 0 6 1
1
<?php
2
3
namespace SilverStripe\AssetAdmin\Forms;
4
5
use Embed\Exceptions\InvalidUrlException;
6
use InvalidArgumentException;
7
use SilverStripe\Control\Controller;
8
use SilverStripe\Control\Director;
9
use SilverStripe\Core\Config\Configurable;
10
use SilverStripe\Core\Extensible;
11
use SilverStripe\Forms\CompositeField;
12
use SilverStripe\Forms\FieldGroup;
13
use SilverStripe\Forms\FieldList;
14
use SilverStripe\Forms\Form;
15
use SilverStripe\Forms\FormAction;
16
use SilverStripe\Forms\FormFactory;
17
use SilverStripe\Forms\HiddenField;
18
use SilverStripe\Forms\HTMLEditor\HTMLEditorField_Embed;
19
use SilverStripe\Forms\LabelField;
20
use SilverStripe\Forms\LiteralField;
21
use SilverStripe\Forms\OptionsetField;
22
use SilverStripe\Forms\ReadonlyField;
23
use SilverStripe\Forms\RequiredFields;
24
use SilverStripe\Forms\TextField;
25
26
class RemoteFileFormFactory implements FormFactory
27
{
28
    use Extensible;
29
    use Configurable;
30
    
31
    private static $fileurl_scheme_whitelist = ['http', 'https'];
0 ignored issues
show
Unused Code introduced by
The property $fileurl_scheme_whitelist is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
32
    
33
    private static $fileurl_domain_whitelist = [];
0 ignored issues
show
Unused Code introduced by
The property $fileurl_domain_whitelist is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
34
    
35
    /**
36
     * @param Controller $controller
37
     * @param string $name
38
     * @param array $context
39
     * @return Form
40
     */
41
    public function getForm(Controller $controller, $name = self::DEFAULT_NAME, $context = [])
42
    {
43
        // Validate context
44
        foreach ($this->getRequiredContext() as $required) {
45
            if (!isset($context[$required])) {
46
                throw new InvalidArgumentException("Missing required context $required");
47
            }
48
        }
49
    
50
        $fields = $this->getFormFields($controller, $name, $context);
51
        $actions = $this->getFormActions($controller, $name, $context);
52
        
53
        $validator = new RequiredFields();
54
        $form = Form::create($controller, $name, $fields, $actions, $validator);
55
        $form->addExtraClass('form--fill-height');
56
        $form->addExtraClass('form--no-dividers');
57
        $form->addExtraClass('insert-embed-modal--'. strtolower($context['type']));
58
    
59
        // Extend form
60
        $this->invokeWithExtensions('updateForm', $form, $controller, $name, $context);
61
    
62
        return $form;
63
    }
64
    
65
    public function getRequiredContext()
66
    {
67
        return ['type'];
68
    }
69
    
70
    protected function getFormFields($controller, $name, $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 $name 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...
71
    {
72
        $fields = [];
73
        $url = (isset($context['url'])) ? $context['url'] : null;
74
        
75
        if ($context['type'] === 'create') {
76
            $fields = [
77
                LabelField::create('UrlDescription', _t(
78
                    'RemoteFileForm.UrlDescription',
79
                    'Embed Youtube and Vimeo videos, images and other media directly from the web.'
80
                )),
81
                TextField::create('Url', ''),
82
            ];
83
        }
84
        
85
        if ($context['type'] === 'edit' && $url && $this->validateUrl($url)) {
86
            $embed = $this->getEmbed($url);
87
            $alignments = array(
88
                'leftAlone' => _t('AssetAdmin.AlignmentLeftAlone', 'Left'),
89
                'center' => _t('AssetAdmin.AlignmentCenter', 'Center'),
90
                'rightAlone' => _t('AssetAdmin.AlignmentRightAlone', 'Right'),
91
                'left' => _t('AssetAdmin.AlignmentLeft', 'Left wrap'),
92
                'right' => _t('AssetAdmin.AlignmentRight', 'Right wrap'),
93
            );
94
            
95
            $fields = CompositeField::create([
96
                LiteralField::create('Preview', sprintf('<img src="%s" class="%s" />',
97
                    $embed->getPreviewURL(),
98
                    'insert-embed-modal__preview'
99
                ))->addExtraClass('insert-embed-modal__preview-container'),
100
                HiddenField::create('PreviewUrl', 'PreviewUrl', $embed->getPreviewURL()),
101
                CompositeField::create([
102
                    ReadonlyField::create('Url', $embed->getName(), $url),
103
                    TextField::create('CaptionText', _t('AssetAdmin.Caption', 'Caption')),
104
                    OptionsetField::create(
105
                        'Placement',
106
                        _t('AssetAdmin.Placement', 'Placement'),
107
                        $alignments
108
                    )
109
                        ->addExtraClass('insert-embed-modal__placement'),
110
                    FieldGroup::create(
111
                        _t('AssetAdmin.ImageSpecs', 'Dimensions'),
112
                        TextField::create(
113
                            'Width',
114
                            _t('AssetAdmin.ImageWidth', 'Width'),
115
                            $embed->getWidth()
116
                        )
117
                            ->setMaxLength(5)
118
                            ->addExtraClass('flexbox-area-grow'),
119
                        TextField::create(
120
                            'Height',
121
                            _t('AssetAdmin.ImageHeight', 'Height'),
122
                            $embed->getHeight()
123
                        )
124
                            ->setMaxLength(5)
125
                            ->addExtraClass('flexbox-area-grow')
126
                    )->addExtraClass('fieldgroup--fill-width')
127
                ])->addExtraClass('flexbox-area-grow'),
128
            ])->addExtraClass('insert-embed-modal__fields--fill-width');
129
        }
130
        
131
        return FieldList::create($fields);
132
    }
133
    
134
    protected function getFormActions($controller, $name, $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 $name 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...
135
    {
136
        $actions = [];
137
        
138
        if ($context['type'] === 'create') {
139
            $actions = [
140
                FormAction::create('addmedia', _t('RemoteFileForm.AddMedia', 'Add media'))
141
                    ->setSchemaData(['data' => ['buttonStyle' => 'primary']]),
142
            ];
143
        }
144
        
145
        if ($context['type'] === 'edit') {
146
            $actions = [
147
                FormAction::create('insertmedia', _t('RemoteFileForm.InsertMedia', 'Insert media'))
148
                    ->setSchemaData(['data' => ['buttonStyle' => 'primary']]),
149
                FormAction::create('cancel', _t('RemoteFileForm.Cancel', 'Cancel')),
150
            ];
151
        }
152
    
153
        return FieldList::create($actions);
154
    }
155
    
156
    /**
157
     * @param $url
158
     * @return bool
159
     * @throws InvalidUrlException
160
     */
161
    protected function validateUrl($url)
162
    {
163
        if (!Director::is_absolute_url($url)) {
164
            throw new InvalidUrlException(_t(
165
                "HTMLEditorField_Toolbar.ERROR_ABSOLUTE",
166
                "Only absolute urls can be embedded"
167
            ));
168
        }
169
        $scheme = strtolower(parse_url($url, PHP_URL_SCHEME));
170
        $allowed_schemes = self::config()->get('fileurl_scheme_whitelist');
171
        if (!$scheme || ($allowed_schemes && !in_array($scheme, $allowed_schemes))) {
172
            throw new InvalidUrlException(_t(
173
                "HTMLEditorField_Toolbar.ERROR_SCHEME",
174
                "This file scheme is not included in the whitelist"
175
            ));
176
        }
177
        $domain = strtolower(parse_url($url, PHP_URL_HOST));
178
        $allowed_domains = self::config()->get('fileurl_domain_whitelist');
179
        if (!$domain || ($allowed_domains && !in_array($domain, $allowed_domains))) {
180
            throw new InvalidUrlException(_t(
181
                "HTMLEditorField_Toolbar.ERROR_HOSTNAME",
182
                "This file hostname is not included in the whitelist"
183
            ));
184
        }
185
        return true;
186
    }
187
    
188
    protected function getEmbed($url)
189
    {
190
        $embed = new HTMLEditorField_Embed($url);
191
        
192
        return $embed;
193
    }
194
}
195