+ */
+class ArrayConverter
+{
+ /**
+ * Converts linear messages array to tree-like array.
+ * For example this rray('foo.bar' => 'value') will be converted to array('foo' => array('bar' => 'value')).
+ *
+ * @param array $messages Linear messages array
+ *
+ * @return array Tree-like messages array
+ */
+ public static function expandToTree(array $messages)
+ {
+ $tree = array();
+
+ foreach ($messages as $id => $value) {
+ $referenceToElement = &self::getElementByPath($tree, explode('.', $id));
+
+ $referenceToElement = $value;
+
+ unset($referenceToElement);
+ }
+
+ return $tree;
+ }
+
+ private static function &getElementByPath(array &$tree, array $parts)
+ {
+ $elem = &$tree;
+ $parentOfElem = null;
+
+ foreach ($parts as $i => $part) {
+ if (isset($elem[$part]) && is_string($elem[$part])) {
+ /* Process next case:
+ * 'foo': 'test1',
+ * 'foo.bar': 'test2'
+ *
+ * $tree['foo'] was string before we found array {bar: test2}.
+ * Treat new element as string too, e.g. add $tree['foo.bar'] = 'test2';
+ */
+ $elem = &$elem[ implode('.', array_slice($parts, $i)) ];
+ break;
+ }
+ $parentOfElem = &$elem;
+ $elem = &$elem[$part];
+ }
+
+ if (is_array($elem) && count($elem) > 0 && $parentOfElem) {
+ /* Process next case:
+ * 'foo.bar': 'test1'
+ * 'foo': 'test2'
+ *
+ * $tree['foo'] was array = {bar: 'test1'} before we found string constant `foo`.
+ * Cancel treating $tree['foo'] as array and cancel back it expansion,
+ * e.g. make it $tree['foo.bar'] = 'test1' again.
+ */
+ self::cancelExpand($parentOfElem, $part, $elem);
+ }
+
+ return $elem;
+ }
+
+ private static function cancelExpand(array &$tree, $prefix, array $node)
+ {
+ $prefix .= '.';
+
+ foreach ($node as $id => $value) {
+ if (is_string($value)) {
+ $tree[$prefix.$id] = $value;
+ } else {
+ self::cancelExpand($tree, $prefix.$id, $value);
+ }
+ }
+ }
+}
diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json
index 6f1053e66caf0..e428dd04f3e15 100644
--- a/src/Symfony/Component/Translation/composer.json
+++ b/src/Symfony/Component/Translation/composer.json
@@ -19,10 +19,10 @@
"php": ">=5.3.9"
},
"require-dev": {
- "symfony/phpunit-bridge": "~2.7",
+ "symfony/phpunit-bridge": "~2.7|~3.0.0",
"symfony/config": "~2.7",
- "symfony/intl": "~2.3",
- "symfony/yaml": "~2.2",
+ "symfony/intl": "~2.3|~3.0.0",
+ "symfony/yaml": "~2.2|~3.0.0",
"psr/log": "~1.0"
},
"conflict": {
@@ -39,7 +39,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.7-dev"
+ "dev-master": "2.8-dev"
}
}
}
diff --git a/src/Symfony/Component/Validator/README.md b/src/Symfony/Component/Validator/README.md
index 9014ec67240ee..c29a26121d8f7 100644
--- a/src/Symfony/Component/Validator/README.md
+++ b/src/Symfony/Component/Validator/README.md
@@ -113,7 +113,7 @@ https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/ValidatorServiceP
Documentation:
-https://symfony.com/doc/2.7/book/validation.html
+https://symfony.com/doc/2.8/book/validation.html
JSR-303 Specification:
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php
index e23709f3fcfe6..20de505b58f4c 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php
@@ -220,14 +220,24 @@ protected function expectNoValidate()
protected function expectValidateAt($i, $propertyPath, $value, $group)
{
- $validator = $this->context->getValidator()->inContext($this->context);
- $validator->expects($this->at(2 * $i))
- ->method('atPath')
- ->with($propertyPath)
- ->will($this->returnValue($validator));
- $validator->expects($this->at(2 * $i + 1))
- ->method('validate')
- ->with($value, $this->logicalOr(null, array()), $group);
+ switch ($this->getApiVersion()) {
+ case Validation::API_VERSION_2_4:
+ $this->context->expects($this->at($i))
+ ->method('validate')
+ ->with($value, $propertyPath, $group);
+ break;
+ case Validation::API_VERSION_2_5:
+ case Validation::API_VERSION_2_5_BC:
+ $validator = $this->context->getValidator()->inContext($this->context);
+ $validator->expects($this->at(2 * $i))
+ ->method('atPath')
+ ->with($propertyPath)
+ ->will($this->returnValue($validator));
+ $validator->expects($this->at(2 * $i + 1))
+ ->method('validate')
+ ->with($value, $this->logicalOr(null, array(), $this->isInstanceOf('\Symfony\Component\Validator\Constraints\Valid')), $group);
+ break;
+ }
}
protected function expectValidateValueAt($i, $propertyPath, $value, $constraints, $group = null)
diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json
index b89fe1b134515..1e0bebe146a14 100644
--- a/src/Symfony/Component/Validator/composer.json
+++ b/src/Symfony/Component/Validator/composer.json
@@ -17,16 +17,16 @@
],
"require": {
"php": ">=5.3.9",
- "symfony/translation": "~2.4"
+ "symfony/translation": "~2.4|~3.0.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "~2.7",
- "symfony/http-foundation": "~2.1",
- "symfony/intl": "~2.3",
- "symfony/yaml": "~2.0,>=2.0.5",
- "symfony/config": "~2.2",
- "symfony/property-access": "~2.3",
- "symfony/expression-language": "~2.4",
+ "symfony/phpunit-bridge": "~2.7|~3.0.0",
+ "symfony/http-foundation": "~2.1|~3.0.0",
+ "symfony/intl": "~2.3|~3.0.0",
+ "symfony/yaml": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/config": "~2.2|~3.0.0",
+ "symfony/property-access": "~2.3|~3.0.0",
+ "symfony/expression-language": "~2.4|~3.0.0",
"doctrine/annotations": "~1.0",
"doctrine/cache": "~1.0",
"egulias/email-validator": "~1.2,>=1.2.1"
@@ -48,7 +48,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.7-dev"
+ "dev-master": "2.8-dev"
}
}
}
diff --git a/src/Symfony/Component/VarDumper/Caster/CutArrayStub.php b/src/Symfony/Component/VarDumper/Caster/CutArrayStub.php
new file mode 100644
index 0000000000000..f2a803053a6c0
--- /dev/null
+++ b/src/Symfony/Component/VarDumper/Caster/CutArrayStub.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Caster;
+
+/**
+ * Represents a cut array.
+ *
+ * @author Nicolas Grekas
+ */
+class CutArrayStub extends CutStub
+{
+ public $preservedSubset;
+
+ public function __construct(array $value, array $preservedKeys)
+ {
+ parent::__construct($value);
+
+ $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys));
+ $this->cut -= count($this->preservedSubset);
+ }
+}
diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php
index 79e8bb80b9afc..f4b1f47cf78ee 100644
--- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php
+++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php
@@ -20,6 +20,13 @@
*/
class SplCaster
{
+ private static $splFileObjectFlags = array(
+ \SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE',
+ \SplFileObject::READ_AHEAD => 'READ_AHEAD',
+ \SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY',
+ \SplFileObject::READ_CSV => 'READ_CSV',
+ );
+
public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, $isNested)
{
$prefix = Caster::PREFIX_VIRTUAL;
@@ -72,6 +79,93 @@ public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, S
return $a;
}
+ public static function castFileInfo(\SplFileInfo $c, array $a, Stub $stub, $isNested)
+ {
+ static $map = array(
+ 'path' => 'getPath',
+ 'filename' => 'getFilename',
+ 'basename' => 'getBasename',
+ 'pathname' => 'getPathname',
+ 'extension' => 'getExtension',
+ 'realPath' => 'getRealPath',
+ 'aTime' => 'getATime',
+ 'mTime' => 'getMTime',
+ 'cTime' => 'getCTime',
+ 'inode' => 'getInode',
+ 'size' => 'getSize',
+ 'perms' => 'getPerms',
+ 'owner' => 'getOwner',
+ 'group' => 'getGroup',
+ 'type' => 'getType',
+ 'writable' => 'isWritable',
+ 'readable' => 'isReadable',
+ 'executable' => 'isExecutable',
+ 'file' => 'isFile',
+ 'dir' => 'isDir',
+ 'link' => 'isLink',
+ 'linkTarget' => 'getLinkTarget',
+ );
+
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ foreach ($map as $key => $accessor) {
+ try {
+ $a[$prefix.$key] = $c->$accessor();
+ } catch (\Exception $e) {
+ }
+ }
+
+ if (isset($a[$prefix.'perms'])) {
+ $a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']);
+ }
+
+ static $mapDate = array('aTime', 'mTime', 'cTime');
+ foreach ($mapDate as $key) {
+ if (isset($a[$prefix.$key])) {
+ $a[$prefix.$key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix.$key]), $a[$prefix.$key]);
+ }
+ }
+
+ return $a;
+ }
+
+ public static function castFileObject(\SplFileObject $c, array $a, Stub $stub, $isNested)
+ {
+ static $map = array(
+ 'csvControl' => 'getCsvControl',
+ 'flags' => 'getFlags',
+ 'maxLineLen' => 'getMaxLineLen',
+ 'fstat' => 'fstat',
+ 'eof' => 'eof',
+ 'key' => 'key',
+ );
+
+ $prefix = Caster::PREFIX_VIRTUAL;
+
+ foreach ($map as $key => $accessor) {
+ try {
+ $a[$prefix.$key] = $c->$accessor();
+ } catch (\Exception $e) {
+ }
+ }
+
+ if (isset($a[$prefix.'flags'])) {
+ $flagsArray = array();
+ foreach (self::$splFileObjectFlags as $value => $name) {
+ if ($a[$prefix.'flags'] & $value) {
+ $flagsArray[] = $name;
+ }
+ }
+ $a[$prefix.'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix.'flags']);
+ }
+
+ if (isset($a[$prefix.'fstat'])) {
+ $a[$prefix.'fstat'] = new CutArrayStub($a[$prefix.'fstat'], array('dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks'));
+ }
+
+ return $a;
+ }
+
public static function castFixedArray(\SplFixedArray $c, array $a, Stub $stub, $isNested)
{
$a += array(
diff --git a/src/Symfony/Component/VarDumper/Caster/StubCaster.php b/src/Symfony/Component/VarDumper/Caster/StubCaster.php
index ab0f52e55ae9d..542f8a19f4afb 100644
--- a/src/Symfony/Component/VarDumper/Caster/StubCaster.php
+++ b/src/Symfony/Component/VarDumper/Caster/StubCaster.php
@@ -33,6 +33,11 @@ public static function castStub(Stub $c, array $a, Stub $stub, $isNested)
}
}
+ public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, $isNested)
+ {
+ return $isNested ? $c->preservedSubset : $a;
+ }
+
public static function cutInternals($obj, array $a, Stub $stub, $isNested)
{
if ($isNested) {
diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
index ff5f31341968b..6c433214dac24 100644
--- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
+++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
@@ -23,6 +23,7 @@ abstract class AbstractCloner implements ClonerInterface
{
public static $defaultCasters = array(
'Symfony\Component\VarDumper\Caster\CutStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
+ 'Symfony\Component\VarDumper\Caster\CutArrayStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castCutArray',
'Symfony\Component\VarDumper\Caster\ConstStub' => 'Symfony\Component\VarDumper\Caster\StubCaster::castStub',
'Closure' => 'Symfony\Component\VarDumper\Caster\ReflectionCaster::castClosure',
@@ -78,6 +79,8 @@ abstract class AbstractCloner implements ClonerInterface
'ArrayObject' => 'Symfony\Component\VarDumper\Caster\SplCaster::castArrayObject',
'SplDoublyLinkedList' => 'Symfony\Component\VarDumper\Caster\SplCaster::castDoublyLinkedList',
+ 'SplFileInfo' => 'Symfony\Component\VarDumper\Caster\SplCaster::castFileInfo',
+ 'SplFileObject' => 'Symfony\Component\VarDumper\Caster\SplCaster::castFileObject',
'SplFixedArray' => 'Symfony\Component\VarDumper\Caster\SplCaster::castFixedArray',
'SplHeap' => 'Symfony\Component\VarDumper\Caster\SplCaster::castHeap',
'SplObjectStorage' => 'Symfony\Component\VarDumper\Caster\SplCaster::castObjectStorage',
diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php
index be4947278d5aa..fe3c65042fd93 100644
--- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php
+++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php
@@ -11,8 +11,6 @@
namespace Symfony\Component\VarDumper\Tests\Caster;
-use Symfony\Component\VarDumper\Cloner\VarCloner;
-use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\Test\VarDumperTestCase;
/**
diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php
new file mode 100644
index 0000000000000..121428ccfedef
--- /dev/null
+++ b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php
@@ -0,0 +1,124 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Tests\Caster;
+
+use Symfony\Component\VarDumper\Test\VarDumperTestCase;
+
+/**
+ * @author Grégoire Pineau
+ */
+class SplCasterTest extends VarDumperTestCase
+{
+ public function getCastFileInfoTests()
+ {
+ return array(
+ array(__FILE__, <<<'EOTXT'
+SplFileInfo {
+ path: "%s/Tests/Caster"
+ filename: "SplCasterTest.php"
+ basename: "SplCasterTest.php"
+ pathname: "%s/Tests/Caster/SplCasterTest.php"
+ extension: "php"
+ realPath: "%s/Tests/Caster/SplCasterTest.php"
+ aTime: %s-%s-%d %d:%d:%d
+ mTime: %s-%s-%d %d:%d:%d
+ cTime: %s-%s-%d %d:%d:%d
+ inode: %d
+ size: %d
+ perms: 0%d
+ owner: %d
+ group: %d
+ type: "file"
+ writable: true
+ readable: true
+ executable: false
+ file: true
+ dir: false
+ link: false
+}
+EOTXT
+ ),
+ array('https://google.com/about', <<<'EOTXT'
+SplFileInfo {
+ path: "https://google.com"
+ filename: "about"
+ basename: "about"
+ pathname: "https://google.com/about"
+ extension: ""
+ realPath: false
+ writable: false
+ readable: false
+ executable: false
+ file: false
+ dir: false
+ link: false
+}
+EOTXT
+ ),
+ );
+ }
+
+ /** @dataProvider getCastFileInfoTests */
+ public function testCastFileInfo($file, $dump)
+ {
+ $this->assertDumpMatchesFormat($dump, new \SplFileInfo($file));
+ }
+
+ public function testCastFileObject()
+ {
+ $var = new \SplFileObject(__FILE__);
+ $var->setFlags(\SplFileObject::DROP_NEW_LINE | \SplFileObject::SKIP_EMPTY);
+ $dump = <<<'EOTXT'
+SplFileObject {
+ path: "%s/Tests/Caster"
+ filename: "SplCasterTest.php"
+ basename: "SplCasterTest.php"
+ pathname: "%s/Tests/Caster/SplCasterTest.php"
+ extension: "php"
+ realPath: "%s/Tests/Caster/SplCasterTest.php"
+ aTime: %s-%s-%d %d:%d:%d
+ mTime: %s-%s-%d %d:%d:%d
+ cTime: %s-%s-%d %d:%d:%d
+ inode: %d
+ size: %d
+ perms: 0%d
+ owner: %d
+ group: %d
+ type: "file"
+ writable: true
+ readable: true
+ executable: false
+ file: true
+ dir: false
+ link: false
+ csvControl: array:2 [
+ 0 => ","
+ 1 => """
+ ]
+ flags: DROP_NEW_LINE|SKIP_EMPTY
+ maxLineLen: 0
+ fstat: array:26 [
+ "dev" => %d
+ "ino" => %d
+ "nlink" => %d
+ "rdev" => 0
+ "blksize" => %d
+ "blocks" => %d
+ …20
+ ]
+ eof: false
+ key: 0
+}
+EOTXT;
+ $this->assertDumpMatchesFormat($dump, $var);
+ }
+}
diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json
index 5fec14fb23fb0..50b06fdcd27ee 100644
--- a/src/Symfony/Component/VarDumper/composer.json
+++ b/src/Symfony/Component/VarDumper/composer.json
@@ -19,7 +19,7 @@
"php": ">=5.3.9"
},
"require-dev": {
- "symfony/phpunit-bridge": "~2.7"
+ "symfony/phpunit-bridge": "~2.7|~3.0.0"
},
"suggest": {
"ext-symfony_debug": ""
@@ -31,7 +31,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.7-dev"
+ "dev-master": "2.8-dev"
}
}
}
diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json
index b07b439c96ec4..177608a79fec4 100644
--- a/src/Symfony/Component/Yaml/composer.json
+++ b/src/Symfony/Component/Yaml/composer.json
@@ -19,7 +19,7 @@
"php": ">=5.3.9"
},
"require-dev": {
- "symfony/phpunit-bridge": "~2.7"
+ "symfony/phpunit-bridge": "~2.7|~3.0.0"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Yaml\\": "" }
@@ -27,7 +27,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.7-dev"
+ "dev-master": "2.8-dev"
}
}
}