2e651bbcc6242a6baab7bc0a9acc35259106e9d4
[yaffs-website] / web / modules / contrib / video / src / Plugin / Field / FieldWidget / VideoUploadWidget.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\video\Plugin\Field\FieldWidget\VideoUploadWidget.
6  */
7
8 namespace Drupal\video\Plugin\Field\FieldWidget;
9
10 use Drupal\Component\Utility\Bytes;
11 use Drupal\Component\Render\PlainTextOutput;
12 use Drupal\Core\Field\FieldItemListInterface;
13 use Drupal\Component\Utility\NestedArray;
14 use Drupal\Core\Form\FormStateInterface;
15 use Drupal\file\Entity\File;
16 use Drupal\file\Plugin\Field\FieldWidget\FileWidget;
17 use Drupal\Core\StreamWrapper\StreamWrapperInterface;
18
19 /**
20  * Plugin implementation of the 'video_upload' widget.
21  *
22  * @FieldWidget(
23  *   id = "video_upload",
24  *   label = @Translation("Video Upload"),
25  *   field_types = {
26  *     "video"
27  *   }
28  * )
29  */
30 class VideoUploadWidget extends FileWidget {
31
32   /**
33    * {@inheritdoc}
34    */
35   public static function defaultSettings() {
36     $settings = array(
37       'file_extensions' => 'mp4 ogv webm',
38       'file_directory' => 'videos/[date:custom:Y]-[date:custom:m]',
39       'max_filesize' => '',
40       'uri_scheme' => 'public'
41     ) + parent::defaultSettings();
42     return $settings;
43   }
44
45   /**
46    * {@inheritdoc}
47    */
48   public function settingsForm(array $form, FormStateInterface $form_state) {
49     $element = parent::settingsForm($form, $form_state);
50     $settings = $this->getSettings();
51
52     $element['file_directory'] = array(
53       '#type' => 'textfield',
54       '#title' => t('File directory'),
55       '#default_value' => $settings['file_directory'],
56       '#description' => t('Optional subdirectory within the upload destination where files will be stored. Do not include preceding or trailing slashes.'),
57       '#element_validate' => array(array(get_class($this), 'validateDirectory')),
58       '#weight' => 3,
59     );
60
61     // Make the extension list a little more human-friendly by comma-separation.
62     $extensions = str_replace(' ', ', ', $settings['file_extensions']);
63     $element['file_extensions'] = array(
64       '#type' => 'textfield',
65       '#title' => t('Allowed file extensions'),
66       '#default_value' => $extensions,
67       '#description' => t('Separate extensions with a space or comma and do not include the leading dot.'),
68       '#element_validate' => array(array(get_class($this), 'validateExtensions')),
69       '#weight' => 1,
70       '#maxlength' => 256,
71       // By making this field required, we prevent a potential security issue
72       // that would allow files of any type to be uploaded.
73       '#required' => TRUE,
74     );
75
76     $element['max_filesize'] = array(
77       '#type' => 'textfield',
78       '#title' => t('Maximum upload size'),
79       '#default_value' => $settings['max_filesize'],
80       '#description' => t('Enter a value like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes) in order to restrict the allowed file size. If left empty the file sizes will be limited only by PHP\'s maximum post and file upload sizes (current limit <strong>%limit</strong>).', array('%limit' => format_size(file_upload_max_size()))),
81       '#size' => 10,
82       '#element_validate' => array(array(get_class($this), 'validateMaxFilesize')),
83       '#weight' => 5,
84     );
85     
86     $scheme_options = \Drupal::service('stream_wrapper_manager')->getNames(StreamWrapperInterface::WRITE_VISIBLE);
87     $element['uri_scheme'] = array(
88       '#type' => 'radios',
89       '#title' => t('Upload destination'),
90       '#options' => $scheme_options,
91       '#default_value' => $this->getSetting('uri_scheme'),
92       '#description' => t('Select where the final files should be stored. Private file storage has significantly more overhead than public files, but allows restricted access to files within this field.'),
93       '#weight' => 6,
94     );
95     return $element;
96   }
97
98   /**
99    * Form API callback
100    *
101    * Removes slashes from the beginning and end of the destination value and
102    * ensures that the file directory path is not included at the beginning of the
103    * value.
104    *
105    * This function is assigned as an #element_validate callback in
106    * settingsForm().
107    */
108   public static function validateDirectory($element, FormStateInterface $form_state) {
109     // Strip slashes from the beginning and end of $element['file_directory'].
110     $value = trim($element['#value'], '\\/');
111     $form_state->setValueForElement($element, $value);
112   }
113
114   /**
115    * Form API callback.
116    *
117    * This function is assigned as an #element_validate callback in
118    * settingsForm().
119    *
120    * This doubles as a convenience clean-up function and a validation routine.
121    * Commas are allowed by the end-user, but ultimately the value will be stored
122    * as a space-separated list for compatibility with file_validate_extensions().
123    */
124   public static function validateExtensions($element, FormStateInterface $form_state) {
125     if (!empty($element['#value'])) {
126       $extensions = preg_replace('/([, ]+\.?)/', ' ', trim(strtolower($element['#value'])));
127       $extensions = array_filter(explode(' ', $extensions));
128       $extensions = implode(' ', array_unique($extensions));
129       if (!preg_match('/^([a-z0-9]+([.][a-z0-9])* ?)+$/', $extensions)) {
130         $form_state->setError($element, t('The list of allowed extensions is not valid, be sure to exclude leading dots and to separate extensions with a comma or space.'));
131       }
132       else {
133         $form_state->setValueForElement($element, $extensions);
134       }
135     }
136   }
137
138   /**
139    * Form API callback.
140    *
141    * Ensures that a size has been entered and that it can be parsed by
142    * \Drupal\Component\Utility\Bytes::toInt().
143    *
144    * This function is assigned as an #element_validate callback in
145    * settingsForm().
146    */
147   public static function validateMaxFilesize($element, FormStateInterface $form_state) {
148     if (!empty($element['#value']) && (Bytes::toInt($element['#value']) == 0)) {
149       $form_state->setError($element, t('The option must contain a valid value. You may either leave the text field empty or enter a string like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes).'));
150     }
151   }
152
153   /**
154    * {@inheritdoc}
155    */
156   public function settingsSummary() {
157     $summary = array();
158     $summary[] = t('Progress indicator: @progress_indicator<br/>Extensions : @file_extensions<br/>File directory : @file_directory<br/>@max_filesize', 
159     array(
160       '@progress_indicator' => $this->getSetting('progress_indicator'),
161       '@file_extensions' => $this->getSetting('file_extensions'),
162       '@file_directory' => $this->getSetting('uri_scheme') . '://' . $this->getSetting('file_directory'),
163       '@max_filesize' => ($this->getSetting('max_filesize')) ? 'Max filesize: ' . $this->getSetting('max_filesize') : '',
164     ));
165     return $summary;
166   }
167
168   /**
169    * Overrides \Drupal\file\Plugin\Field\FieldWidget\FileWidget::formMultipleElements().
170    *
171    * Special handling for draggable multiple widgets and 'add more' button.
172    */
173   protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
174     $elements = parent::formMultipleElements($items, $form, $form_state);
175
176     $cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
177     $file_upload_help = array(
178       '#theme' => 'file_upload_help',
179       '#description' => '',
180       '#upload_validators' => $elements[0]['#upload_validators'],
181       '#cardinality' => $cardinality,
182     );
183     if ($cardinality == 1) {
184       // If there's only one field, return it as delta 0.
185       if (empty($elements[0]['#default_value']['fids'])) {
186         $file_upload_help['#description'] = $this->fieldDefinition->getDescription();
187         $elements[0]['#description'] = \Drupal::service('renderer')->renderPlain($file_upload_help);
188       }
189     }
190     else {
191       $elements['#file_upload_description'] = $file_upload_help;
192     }
193
194     return $elements;
195   }
196
197   /**
198    * {@inheritdoc}
199    */
200   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
201     $element = parent::formElement($items, $delta, $element, $form, $form_state);
202
203     // If not using custom extension validation, ensure this is a video.
204     $element['#upload_location'] = $this->getUploadLocation();
205     $element['#upload_validators'] = $this->getUploadValidators();
206
207     return $element;
208   }
209
210   /**
211    * Determines the URI for a video field.
212    *
213    * @param array $data
214    *   An array of token objects to pass to token_replace().
215    *
216    * @return string
217    *   An unsanitized file directory URI with tokens replaced. The result of
218    *   the token replacement is then converted to plain text and returned.
219    *
220    * @see token_replace()
221    */
222   public function getUploadLocation($data = array()) {
223     return static::doGetUploadLocation($this->getSettings(), $data);
224   }
225
226   /**
227    * Determines the URI for a video field.
228    *
229    * @param array $settings
230    *   The array of field settings.
231    * @param array $data
232    *   An array of token objects to pass to token_replace().
233    *
234    * @return string
235    *   An unsanitized file directory URI with tokens replaced. The result of
236    *   the token replacement is then converted to plain text and returned.
237    */
238   protected static function doGetUploadLocation(array $settings, $data = []) {
239     $destination = trim($settings['file_directory'], '/');
240
241     // Replace tokens. As the tokens might contain HTML we convert it to plain
242     // text.
243     $destination = PlainTextOutput::renderFromHtml(\Drupal::token()->replace($destination, $data));
244     return $settings['uri_scheme'] . '://' . $destination;
245   }
246
247   /**
248    * Retrieves the upload validators for a video field.
249    *
250    * @return array
251    *   An array suitable for passing to file_save_upload() or the file field
252    *   element's '#upload_validators' property.
253    */
254   public function getUploadValidators() {
255     $validators = array();
256     $settings = $this->getSettings();
257
258     // Cap the upload size according to the PHP limit.
259     $max_filesize = Bytes::toInt(file_upload_max_size());
260     if (!empty($settings['max_filesize'])) {
261       $max_filesize = min($max_filesize, Bytes::toInt($settings['max_filesize']));
262     }
263
264     // There is always a file size limit due to the PHP server limit.
265     $validators['file_validate_size'] = array($max_filesize);
266
267     // Add the extension check if necessary.
268     if (!empty($settings['file_extensions'])) {
269       $validators['file_validate_extensions'] = array($settings['file_extensions']);
270     }
271
272     return $validators;
273   }
274
275   /**
276    * Form API callback: Processes a video_upload field element.
277    *
278    * This method is assigned as a #process callback in formElement() method.
279    */
280   public static function process($element, FormStateInterface $form_state, $form) {
281     return parent::process($element, $form_state, $form);
282   }
283 }