[HttFoundation] extracted FileBag, ServerBag, fixed HeaderBag::add(), updated Request test
This commit is contained in:
parent
183c8c6f6c
commit
271e757f27
127
src/Symfony/Component/HttpFoundation/FileBag.php
Normal file
127
src/Symfony/Component/HttpFoundation/FileBag.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpFoundation;
|
||||
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
|
||||
/**
|
||||
* FileBag is a container for HTTP headers.
|
||||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
*/
|
||||
class FileBag extends ParameterBag
|
||||
{
|
||||
private $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see Symfony\Component\HttpFoundation\ParameterBag::replace()
|
||||
*/
|
||||
public function replace(array $files = array())
|
||||
{
|
||||
$this->parameters = array();
|
||||
$this->add($files);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see Symfony\Component\HttpFoundation\ParameterBag::set()
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
parent::set($key, $this->convertFileInformation($value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
* @see Symfony\Component\HttpFoundation\ParameterBag::add()
|
||||
*/
|
||||
public function add(array $files = array())
|
||||
{
|
||||
foreach ($files as $key => $file) {
|
||||
$this->set($key, $file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts uploaded files to UploadedFile instances.
|
||||
*
|
||||
* @param array $file A (multi-dimensional) array of uploaded file information
|
||||
*
|
||||
* @return array A (multi-dimensional) array of UploadedFile instances
|
||||
*/
|
||||
protected function convertFileInformation(array $file)
|
||||
{
|
||||
$file = $this->fixPhpFilesArray($file);
|
||||
if (is_array($file)) {
|
||||
$keys = array_keys($file);
|
||||
sort($keys);
|
||||
if ($keys == $this->fileKeys) {
|
||||
$file['error'] = (int) $file['error'];
|
||||
}
|
||||
if ($keys != $this->fileKeys) {
|
||||
$file = array_map(array($this, 'convertFileInformation'), $file);
|
||||
} else
|
||||
if ($file['error'] === UPLOAD_ERR_NO_FILE) {
|
||||
$file = null;
|
||||
} else {
|
||||
$file = new UploadedFile($file['tmp_name'], $file['name'],
|
||||
$file['type'], $file['size'], $file['error']);
|
||||
}
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes a malformed PHP $_FILES array.
|
||||
*
|
||||
* PHP has a bug that the format of the $_FILES array differs, depending on
|
||||
* whether the uploaded file fields had normal field names or array-like
|
||||
* field names ("normal" vs. "parent[child]").
|
||||
*
|
||||
* This method fixes the array to look like the "normal" $_FILES array.
|
||||
*
|
||||
* It's safe to pass an already converted array, in which case this method
|
||||
* just returns the original array unmodified.
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
protected function fixPhpFilesArray($data)
|
||||
{
|
||||
if (! is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
$keys = array_keys($data);
|
||||
sort($keys);
|
||||
if ($this->fileKeys != $keys || ! isset($data['name']) ||
|
||||
! is_array($data['name'])) {
|
||||
return $data;
|
||||
}
|
||||
$files = $data;
|
||||
foreach ($this->fileKeys as $k) {
|
||||
unset($files[$k]);
|
||||
}
|
||||
foreach (array_keys($data['name']) as $key) {
|
||||
$files[$key] = $this->fixPhpFilesArray(array(
|
||||
'error' => $data['error'][$key],
|
||||
'name' => $data['name'][$key], 'type' => $data['type'][$key],
|
||||
'tmp_name' => $data['tmp_name'][$key],
|
||||
'size' => $data['size'][$key]
|
||||
));
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
}
|
@ -62,6 +62,16 @@ class HeaderBag
|
||||
public function replace(array $headers = array())
|
||||
{
|
||||
$this->headers = array();
|
||||
$this->add($headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new headers the current HTTP headers set.
|
||||
*
|
||||
* @param array $headers An array of HTTP headers
|
||||
*/
|
||||
public function add(array $headers)
|
||||
{
|
||||
foreach ($headers as $key => $values) {
|
||||
$this->set($key, $values);
|
||||
}
|
||||
|
@ -103,9 +103,9 @@ class Request
|
||||
$this->query = new ParameterBag(null !== $query ? $query : $_GET);
|
||||
$this->attributes = new ParameterBag(null !== $attributes ? $attributes : array());
|
||||
$this->cookies = new ParameterBag(null !== $cookies ? $cookies : $_COOKIE);
|
||||
$this->files = new ParameterBag($this->convertFileInformation(null !== $files ? $files : $_FILES));
|
||||
$this->server = new ParameterBag(null !== $server ? $server : $_SERVER);
|
||||
$this->headers = new HeaderBag($this->initializeHeaders());
|
||||
$this->files = new FileBag(null !== $files ? $files : $_FILES);
|
||||
$this->server = new ServerBag(null !== $server ? $server : $_SERVER);
|
||||
$this->headers = new HeaderBag($this->server->getHeaders());
|
||||
|
||||
$this->content = null;
|
||||
$this->languages = null;
|
||||
@ -930,102 +930,6 @@ class Request
|
||||
return (string) $pathInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts uploaded files to UploadedFile instances.
|
||||
*
|
||||
* @param array $files A (multi-dimensional) array of uploaded file information
|
||||
*
|
||||
* @return array A (multi-dimensional) array of UploadedFile instances
|
||||
*/
|
||||
protected function convertFileInformation(array $files)
|
||||
{
|
||||
$fixedFiles = array();
|
||||
|
||||
foreach ($files as $key => $data) {
|
||||
$fixedFiles[$key] = $this->fixPhpFilesArray($data);
|
||||
}
|
||||
|
||||
$fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
|
||||
foreach ($fixedFiles as $key => $data) {
|
||||
if (is_array($data)) {
|
||||
$keys = array_keys($data);
|
||||
sort($keys);
|
||||
|
||||
if ($keys == $fileKeys) {
|
||||
$data['error'] = (int) $data['error'];
|
||||
}
|
||||
|
||||
if ($keys != $fileKeys) {
|
||||
$fixedFiles[$key] = $this->convertFileInformation($data);
|
||||
} else if ($data['error'] === UPLOAD_ERR_NO_FILE) {
|
||||
$fixedFiles[$key] = null;
|
||||
} else {
|
||||
$fixedFiles[$key] = new UploadedFile($data['tmp_name'], $data['name'], $data['type'], $data['size'], $data['error']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $fixedFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes a malformed PHP $_FILES array.
|
||||
*
|
||||
* PHP has a bug that the format of the $_FILES array differs, depending on
|
||||
* whether the uploaded file fields had normal field names or array-like
|
||||
* field names ("normal" vs. "parent[child]").
|
||||
*
|
||||
* This method fixes the array to look like the "normal" $_FILES array.
|
||||
*
|
||||
* It's safe to pass an already converted array, in which case this method
|
||||
* just returns the original array unmodified.
|
||||
*
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
protected function fixPhpFilesArray($data)
|
||||
{
|
||||
if (!is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
|
||||
$keys = array_keys($data);
|
||||
sort($keys);
|
||||
|
||||
if ($fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$files = $data;
|
||||
foreach ($fileKeys as $k) {
|
||||
unset($files[$k]);
|
||||
}
|
||||
foreach (array_keys($data['name']) as $key) {
|
||||
$files[$key] = $this->fixPhpFilesArray(array(
|
||||
'error' => $data['error'][$key],
|
||||
'name' => $data['name'][$key],
|
||||
'type' => $data['type'][$key],
|
||||
'tmp_name' => $data['tmp_name'][$key],
|
||||
'size' => $data['size'][$key],
|
||||
));
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
protected function initializeHeaders()
|
||||
{
|
||||
$headers = array();
|
||||
foreach ($this->server->all() as $key => $value) {
|
||||
if ('http_' === strtolower(substr($key, 0, 5))) {
|
||||
$headers[substr($key, 5)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
static protected function initializeFormats()
|
||||
{
|
||||
static::$formats = array(
|
||||
|
34
src/Symfony/Component/HttpFoundation/ServerBag.php
Normal file
34
src/Symfony/Component/HttpFoundation/ServerBag.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpFoundation;
|
||||
|
||||
/**
|
||||
* HeaderBag is a container for HTTP headers.
|
||||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
*/
|
||||
class ServerBag extends ParameterBag
|
||||
{
|
||||
public function getHeaders()
|
||||
{
|
||||
$headers = array();
|
||||
|
||||
foreach ($this->parameters as $key => $value) {
|
||||
if ('http_' === strtolower(substr($key, 0, 5))) {
|
||||
$headers[substr($key, 5)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
}
|
117
tests/Symfony/Tests/Component/HttpFoundation/FileBagTest.php
Normal file
117
tests/Symfony/Tests/Component/HttpFoundation/FileBagTest.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Tests\Component\HttpFoundation;
|
||||
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\FileBag;
|
||||
|
||||
/**
|
||||
* FileBagTest.
|
||||
*
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.org>
|
||||
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
*/
|
||||
class FileBagTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
public function testShouldConvertsUploadedFiles()
|
||||
{
|
||||
$tmpFile = $this->createTempFile();
|
||||
$file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
|
||||
|
||||
$bag = new FileBag(array('file' => array(
|
||||
'name' => basename($tmpFile),
|
||||
'type' => 'text/plain',
|
||||
'tmp_name' => $tmpFile,
|
||||
'error' => 0,
|
||||
'size' => 100
|
||||
)));
|
||||
|
||||
$this->assertEquals($file, $bag->get('file'));
|
||||
}
|
||||
|
||||
public function testShouldSetEmptyUploadedFilesToNull()
|
||||
{
|
||||
$bag = new FileBag(array('file' => array(
|
||||
'name' => '',
|
||||
'type' => '',
|
||||
'tmp_name' => '',
|
||||
'error' => UPLOAD_ERR_NO_FILE,
|
||||
'size' => 0
|
||||
)));
|
||||
|
||||
$this->assertEquals(null, $bag->get('file'));
|
||||
}
|
||||
|
||||
public function testShouldConvertUploadedFilesWithPhpBug()
|
||||
{
|
||||
$tmpFile = $this->createTempFile();
|
||||
$file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
|
||||
|
||||
$bag = new FileBag(array(
|
||||
'child' => array(
|
||||
'name' => array(
|
||||
'file' => basename($tmpFile),
|
||||
),
|
||||
'type' => array(
|
||||
'file' => 'text/plain',
|
||||
),
|
||||
'tmp_name' => array(
|
||||
'file' => $tmpFile,
|
||||
),
|
||||
'error' => array(
|
||||
'file' => 0,
|
||||
),
|
||||
'size' => array(
|
||||
'file' => 100,
|
||||
),
|
||||
)
|
||||
));
|
||||
|
||||
$files = $bag->all();
|
||||
$this->assertEquals($file, $files['child']['file']);
|
||||
}
|
||||
|
||||
public function testShouldConvertNestedUploadedFilesWithPhpBug()
|
||||
{
|
||||
$tmpFile = $this->createTempFile();
|
||||
$file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
|
||||
|
||||
$bag = new FileBag(array(
|
||||
'child' => array(
|
||||
'name' => array(
|
||||
'sub' => array('file' => basename($tmpFile))
|
||||
),
|
||||
'type' => array(
|
||||
'sub' => array('file' => 'text/plain')
|
||||
),
|
||||
'tmp_name' => array(
|
||||
'sub' => array('file' => $tmpFile)
|
||||
),
|
||||
'error' => array(
|
||||
'sub' => array('file' => 0)
|
||||
),
|
||||
'size' => array(
|
||||
'sub' => array('file' => 100)
|
||||
),
|
||||
)
|
||||
));
|
||||
|
||||
$files = $bag->all();
|
||||
$this->assertEquals($file, $files['child']['sub']['file']);
|
||||
}
|
||||
|
||||
protected function createTempFile()
|
||||
{
|
||||
return tempnam(sys_get_temp_dir(), 'FormTest');
|
||||
}
|
||||
}
|
@ -392,93 +392,6 @@ class RequestTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
|
||||
}
|
||||
|
||||
public function testInitializeConvertsUploadedFiles()
|
||||
{
|
||||
$tmpFile = $this->createTempFile();
|
||||
$file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
|
||||
|
||||
$request = Request::create('', 'get', array(), array(), array('file' => array(
|
||||
'name' => basename($tmpFile),
|
||||
'type' => 'text/plain',
|
||||
'tmp_name' => $tmpFile,
|
||||
'error' => 0,
|
||||
'size' => 100
|
||||
)));
|
||||
|
||||
$this->assertEquals($file, $request->files->get('file'));
|
||||
}
|
||||
|
||||
public function testInitializeDoesNotConvertEmptyUploadedFiles()
|
||||
{
|
||||
$request = Request::create('', 'get', array(), array(), array('file' => array(
|
||||
'name' => '',
|
||||
'type' => '',
|
||||
'tmp_name' => '',
|
||||
'error' => UPLOAD_ERR_NO_FILE,
|
||||
'size' => 0
|
||||
)));
|
||||
|
||||
$this->assertEquals(null, $request->files->get('file'));
|
||||
}
|
||||
|
||||
public function testInitializeConvertsUploadedFilesWithPhpBug()
|
||||
{
|
||||
$tmpFile = $this->createTempFile();
|
||||
$file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
|
||||
|
||||
$request = Request::create('', 'get', array(), array(), array(
|
||||
'child' => array(
|
||||
'name' => array(
|
||||
'file' => basename($tmpFile),
|
||||
),
|
||||
'type' => array(
|
||||
'file' => 'text/plain',
|
||||
),
|
||||
'tmp_name' => array(
|
||||
'file' => $tmpFile,
|
||||
),
|
||||
'error' => array(
|
||||
'file' => 0,
|
||||
),
|
||||
'size' => array(
|
||||
'file' => 100,
|
||||
),
|
||||
)
|
||||
));
|
||||
|
||||
$files = $request->files->all();
|
||||
$this->assertEquals($file, $files['child']['file']);
|
||||
}
|
||||
|
||||
public function testInitializeConvertsNestedUploadedFilesWithPhpBug()
|
||||
{
|
||||
$tmpFile = $this->createTempFile();
|
||||
$file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
|
||||
|
||||
$request = Request::create('', 'get', array(), array(), array(
|
||||
'child' => array(
|
||||
'name' => array(
|
||||
'sub' => array('file' => basename($tmpFile))
|
||||
),
|
||||
'type' => array(
|
||||
'sub' => array('file' => 'text/plain')
|
||||
),
|
||||
'tmp_name' => array(
|
||||
'sub' => array('file' => $tmpFile)
|
||||
),
|
||||
'error' => array(
|
||||
'sub' => array('file' => 0)
|
||||
),
|
||||
'size' => array(
|
||||
'sub' => array('file' => 100)
|
||||
),
|
||||
)
|
||||
));
|
||||
|
||||
$files = $request->files->all();
|
||||
$this->assertEquals($file, $files['child']['sub']['file']);
|
||||
}
|
||||
|
||||
public function testGetContentWorksTwiceInDefaultMode()
|
||||
{
|
||||
$req = new Request;
|
||||
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Tests\Component\HttpFoundation;
|
||||
|
||||
use Symfony\Component\HttpFoundation\ServerBag;
|
||||
|
||||
/**
|
||||
* ServerBagTest
|
||||
*
|
||||
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
*/
|
||||
class ServerBagTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testShouldExtractHeadersFromServerArray()
|
||||
{
|
||||
$server = array(
|
||||
'SOME_SERVER_VARIABLE' => 'value',
|
||||
'SOME_SERVER_VARIABLE2' => 'value',
|
||||
'ROOT' => 'value',
|
||||
'HTTP_CONTENT_TYPE' => 'text/html',
|
||||
'HTTP_CONTENT_LENGTH' => '0',
|
||||
'HTTP_ETAG' => 'asdf',
|
||||
);
|
||||
|
||||
$bag = new ServerBag($server);
|
||||
|
||||
$this->assertEquals(array(
|
||||
'CONTENT_TYPE' => 'text/html',
|
||||
'CONTENT_LENGTH' => '0',
|
||||
'ETAG' => 'asdf'
|
||||
), $bag->getHeaders());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user