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 <fabien@symfony.com>
  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 <fabien@symfony.com>
  16.  * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
  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.         if (\is_array($file)) {
  68.             $file $this->fixPhpFilesArray($file);
  69.             $keys array_keys($file);
  70.             sort($keys);
  71.             if (self::FILE_KEYS == $keys) {
  72.                 if (\UPLOAD_ERR_NO_FILE == $file['error']) {
  73.                     $file null;
  74.                 } else {
  75.                     $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], false);
  76.                 }
  77.             } else {
  78.                 $file array_map([$this'convertFileInformation'], $file);
  79.                 if (array_keys($keys) === $keys) {
  80.                     $file array_filter($file);
  81.                 }
  82.             }
  83.         }
  84.         return $file;
  85.     }
  86.     /**
  87.      * Fixes a malformed PHP $_FILES array.
  88.      *
  89.      * PHP has a bug that the format of the $_FILES array differs, depending on
  90.      * whether the uploaded file fields had normal field names or array-like
  91.      * field names ("normal" vs. "parent[child]").
  92.      *
  93.      * This method fixes the array to look like the "normal" $_FILES array.
  94.      *
  95.      * It's safe to pass an already converted array, in which case this method
  96.      * just returns the original array unmodified.
  97.      *
  98.      * @param array $data
  99.      *
  100.      * @return array
  101.      */
  102.     protected function fixPhpFilesArray($data)
  103.     {
  104.         $keys array_keys($data);
  105.         sort($keys);
  106.         if (self::FILE_KEYS != $keys || !isset($data['name']) || !\is_array($data['name'])) {
  107.             return $data;
  108.         }
  109.         $files $data;
  110.         foreach (self::FILE_KEYS as $k) {
  111.             unset($files[$k]);
  112.         }
  113.         foreach ($data['name'] as $key => $name) {
  114.             $files[$key] = $this->fixPhpFilesArray([
  115.                 'error' => $data['error'][$key],
  116.                 'name' => $name,
  117.                 'type' => $data['type'][$key],
  118.                 'tmp_name' => $data['tmp_name'][$key],
  119.                 'size' => $data['size'][$key],
  120.             ]);
  121.         }
  122.         return $files;
  123.     }
  124. }