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

RemoteFileFormFactory::getEmbed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 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(
97
                    'Preview',
98
                    sprintf(
99
                        '<img src="%s" class="%s" />',
100
                        $embed->getPreviewURL(),
101
                        'insert-embed-modal__preview'
102
                    )
103
                )->addExtraClass('insert-embed-modal__preview-container'),
104
                HiddenField::create('PreviewUrl', 'PreviewUrl', $embed->getPreviewURL()),
105
                CompositeField::create([
106
                    ReadonlyField::create('Url', $embed->getName(), $url),
107
                    TextField::create('CaptionText', _t('AssetAdmin.Caption', 'Caption')),
108
                    OptionsetField::create(
109
                        'Placement',
110
                        _t('AssetAdmin.Placement', 'Placement'),
111
                        $alignments
112
                    )
113
                        ->addExtraClass('insert-embed-modal__placement'),
114
                    FieldGroup::create(
115
                        _t('AssetAdmin.ImageSpecs', 'Dimensions'),
116
                        TextField::create(
117
                            'Width',
118
                            _t('AssetAdmin.ImageWidth', 'Width'),
119
                            $embed->getWidth()
120
                        )
121
                            ->setMaxLength(5)
122
                            ->addExtraClass('flexbox-area-grow'),
123
                        TextField::create(
124
                            'Height',
125
                            _t('AssetAdmin.ImageHeight', 'Height'),
126
                            $embed->getHeight()
127
                        )
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