Permalink
Browse files

Merge branch '2.3' into 2.4

* 2.3:
  [Process] minor fixes
  Improve performance of getNextEmbedBlock by removing unnecessary preg_match and function calls.
  Avoid unnecessary line indentation calculation.
  Optimise Inline::evaluateScalar() for parsing strings.
  fixed CS
  fixed parsing Mongo DSN and added Test for it
  () is also a valid delimiter
  Adding PHP 5.6 to travis-ci tests
  Update BCryptPasswordEncoder.php
  [Validator] Removed PHP <5.3.3 specific code which is not officially supported.
  Fixed wrong redirect url if path contains some query parameters
  • Loading branch information...
2 parents 88118a2 + 30f35c0 commit 81e27d2a3e15cd4c36dc8218b6300aba21f1fcb3 @fabpot fabpot committed Feb 24, 2014
View
@@ -5,6 +5,7 @@ php:
- 5.3
- 5.4
- 5.5
+ - 5.6
- hhvm
matrix:
@@ -100,7 +100,11 @@ public function urlRedirectAction(Request $request, $path, $permanent = false, $
$qs = $request->getQueryString();
if ($qs) {
- $qs = '?'.$qs;
+ if (strpos($path, '?') === false) {
+ $qs = '?'.$qs;
+ } else {
+ $qs = '&'.$qs;
+ }
}
$port = '';
@@ -199,7 +199,36 @@ public function testUrlRedirect($scheme, $httpPort, $httpsPort, $requestScheme,
$this->assertRedirectUrl($returnValue, $expectedUrl);
}
- private function createRequestObject($scheme, $host, $port, $baseUrl)
+ public function pathQueryParamsProvider()
+ {
+ return array(
+ array('http://www.example.com/base/redirect-path', '/redirect-path', ''),
+ array('http://www.example.com/base/redirect-path?foo=bar', '/redirect-path?foo=bar', ''),
+ array('http://www.example.com/base/redirect-path?foo=bar', '/redirect-path', 'foo=bar'),
+ array('http://www.example.com/base/redirect-path?foo=bar&abc=example', '/redirect-path?foo=bar', 'abc=example'),
+ array('http://www.example.com/base/redirect-path?foo=bar&abc=example&baz=def', '/redirect-path?foo=bar', 'abc=example&baz=def'),
+ );
+ }
+
+ /**
+ * @dataProvider pathQueryParamsProvider
+ */
+ public function testPathQueryParams($expectedUrl, $path, $queryString)
+ {
+ $scheme = 'http';
+ $host = 'www.example.com';
+ $baseUrl = '/base';
+ $port = 80;
+
+ $request = $this->createRequestObject($scheme, $host, $port, $baseUrl, $queryString);
+
+ $controller = $this->createRedirectController();
+
+ $returnValue = $controller->urlRedirectAction($request, $path, false, $scheme, $port, null);
+ $this->assertRedirectUrl($returnValue, $expectedUrl);
+ }
+
+ private function createRequestObject($scheme, $host, $port, $baseUrl, $queryString = '')
{
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
$request
@@ -218,6 +247,10 @@ private function createRequestObject($scheme, $host, $port, $baseUrl)
->expects($this->any())
->method('getBaseUrl')
->will($this->returnValue($baseUrl));
+ $request
+ ->expects($this->any())
+ ->method('getQueryString')
+ ->will($this->returnValue($queryString));
return $request;
}
@@ -65,7 +65,11 @@ public static function create($expr)
$start = substr($m[1], 0, 1);
$end = substr($m[1], -1);
- if (($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) || ($start === '{' && $end === '}')) {
+ if (
+ ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
+ || ($start === '{' && $end === '}')
+ || ($start === '(' && $end === ')')
+ ) {
return new self(substr($m[1], 1, -1), $m[2], $end);
}
}
@@ -99,21 +99,19 @@ public function write(Profile $profile)
*/
protected function getMongo()
{
- if ($this->mongo === null) {
- if (preg_match('#^(mongodb://.*)/(.*)/(.*)$#', $this->dsn, $matches)) {
- $server = $matches[1].(!empty($matches[2]) ? '/'.$matches[2] : '');
- $database = $matches[2];
- $collection = $matches[3];
-
- $mongoClass = (version_compare(phpversion('mongo'), '1.3.0', '<')) ? '\Mongo' : '\MongoClient';
- $mongo = new $mongoClass($server);
- $this->mongo = $mongo->selectCollection($database, $collection);
- } else {
- throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use MongoDB with an invalid dsn "%s". The expected format is "mongodb://[user:pass@]host/database/collection"', $this->dsn));
- }
+ if (null !== $this->mongo) {
+ return $this->mongo;
+ }
+
+ if (!$parsedDsn = $this->parseDsn($this->dsn)) {
+ throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use MongoDB with an invalid dsn "%s". The expected format is "mongodb://[user:pass@]host/database/collection"', $this->dsn));
}
- return $this->mongo;
+ list($server, $database, $collection) = $parsedDsn;
+ $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? '\Mongo' : '\MongoClient';
+ $mongo = new $mongoClass($server);
+
+ return $this->mongo = $mongo->selectCollection($database, $collection);
}
/**
@@ -233,4 +231,27 @@ private function getProfile(array $data)
return $profile;
}
+
+ /**
+ * @param string $dsn
+ *
+ * @return null|array Array($server, $database, $collection)
+ */
+ private function parseDsn($dsn)
+ {
+ if (!preg_match('#^(mongodb://.*)/(.*)/(.*)$#', $dsn, $matches)) {
+ return;
+ }
+
+ $server = $matches[1];
+ $database = $matches[2];
+ $collection = $matches[3];
+ preg_match('#^mongodb://(([^:]+):?(.*)(?=@))?@?([^/]*)(.*)$#', $server, $matchesServer);
+
+ if ('' == $matchesServer[5] && '' != $matches[2]) {
+ $server .= '/'.$matches[2];
+ }
+
+ return array($server, $database, $collection);
+ }
}
@@ -71,6 +71,32 @@ public static function tearDownAfterClass()
}
}
+ public function getDsns()
+ {
+ return array(
+ array('mongodb://localhost/symfony_tests/profiler_data', array(
+ 'mongodb://localhost/symfony_tests',
+ 'symfony_tests',
+ 'profiler_data'
+ )),
+ array('mongodb://user:password@localhost/symfony_tests/profiler_data', array(
+ 'mongodb://user:password@localhost/symfony_tests',
+ 'symfony_tests',
+ 'profiler_data'
+ )),
+ array('mongodb://user:password@localhost/admin/symfony_tests/profiler_data', array(
+ 'mongodb://user:password@localhost/admin',
+ 'symfony_tests',
+ 'profiler_data'
+ )),
+ array('mongodb://user:password@localhost:27009,localhost:27010/?replicaSet=rs-name&authSource=admin/symfony_tests/profiler_data', array(
+ 'mongodb://user:password@localhost:27009,localhost:27010/?replicaSet=rs-name&authSource=admin',
+ 'symfony_tests',
+ 'profiler_data'
+ ))
+ );
+ }
+
public function testCleanup()
{
$dt = new \DateTime('-2 day');
@@ -87,6 +113,17 @@ public function testCleanup()
self::$storage->purge();
}
+ /**
+ * @dataProvider getDsns
+ */
+ public function testDsnParser($dsn, $expected)
+ {
+ $m = new \ReflectionMethod(self::$storage, 'parseDsn');
+ $m->setAccessible(true);
+
+ $this->assertEquals($expected, $m->invoke(self::$storage, $dsn));
+ }
+
public function testUtf8()
{
$profile = new Profile('utf8_test_profile');
@@ -865,7 +865,9 @@ public function getEnv()
public function setEnv(array $env)
{
// Process can not handle env values that are arrays
- $env = array_filter($env, function ($value) { if (!is_array($value)) { return true; } });
+ $env = array_filter($env, function ($value) {
+ return !is_array($value);
+ });
$this->env = array();
foreach ($env as $key => $value) {
@@ -1117,6 +1119,7 @@ private function validateTimeout($timeout)
* Reads pipes, executes callback.
*
* @param Boolean $blocking Whether to use blocking calls or not.
+ * @param Boolean $close Whether to close file handles or not.
*/
private function readPipes($blocking, $close)
{
@@ -76,7 +76,7 @@ public function unblock()
public function close()
{
$this->closeUnixPipes();
- foreach ($this->fileHandles as $offset => $handle) {
+ foreach ($this->fileHandles as $handle) {
fclose($handle);
}
$this->fileHandles = array();
@@ -218,6 +218,8 @@ public function write($blocking, $stdin)
/**
* Reads data in file handles.
*
+ * @param Boolean $close Whether to close file handles or not.
+ *
* @return array An array of read data indexed by their fd.
*/
private function readFileHandles($close = false)
@@ -253,6 +255,7 @@ private function readFileHandles($close = false)
* Reads data in file pipes streams.
*
* @param Boolean $blocking Whether to use blocking calls or not.
+ * @param Boolean $close Whether to close file handles or not.
*
* @return array An array of read data indexed by their fd.
*/
@@ -29,6 +29,7 @@ class BCryptPasswordEncoder extends BasePasswordEncoder
*
* @param integer $cost The algorithmic cost that should be used
*
+ * @throws \RuntimeException When no BCrypt encoder is available
* @throws \InvalidArgumentException if cost is out of range
*/
public function __construct($cost)
@@ -386,51 +386,55 @@ private static function parseMapping($mapping, &$i = 0)
private static function evaluateScalar($scalar)
{
$scalar = trim($scalar);
-
+ $scalarLower = strtolower($scalar);
switch (true) {
- case 'null' == strtolower($scalar):
+ case 'null' == $scalarLower:
case '' == $scalar:
case '~' == $scalar:
return null;
- case 0 === strpos($scalar, '!str'):
- return (string) substr($scalar, 5);
- case 0 === strpos($scalar, '! '):
- return intval(self::parseScalar(substr($scalar, 2)));
- case 0 === strpos($scalar, '!!php/object:'):
- if (self::$objectSupport) {
- return unserialize(substr($scalar, 13));
- }
-
- if (self::$exceptionOnInvalidType) {
- throw new ParseException('Object support when parsing a YAML file has been disabled.');
- }
-
- return null;
- case ctype_digit($scalar):
- $raw = $scalar;
- $cast = intval($scalar);
-
- return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
- case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)):
- $raw = $scalar;
- $cast = intval($scalar);
-
- return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
- case 'true' === strtolower($scalar):
+ case 'true' === $scalarLower:
return true;
- case 'false' === strtolower($scalar):
+ case 'false' === $scalarLower:
return false;
- case is_numeric($scalar):
- return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
- case 0 == strcasecmp($scalar, '.inf'):
- case 0 == strcasecmp($scalar, '.NaN'):
- return -log(0);
- case 0 == strcasecmp($scalar, '-.inf'):
- return log(0);
- case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
- return floatval(str_replace(',', '', $scalar));
- case preg_match(self::getTimestampRegex(), $scalar):
- return strtotime($scalar);
+ // Optimise for returning strings.
+ case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || $scalar[0] === '!' || is_numeric($scalar[0]):
+ switch (true) {
+ case 0 === strpos($scalar, '!str'):
+ return (string) substr($scalar, 5);
+ case 0 === strpos($scalar, '! '):
+ return intval(self::parseScalar(substr($scalar, 2)));
+ case 0 === strpos($scalar, '!!php/object:'):
+ if (self::$objectSupport) {
+ return unserialize(substr($scalar, 13));
+ }
+
+ if (self::$exceptionOnInvalidType) {
+ throw new ParseException('Object support when parsing a YAML file has been disabled.');
+ }
+
+ return null;
+ case ctype_digit($scalar):
+ $raw = $scalar;
+ $cast = intval($scalar);
+
+ return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
+ case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)):
+ $raw = $scalar;
+ $cast = intval($scalar);
+
+ return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
+ case is_numeric($scalar):
+ return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
+ case 0 == strcasecmp($scalar, '.inf'):
+ case 0 == strcasecmp($scalar, '.NaN'):
+ return -log(0);
+ case 0 == strcasecmp($scalar, '-.inf'):
+ return log(0);
+ case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
+ return floatval(str_replace(',', '', $scalar));
+ case preg_match(self::getTimestampRegex(), $scalar):
+ return strtotime($scalar);
+ }
default:
return (string) $scalar;
}
@@ -312,7 +312,9 @@ private function getNextEmbedBlock($indentation = null)
$removeComments = !preg_match($removeCommentsPattern, $this->currentLine);
while ($this->moveToNextLine()) {
- if ($this->getCurrentLineIndentation() === $newIndent) {
+ $indent = $this->getCurrentLineIndentation();
+
+ if ($indent === $newIndent) {
$removeComments = !preg_match($removeCommentsPattern, $this->currentLine);
}
@@ -321,20 +323,16 @@ private function getNextEmbedBlock($indentation = null)
break;
}
- if ($removeComments && $this->isCurrentLineEmpty() || $this->isCurrentLineBlank()) {
- if ($this->isCurrentLineBlank()) {
- $data[] = substr($this->currentLine, $newIndent);
- }
-
+ if ($this->isCurrentLineBlank()) {
+ $data[] = substr($this->currentLine, $newIndent);
continue;
}
- $indent = $this->getCurrentLineIndentation();
+ if ($removeComments && $this->isCurrentLineComment()) {
+ continue;
+ }
- if (preg_match('#^(?P<text> *)$#', $this->currentLine, $match)) {
- // empty line
- $data[] = $match['text'];
- } elseif ($indent >= $newIndent) {
+ if ($indent >= $newIndent) {
$data[] = substr($this->currentLine, $newIndent);
} elseif (0 == $indent) {
$this->moveToPreviousLine();

0 comments on commit 81e27d2

Please sign in to comment.