Pull merge.
[yaffs-website] / web / core / modules / file / src / Element / ManagedFile.php
index 45c8aa7cec53c1814415d7cb134ce7d7030b13f6..95798c6734de0c3f48efe759d61cc382392a3212 100644 (file)
@@ -8,6 +8,7 @@ use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Ajax\AjaxResponse;
 use Drupal\Core\Ajax\ReplaceCommand;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element;
 use Drupal\Core\Render\Element\FormElement;
 use Drupal\Core\Site\Settings;
 use Drupal\Core\Url;
@@ -175,6 +176,9 @@ class ManagedFile extends FormElement {
 
     $form_parents = explode('/', $request->query->get('element_parents'));
 
+    // Sanitize form parents before using them.
+    $form_parents = array_filter($form_parents, [Element::class, 'child']);
+
     // Retrieve the element to be rendered.
     $form = NestedArray::getValue($form, $form_parents);
 
@@ -295,6 +299,10 @@ class ManagedFile extends FormElement {
 
       // Add the upload progress callback.
       $element['upload_button']['#ajax']['progress']['url'] = Url::fromRoute('file.ajax_progress', ['key' => $upload_progress_key]);
+
+      // Set a custom submit event so we can modify the upload progress
+      // identifier element before the form gets submitted.
+      $element['upload_button']['#ajax']['event'] = 'fileUpload';
     }
 
     // The file upload field itself.
@@ -398,15 +406,23 @@ class ManagedFile extends FormElement {
    * Render API callback: Validates the managed_file element.
    */
   public static function validateManagedFile(&$element, FormStateInterface $form_state, &$complete_form) {
-    // If referencing an existing file, only allow if there are existing
-    // references. This prevents unmanaged files from being deleted if this
-    // item were to be deleted.
     $clicked_button = end($form_state->getTriggeringElement()['#parents']);
     if ($clicked_button != 'remove_button' && !empty($element['fids']['#value'])) {
       $fids = $element['fids']['#value'];
       foreach ($fids as $fid) {
         if ($file = File::load($fid)) {
-          if ($file->isPermanent()) {
+          // If referencing an existing file, only allow if there are existing
+          // references. This prevents unmanaged files from being deleted if
+          // this item were to be deleted. When files that are no longer in use
+          // are automatically marked as temporary (now disabled by default),
+          // it is not safe to reference a permanent file without usage. Adding
+          // a usage and then later on removing it again would delete the file,
+          // but it is unknown if and where it is currently referenced. However,
+          // when files are not marked temporary (and then removed)
+          // automatically, it is safe to add and remove usages, as it would
+          // simply return to the current state.
+          // @see https://www.drupal.org/node/2891902
+          if ($file->isPermanent() && \Drupal::config('file.settings')->get('make_unused_managed_files_temporary')) {
             $references = static::fileUsage()->listUsage($file);
             if (empty($references)) {
               // We expect the field name placeholder value to be wrapped in t()