Completed
Pull Request — master (#406)
by Damian
02:12
created

RemoteFileFormFactory::getFormActions()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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