vendor/symfony/http-foundation/FileBag.php line 22

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\HttpFoundation;
  11. use Symfony\Component\HttpFoundation\File\UploadedFile;
  12. /**
  13.  * FileBag is a container for uploaded files.
  14.  *
  15.  * @author Fabien Potencier <[email protected]>
  16.  * @author Bulat Shakirzyanov <[email protected]>
  17.  */
  18. class FileBag extends ParameterBag
  19. {
  20.     private const FILE_KEYS = ['error''name''size''tmp_name''type'];
  21.     /**
  22.      * @param array|UploadedFile[] $parameters An array of HTTP files
  23.      */
  24.     public function __construct(array $parameters = [])
  25.     {
  26.         $this->replace($parameters);
  27.     }
  28.     /**
  29.      * {@inheritdoc}
  30.      */
  31.     public function replace(array $files = [])
  32.     {
  33.         $this->parameters = [];
  34.         $this->add($files);
  35.     }
  36.     /**
  37.      * {@inheritdoc}
  38.      */
  39.     public function set(string $key$value)
  40.     {
  41.         if (!\is_array($value) && !$value instanceof UploadedFile) {
  42.             throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.');
  43.         }
  44.         parent::set($key$this->convertFileInformation($value));
  45.     }
  46.     /**
  47.      * {@inheritdoc}
  48.      */
  49.     public function add(array $files = [])
  50.     {
  51.         foreach ($files as $key => $file) {
  52.             $this->set($key$file);
  53.         }
  54.     }
  55.     /**
  56.      * Converts uploaded files to UploadedFile instances.
  57.      *
  58.      * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information
  59.      *
  60.      * @return UploadedFile[]|UploadedFile|null A (multi-dimensional) array of UploadedFile instances
  61.      */
  62.     protected function convertFileInformation($file)
  63.     {
  64.         if ($file instanceof UploadedFile) {
  65.             return $file;
  66.         }
  67.         $file $this->fixPhpFilesArray($file);
  68.         $keys array_keys($file);
  69.         sort($keys);
  70.         if (self::FILE_KEYS == $keys) {
  71.             if (\UPLOAD_ERR_NO_FILE == $file['error']) {
  72.                 $file null;
  73.             } else {
  74.                 $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], false);
  75.             }
  76.         } else {
  77.             $file array_map(function ($v) { return $v instanceof UploadedFile || \is_array($v) ? $this->convertFileInformation($v) : $v; }, $file);
  78.             if (array_keys($keys) === $keys) {
  79.                 $file array_filter($file);
  80.             }
  81.         }
  82.         return $file;
  83.     }
  84.     /**
  85.      * Fixes a malformed PHP $_FILES array.
  86.      *
  87.      * PHP has a bug that the format of the $_FILES array differs, depending on
  88.      * whether the uploaded file fields had normal field names or array-like
  89.      * field names ("normal" vs. "parent[child]").
  90.      *
  91.      * This method fixes the array to look like the "normal" $_FILES array.
  92.      *
  93.      * It's safe to pass an already converted array, in which case this method
  94.      * just returns the original array unmodified.
  95.      *
  96.      * @return array
  97.      */
  98.     protected function fixPhpFilesArray(array $data)
  99.     {
  100.         // Remove extra key added by PHP 8.1.
  101.         unset($data['full_path']);
  102.         $keys array_keys($data);
  103.         sort($keys);
  104.         if (self::FILE_KEYS != $keys || !isset($data['name']) || !\is_array($data['name'])) {
  105.             return $data;
  106.         }
  107.         $files $data;
  108.         foreach (self::FILE_KEYS as $k) {
  109.             unset($files[$k]);
  110.         }
  111.         foreach ($data['name'] as $key => $name) {
  112.             $files[$key] = $this->fixPhpFilesArray([
  113.                 'error' => $data['error'][$key],
  114.                 'name' => $name,
  115.                 'type' => $data['type'][$key],
  116.                 'tmp_name' => $data['tmp_name'][$key],
  117.                 'size' => $data['size'][$key],
  118.             ]);
  119.         }
  120.         return $files;
  121.     }
  122. }