Merge branch '3.4' into 4.1
* 3.4: [Routing] fix trailing slash redirection when using RedirectableUrlMatcher [PropertyAccessor] fix encoding of cache keys [WebProfiler] Detect empty file paths in file viewer fixed CS Changes for upcoming Travis' infra migration Doc fix: clarify isMethodCacheable() returns true only for GET & HEAD [DomCrawler] exclude fields inside "template" tags Use XLIFF source rather than resname when there's no target [DoctrineBridge] catch errors while converting to db values in data collector [DoctrineBridge] fix case sensitivity issue in RememberMe\DoctrineTokenProvider [EventDispatcher] Unwrap wrapped listeners internally Indentation error [HttpFoundation] Fix trailing space for mime-type with parameters [HttpFoundation] Fixed absolute Request URI with default port properly parse backslashes in unquoted env vars Use intersection type when referring to ParentNodeDefinitionInterface [BrowserKit] fixed BC Break for HTTP_HOST header; implemented same behaviour for HTTPS server parameter
This commit is contained in:
commit
9dc9d7e0b7
|
@ -1,7 +1,6 @@
|
|||
language: php
|
||||
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
git:
|
||||
depth: 2
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace Symfony\Bridge\Doctrine\DataCollector;
|
|||
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Doctrine\DBAL\Logging\DebugStack;
|
||||
use Doctrine\DBAL\Types\ConversionException;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
@ -146,7 +147,14 @@ class DoctrineDataCollector extends DataCollector
|
|||
}
|
||||
if ($type instanceof Type) {
|
||||
$query['types'][$j] = $type->getBindingType();
|
||||
$param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform());
|
||||
try {
|
||||
$param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform());
|
||||
} catch (\TypeError $e) {
|
||||
// Error thrown while processing params, query is not explainable.
|
||||
$query['explainable'] = false;
|
||||
} catch (ConversionException $e) {
|
||||
$query['explainable'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ class DoctrineTokenProvider implements TokenProviderInterface
|
|||
*/
|
||||
public function loadTokenBySeries($series)
|
||||
{
|
||||
$sql = 'SELECT class, username, value, lastUsed'
|
||||
// the alias for lastUsed works around case insensitivity in PostgreSQL
|
||||
$sql = 'SELECT class, username, value, lastUsed AS last_used'
|
||||
.' FROM rememberme_token WHERE series=:series';
|
||||
$paramValues = array('series' => $series);
|
||||
$paramTypes = array('series' => \PDO::PARAM_STR);
|
||||
|
@ -58,7 +59,7 @@ class DoctrineTokenProvider implements TokenProviderInterface
|
|||
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row) {
|
||||
return new PersistentToken($row['class'], $row['username'], $series, $row['value'], new \DateTime($row['lastUsed']));
|
||||
return new PersistentToken($row['class'], $row['username'], $series, $row['value'], new \DateTime($row['last_used']));
|
||||
}
|
||||
|
||||
throw new TokenNotFoundException('No token found.');
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
namespace Symfony\Bridge\Doctrine\Tests\DataCollector;
|
||||
|
||||
use Doctrine\DBAL\Platforms\MySqlPlatform;
|
||||
use Doctrine\DBAL\Version;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\Doctrine\DataCollector\DoctrineDataCollector;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
@ -134,7 +135,7 @@ class DoctrineDataCollectorTest extends TestCase
|
|||
|
||||
public function paramProvider()
|
||||
{
|
||||
return array(
|
||||
$tests = array(
|
||||
array('some value', array(), 'some value', true),
|
||||
array(1, array(), 1, true),
|
||||
array(true, array(), true, true),
|
||||
|
@ -149,6 +150,13 @@ class DoctrineDataCollectorTest extends TestCase
|
|||
false,
|
||||
),
|
||||
);
|
||||
|
||||
if (version_compare(Version::VERSION, '2.6', '>=')) {
|
||||
$tests[] = array('this is not a date', array('date'), 'this is not a date', false);
|
||||
$tests[] = array(new \stdClass(), array('date'), 'Object(stdClass)', false);
|
||||
}
|
||||
|
||||
return $tests;
|
||||
}
|
||||
|
||||
private function createCollector($queries)
|
||||
|
|
|
@ -134,7 +134,7 @@ class CodeExtension extends AbstractExtension
|
|||
*/
|
||||
public function fileExcerpt($file, $line, $srcContext = 3)
|
||||
{
|
||||
if (is_readable($file)) {
|
||||
if (is_file($file) && is_readable($file)) {
|
||||
// highlight_file could throw warnings
|
||||
// see https://bugs.php.net/bug.php?id=25725
|
||||
$code = @highlight_file($file, true);
|
||||
|
@ -157,6 +157,8 @@ class CodeExtension extends AbstractExtension
|
|||
|
||||
return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,6 +54,11 @@ a.doc:hover {
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.empty {
|
||||
padding: 10px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.source {
|
||||
margin-top: 41px;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,16 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="header">
|
||||
<h1>{{ file }}{% if 0 < line %} <small>line {{ line }}</small>{% endif %}</h1>
|
||||
<a class="doc" href="https://symfony.com/doc/{{ constant('Symfony\\Component\\HttpKernel\\Kernel::VERSION') }}/reference/configuration/framework.html#ide" rel="help">Open in your IDE?</a>
|
||||
</div>
|
||||
<div class="source">
|
||||
{{ filename|file_excerpt(line, -1) }}
|
||||
</div>
|
||||
{% set source = filename|file_excerpt(line, -1) %}
|
||||
<div class="header">
|
||||
<h1>{{ file }}{% if 0 < line %} <small>line {{ line }}</small>{% endif %}</h1>
|
||||
<a class="doc" href="https://symfony.com/doc/{{ constant('Symfony\\Component\\HttpKernel\\Kernel::VERSION') }}/reference/configuration/framework.html#ide" rel="help">Open in your IDE?</a>
|
||||
</div>
|
||||
<div class="source">
|
||||
{% if source is null %}
|
||||
<p class="empty">The file is not readable.</p>
|
||||
{% else %}
|
||||
{{ source|raw }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -319,11 +319,17 @@ abstract class Client
|
|||
++$this->redirectCount;
|
||||
}
|
||||
|
||||
$originalUri = $uri;
|
||||
|
||||
$uri = $this->getAbsoluteUri($uri);
|
||||
|
||||
$server = array_merge($this->server, $server);
|
||||
|
||||
if (isset($server['HTTPS'])) {
|
||||
if (!empty($server['HTTP_HOST']) && null === parse_url($originalUri, PHP_URL_HOST)) {
|
||||
$uri = preg_replace('{^(https?\://)'.preg_quote($this->extractHost($uri)).'}', '${1}'.$server['HTTP_HOST'], $uri);
|
||||
}
|
||||
|
||||
if (isset($server['HTTPS']) && null === parse_url($originalUri, PHP_URL_SCHEME)) {
|
||||
$uri = preg_replace('{^'.parse_url($uri, PHP_URL_SCHEME).'}', $server['HTTPS'] ? 'https' : 'http', $uri);
|
||||
}
|
||||
|
||||
|
|
|
@ -741,7 +741,7 @@ class ClientTest extends TestCase
|
|||
$this->assertEquals('', $client->getServerParameter('HTTP_HOST'));
|
||||
$this->assertEquals('Symfony BrowserKit', $client->getServerParameter('HTTP_USER_AGENT'));
|
||||
|
||||
$this->assertEquals('http://www.example.com/https/www.example.com', $client->getRequest()->getUri());
|
||||
$this->assertEquals('https://www.example.com/https/www.example.com', $client->getRequest()->getUri());
|
||||
|
||||
$server = $client->getRequest()->getServer();
|
||||
|
||||
|
@ -755,7 +755,24 @@ class ClientTest extends TestCase
|
|||
$this->assertEquals('new-server-key-value', $server['NEW_SERVER_KEY']);
|
||||
|
||||
$this->assertArrayHasKey('HTTPS', $server);
|
||||
$this->assertFalse($server['HTTPS']);
|
||||
$this->assertTrue($server['HTTPS']);
|
||||
}
|
||||
|
||||
public function testRequestWithRelativeUri()
|
||||
{
|
||||
$client = new TestClient();
|
||||
|
||||
$client->request('GET', '/', array(), array(), array(
|
||||
'HTTP_HOST' => 'testhost',
|
||||
'HTTPS' => true,
|
||||
));
|
||||
$this->assertEquals('https://testhost/', $client->getRequest()->getUri());
|
||||
|
||||
$client->request('GET', 'https://www.example.com/', array(), array(), array(
|
||||
'HTTP_HOST' => 'testhost',
|
||||
'HTTPS' => false,
|
||||
));
|
||||
$this->assertEquals('https://www.example.com/', $client->getRequest()->getUri());
|
||||
}
|
||||
|
||||
public function testInternalRequest()
|
||||
|
|
|
@ -133,7 +133,7 @@ class NodeBuilder implements NodeParentInterface
|
|||
/**
|
||||
* Returns the parent node.
|
||||
*
|
||||
* @return ParentNodeDefinitionInterface|NodeDefinition The parent node
|
||||
* @return NodeDefinition&ParentNodeDefinitionInterface The parent node
|
||||
*/
|
||||
public function end()
|
||||
{
|
||||
|
|
|
@ -443,14 +443,14 @@ class Form extends Link implements \ArrayAccess
|
|||
// corresponding elements are either descendants or have a matching HTML5 form attribute
|
||||
$formId = Crawler::xpathLiteral($this->node->getAttribute('id'));
|
||||
|
||||
$fieldNodes = $xpath->query(sprintf('descendant::input[@form=%s] | descendant::button[@form=%1$s] | descendant::textarea[@form=%1$s] | descendant::select[@form=%1$s] | //form[@id=%1$s]//input[not(@form)] | //form[@id=%1$s]//button[not(@form)] | //form[@id=%1$s]//textarea[not(@form)] | //form[@id=%1$s]//select[not(@form)]', $formId));
|
||||
$fieldNodes = $xpath->query(sprintf('( descendant::input[@form=%s] | descendant::button[@form=%1$s] | descendant::textarea[@form=%1$s] | descendant::select[@form=%1$s] | //form[@id=%1$s]//input[not(@form)] | //form[@id=%1$s]//button[not(@form)] | //form[@id=%1$s]//textarea[not(@form)] | //form[@id=%1$s]//select[not(@form)] )[not(ancestor::template)]', $formId));
|
||||
foreach ($fieldNodes as $node) {
|
||||
$this->addField($node);
|
||||
}
|
||||
} else {
|
||||
// do the xpath query with $this->node as the context node, to only find descendant elements
|
||||
// however, descendant elements with form attribute are not part of this form
|
||||
$fieldNodes = $xpath->query('descendant::input[not(@form)] | descendant::button[not(@form)] | descendant::textarea[not(@form)] | descendant::select[not(@form)]', $this->node);
|
||||
$fieldNodes = $xpath->query('( descendant::input[not(@form)] | descendant::button[not(@form)] | descendant::textarea[not(@form)] | descendant::select[not(@form)] )[not(ancestor::template)]', $this->node);
|
||||
foreach ($fieldNodes as $node) {
|
||||
$this->addField($node);
|
||||
}
|
||||
|
|
|
@ -400,6 +400,10 @@ class FormTest extends TestCase
|
|||
|
||||
$form = $this->createForm('<form><input type="text" name="foo" value="foo" disabled="disabled" /><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
|
||||
$this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include disabled fields');
|
||||
|
||||
$form = $this->createForm('<form><template><input type="text" name="foo" value="foo" /></template><input type="text" name="bar" value="bar" /><input type="submit" /></form>');
|
||||
$this->assertEquals(array('bar' => 'bar'), $form->getValues(), '->getValues() does not include template fields');
|
||||
$this->assertFalse($form->has('foo'));
|
||||
}
|
||||
|
||||
public function testSetValues()
|
||||
|
@ -450,6 +454,10 @@ class FormTest extends TestCase
|
|||
|
||||
$form = $this->createForm('<form method="post"><input type="file" name="foo[bar]" disabled="disabled" /><input type="submit" /></form>');
|
||||
$this->assertEquals(array(), $form->getFiles(), '->getFiles() does not include disabled file fields');
|
||||
|
||||
$form = $this->createForm('<form method="post"><template><input type="file" name="foo"/></template><input type="text" name="bar" value="bar"/><input type="submit"/></form>');
|
||||
$this->assertEquals(array(), $form->getFiles(), '->getFiles() does not include template file fields');
|
||||
$this->assertFalse($form->has('foo'));
|
||||
}
|
||||
|
||||
public function testGetPhpFiles()
|
||||
|
@ -869,7 +877,7 @@ class FormTest extends TestCase
|
|||
protected function createForm($form, $method = null, $currentUri = null)
|
||||
{
|
||||
$dom = new \DOMDocument();
|
||||
$dom->loadHTML('<html>'.$form.'</html>');
|
||||
@$dom->loadHTML('<html>'.$form.'</html>');
|
||||
|
||||
$xPath = new \DOMXPath($dom);
|
||||
$nodes = $xPath->query('//input | //button');
|
||||
|
|
|
@ -225,10 +225,11 @@ final class Dotenv
|
|||
throw $this->createFormatException('Missing quote to end the value');
|
||||
}
|
||||
++$this->cursor;
|
||||
$value = str_replace(array('\\\\', '\\"', '\r', '\n'), array('\\', '"', "\r", "\n"), $value);
|
||||
$value = str_replace(array('\\"', '\r', '\n'), array('"', "\r", "\n"), $value);
|
||||
$resolvedValue = $value;
|
||||
$resolvedValue = $this->resolveVariables($resolvedValue);
|
||||
$resolvedValue = $this->resolveCommands($resolvedValue);
|
||||
$resolvedValue = str_replace('\\\\', '\\', $resolvedValue);
|
||||
$v .= $resolvedValue;
|
||||
} else {
|
||||
$value = '';
|
||||
|
@ -251,6 +252,7 @@ final class Dotenv
|
|||
$resolvedValue = $value;
|
||||
$resolvedValue = $this->resolveVariables($resolvedValue);
|
||||
$resolvedValue = $this->resolveCommands($resolvedValue);
|
||||
$resolvedValue = str_replace('\\\\', '\\', $resolvedValue);
|
||||
|
||||
if ($resolvedValue === $value && preg_match('/\s+/', $value)) {
|
||||
throw $this->createFormatException('A value containing spaces must be surrounded by quotes');
|
||||
|
@ -351,24 +353,31 @@ final class Dotenv
|
|||
}
|
||||
|
||||
$regex = '/
|
||||
(\\\\)? # escaped with a backslash?
|
||||
(?<!\\\\)
|
||||
(?P<backslashes>\\\\*) # escaped with a backslash?
|
||||
\$
|
||||
(?!\() # no opening parenthesis
|
||||
(\{)? # optional brace
|
||||
('.self::VARNAME_REGEX.') # var name
|
||||
(\})? # optional closing brace
|
||||
(?!\() # no opening parenthesis
|
||||
(?P<opening_brace>\{)? # optional brace
|
||||
(?P<name>'.self::VARNAME_REGEX.')? # var name
|
||||
(?P<closing_brace>\})? # optional closing brace
|
||||
/x';
|
||||
|
||||
$value = preg_replace_callback($regex, function ($matches) {
|
||||
if ('\\' === $matches[1]) {
|
||||
// odd number of backslashes means the $ character is escaped
|
||||
if (1 === \strlen($matches['backslashes']) % 2) {
|
||||
return substr($matches[0], 1);
|
||||
}
|
||||
|
||||
if ('{' === $matches[2] && !isset($matches[4])) {
|
||||
// unescaped $ not followed by variable name
|
||||
if (!isset($matches['name'])) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
if ('{' === $matches['opening_brace'] && !isset($matches['closing_brace'])) {
|
||||
throw $this->createFormatException('Unclosed braces on variable expansion');
|
||||
}
|
||||
|
||||
$name = $matches[3];
|
||||
$name = $matches['name'];
|
||||
if (isset($this->values[$name])) {
|
||||
$value = $this->values[$name];
|
||||
} elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
|
||||
|
@ -379,15 +388,14 @@ final class Dotenv
|
|||
$value = (string) getenv($name);
|
||||
}
|
||||
|
||||
if (!$matches[2] && isset($matches[4])) {
|
||||
if (!$matches['opening_brace'] && isset($matches['closing_brace'])) {
|
||||
$value .= '}';
|
||||
}
|
||||
|
||||
return $value;
|
||||
return $matches['backslashes'].$value;
|
||||
}, $value);
|
||||
|
||||
// unescape $
|
||||
return str_replace('\\$', '$', $value);
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function moveCursor($text)
|
||||
|
|
|
@ -66,6 +66,20 @@ class DotenvTest extends TestCase
|
|||
$_ENV['REMOTE'] = 'remote';
|
||||
|
||||
$tests = array(
|
||||
// backslashes
|
||||
array('FOO=foo\\\\bar', array('FOO' => 'foo\\bar')),
|
||||
array("FOO='foo\\\\bar'", array('FOO' => 'foo\\\\bar')),
|
||||
array('FOO="foo\\\\bar"', array('FOO' => 'foo\\bar')),
|
||||
|
||||
// escaped backslash in front of variable
|
||||
array("BAR=bar\nFOO=foo\\\\\$BAR", array('BAR' => 'bar', 'FOO' => 'foo\\bar')),
|
||||
array("BAR=bar\nFOO='foo\\\\\$BAR'", array('BAR' => 'bar', 'FOO' => 'foo\\\\$BAR')),
|
||||
array("BAR=bar\nFOO=\"foo\\\\\$BAR\"", array('BAR' => 'bar', 'FOO' => 'foo\\bar')),
|
||||
|
||||
array('FOO=foo\\\\\\$BAR', array('FOO' => 'foo\\$BAR')),
|
||||
array('FOO=\'foo\\\\\\$BAR\'', array('FOO' => 'foo\\\\\\$BAR')),
|
||||
array('FOO="foo\\\\\\$BAR"', array('FOO' => 'foo\\$BAR')),
|
||||
|
||||
// spaces
|
||||
array('FOO=bar', array('FOO' => 'bar')),
|
||||
array(' FOO=bar ', array('FOO' => 'bar')),
|
||||
|
|
|
@ -263,7 +263,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
|||
|
||||
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
|
||||
$priority = $this->getListenerPriority($eventName, $listener);
|
||||
$wrappedListener = new WrappedListener($listener, null, $this->stopwatch, $this);
|
||||
$wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this);
|
||||
$this->wrappedListeners[$eventName][] = $wrappedListener;
|
||||
$this->dispatcher->removeListener($eventName, $listener);
|
||||
$this->dispatcher->addListener($eventName, $wrappedListener, $priority);
|
||||
|
|
|
@ -426,7 +426,7 @@ class TestEventSubscriberWithPriorities implements EventSubscriberInterface
|
|||
return array(
|
||||
'pre.foo' => array('preFoo', 10),
|
||||
'post.foo' => array('postFoo'),
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1284,7 +1284,7 @@ class Request
|
|||
{
|
||||
$canonicalMimeType = null;
|
||||
if (false !== $pos = strpos($mimeType, ';')) {
|
||||
$canonicalMimeType = substr($mimeType, 0, $pos);
|
||||
$canonicalMimeType = trim(substr($mimeType, 0, $pos));
|
||||
}
|
||||
|
||||
if (null === static::$formats) {
|
||||
|
@ -1448,7 +1448,7 @@ class Request
|
|||
*
|
||||
* @see https://tools.ietf.org/html/rfc7231#section-4.2.3
|
||||
*
|
||||
* @return bool
|
||||
* @return bool True for GET and HEAD, false otherwise
|
||||
*/
|
||||
public function isMethodCacheable()
|
||||
{
|
||||
|
@ -1695,10 +1695,16 @@ class Request
|
|||
$this->server->remove('IIS_WasUrlRewritten');
|
||||
} elseif ($this->server->has('REQUEST_URI')) {
|
||||
$requestUri = $this->server->get('REQUEST_URI');
|
||||
|
||||
// HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path
|
||||
$schemeAndHttpHost = $this->getSchemeAndHttpHost();
|
||||
if (0 === strpos($requestUri, $schemeAndHttpHost)) {
|
||||
$requestUri = substr($requestUri, \strlen($schemeAndHttpHost));
|
||||
$uriComponents = parse_url($requestUri);
|
||||
|
||||
if (isset($uriComponents['path'])) {
|
||||
$requestUri = $uriComponents['path'];
|
||||
}
|
||||
|
||||
if (isset($uriComponents['query'])) {
|
||||
$requestUri .= '?'.$uriComponents['query'];
|
||||
}
|
||||
} elseif ($this->server->has('ORIG_PATH_INFO')) {
|
||||
// IIS 5.0, PHP as CGI
|
||||
|
|
|
@ -232,6 +232,55 @@ class RequestTest extends TestCase
|
|||
$this->assertEquals(80, $request->getPort());
|
||||
$this->assertEquals('test.com', $request->getHttpHost());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
// Fragment should not be included in the URI
|
||||
$request = Request::create('http://test.com/foo#bar');
|
||||
$this->assertEquals('http://test.com/foo', $request->getUri());
|
||||
}
|
||||
|
||||
public function testCreateWithRequestUri()
|
||||
{
|
||||
$request = Request::create('http://test.com:80/foo');
|
||||
$request->server->set('REQUEST_URI', 'http://test.com:80/foo');
|
||||
$this->assertEquals('http://test.com/foo', $request->getUri());
|
||||
$this->assertEquals('/foo', $request->getPathInfo());
|
||||
$this->assertEquals('test.com', $request->getHost());
|
||||
$this->assertEquals('test.com', $request->getHttpHost());
|
||||
$this->assertEquals(80, $request->getPort());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
$request = Request::create('http://test.com:8080/foo');
|
||||
$request->server->set('REQUEST_URI', 'http://test.com:8080/foo');
|
||||
$this->assertEquals('http://test.com:8080/foo', $request->getUri());
|
||||
$this->assertEquals('/foo', $request->getPathInfo());
|
||||
$this->assertEquals('test.com', $request->getHost());
|
||||
$this->assertEquals('test.com:8080', $request->getHttpHost());
|
||||
$this->assertEquals(8080, $request->getPort());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
$request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz'));
|
||||
$request->server->set('REQUEST_URI', 'http://test.com/foo?bar=foo');
|
||||
$this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
|
||||
$this->assertEquals('/foo', $request->getPathInfo());
|
||||
$this->assertEquals('bar=baz', $request->getQueryString());
|
||||
$this->assertEquals('test.com', $request->getHost());
|
||||
$this->assertEquals('test.com', $request->getHttpHost());
|
||||
$this->assertEquals(80, $request->getPort());
|
||||
$this->assertFalse($request->isSecure());
|
||||
|
||||
$request = Request::create('https://test.com:443/foo');
|
||||
$request->server->set('REQUEST_URI', 'https://test.com:443/foo');
|
||||
$this->assertEquals('https://test.com/foo', $request->getUri());
|
||||
$this->assertEquals('/foo', $request->getPathInfo());
|
||||
$this->assertEquals('test.com', $request->getHost());
|
||||
$this->assertEquals('test.com', $request->getHttpHost());
|
||||
$this->assertEquals(443, $request->getPort());
|
||||
$this->assertTrue($request->isSecure());
|
||||
|
||||
// Fragment should not be included in the URI
|
||||
$request = Request::create('http://test.com/foo#bar');
|
||||
$request->server->set('REQUEST_URI', 'http://test.com/foo#bar');
|
||||
$this->assertEquals('http://test.com/foo', $request->getUri());
|
||||
}
|
||||
|
||||
public function testCreateCheckPrecedence()
|
||||
|
@ -332,6 +381,9 @@ class RequestTest extends TestCase
|
|||
{
|
||||
$request = new Request();
|
||||
$this->assertEquals('json', $request->getFormat('application/json; charset=utf-8'));
|
||||
$this->assertEquals('json', $request->getFormat('application/json;charset=utf-8'));
|
||||
$this->assertEquals('json', $request->getFormat('application/json ; charset=utf-8'));
|
||||
$this->assertEquals('json', $request->getFormat('application/json ;charset=utf-8'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -412,7 +412,7 @@ class PropertyAccessor implements PropertyAccessorInterface
|
|||
*/
|
||||
private function getReadAccessInfo($class, $property)
|
||||
{
|
||||
$key = (false !== strpos($class, '@') ? rawurlencode($class) : $class).'..'.$property;
|
||||
$key = false !== strpbrk($key = $class.'..'.$property, '{}()/@:') ? rawurlencode($key) : $key;
|
||||
|
||||
if (isset($this->readPropertyCache[$key])) {
|
||||
return $this->readPropertyCache[$key];
|
||||
|
@ -587,7 +587,7 @@ class PropertyAccessor implements PropertyAccessorInterface
|
|||
*/
|
||||
private function getWriteAccessInfo(string $class, string $property, $value): array
|
||||
{
|
||||
$key = (false !== strpos($class, '@') ? rawurlencode($class) : $class).'..'.$property;
|
||||
$key = false !== strpbrk($key = $class.'..'.$property, '{}()/@:') ? rawurlencode($key) : $key;
|
||||
|
||||
if (isset($this->writePropertyCache[$key])) {
|
||||
return $this->writePropertyCache[$key];
|
||||
|
@ -753,7 +753,8 @@ class PropertyAccessor implements PropertyAccessorInterface
|
|||
}
|
||||
|
||||
if ($this->cacheItemPool) {
|
||||
$item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_PROPERTY_PATH.$propertyPath);
|
||||
$key = false !== strpbrk($propertyPath, '{}()/@:') ? rawurlencode($propertyPath) : $propertyPath;
|
||||
$item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_PROPERTY_PATH.str_replace('\\', '.', $key));
|
||||
if ($item->isHit()) {
|
||||
return $this->propertyPathCache[$propertyPath] = $item->get();
|
||||
}
|
||||
|
|
|
@ -582,6 +582,15 @@ class PropertyAccessorTest extends TestCase
|
|||
$this->assertEquals('baz', $propertyAccessor->getValue($obj, 'publicGetSetter'));
|
||||
}
|
||||
|
||||
public function testAttributeWithSpecialChars()
|
||||
{
|
||||
$obj = new \stdClass();
|
||||
$obj->{'@foo'} = 'bar';
|
||||
|
||||
$propertyAccessor = new PropertyAccessor(false, false, new ArrayAdapter());
|
||||
$this->assertSame('bar', $propertyAccessor->getValue($obj, '@foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\PropertyAccess\Exception\InvalidArgumentException
|
||||
* @expectedExceptionMessage Expected argument of type "Countable", "string" given
|
||||
|
|
|
@ -91,7 +91,7 @@ class XliffFileLoader implements LoaderInterface
|
|||
$source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
|
||||
// If the xlf file has another encoding specified, try to convert it because
|
||||
// simple_xml will always return utf-8 encoded values
|
||||
$target = $this->utf8ToCharset((string) (isset($translation->target) ? $translation->target : $source), $encoding);
|
||||
$target = $this->utf8ToCharset((string) (isset($translation->target) ? $translation->target : $translation->source), $encoding);
|
||||
|
||||
$catalogue->set((string) $source, $target, $domain);
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ class XliffFileLoaderTest extends TestCase
|
|||
$loader = new XliffFileLoader();
|
||||
$catalogue = $loader->load(__DIR__.'/../fixtures/resname.xlf', 'en', 'domain1');
|
||||
|
||||
$this->assertEquals(array('foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo'), $catalogue->all('domain1'));
|
||||
$this->assertEquals(array('foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo', 'qux' => 'qux source'), $catalogue->all('domain1'));
|
||||
}
|
||||
|
||||
public function testIncompleteResource()
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
<source>baz</source>
|
||||
<target>foo</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="4" resname="qux">
|
||||
<source>qux source</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
Reference in New Issue