diff --git a/.travis.yml b/.travis.yml index 1fc3647f66..61d060433e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,11 @@ matrix: env: deps=high - php: 7.4 env: deps=low + - php: nightly + services: [memcached] fast_finish: true + allow_failures: + - php: nightly cache: directories: @@ -135,7 +139,9 @@ before_install: echo session.gc_probability = 0 >> $INI echo opcache.enable_cli = 1 >> $INI echo apc.enable_cli = 1 >> $INI - echo extension = memcached.so >> $INI + if [[ $PHP != nightly ]]; then + echo extension = memcached.so >> $INI + fi done - | @@ -147,6 +153,9 @@ before_install: if ! php --ri sodium > /dev/null; then tfold ext.libsodium tpecl libsodium sodium.so $INI fi + if [[ $PHP = nightly ]]; then + tfold ext.memcached tpecl memcached-3.1.5 memcached.so $INI + fi tfold ext.apcu tpecl apcu-5.1.17 apcu.so $INI tfold ext.mongodb tpecl mongodb-1.6.0 mongodb.so $INI @@ -223,6 +232,12 @@ install: export COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -not -wholename '*/Bridge/PhpUnit/*' -printf '%h\n' | sort) fi + - | + # Set composer's platform to php 7.4 if we're on php 8. + if [[ $PHP = nightly ]]; then + composer config platform.php 7.4.99 + fi + - | # Install symfony/flex if [[ $deps = low ]]; then diff --git a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php index 988ff22051..4aaba13425 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php @@ -71,8 +71,14 @@ class MemcachedAdapterTest extends AdapterTestCase */ public function testBadOptions($name, $value) { - $this->expectException('ErrorException'); - $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); + if (\PHP_VERSION_ID < 80000) { + $this->expectException('ErrorException'); + $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); + } else { + $this->expectException('Error'); + $this->expectExceptionMessage('Undefined class constant \'Memcached::'); + } + MemcachedAdapter::createConnection([], [$name => $value]); } diff --git a/src/Symfony/Component/Cache/Tests/Simple/MemcachedCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/MemcachedCacheTest.php index 2209c955f0..90641911e9 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/MemcachedCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/MemcachedCacheTest.php @@ -81,8 +81,14 @@ class MemcachedCacheTest extends CacheTestCase */ public function testBadOptions(string $name, $value) { - $this->expectException('ErrorException'); - $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); + if (\PHP_VERSION_ID < 80000) { + $this->expectException('ErrorException'); + $this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::'); + } else { + $this->expectException('Error'); + $this->expectExceptionMessage('Undefined class constant \'Memcached::'); + } + MemcachedCache::createConnection([], [$name => $value]); } diff --git a/src/Symfony/Component/VarDumper/Caster/Caster.php b/src/Symfony/Component/VarDumper/Caster/Caster.php index 81e238c321..4bdc66ac5b 100644 --- a/src/Symfony/Component/VarDumper/Caster/Caster.php +++ b/src/Symfony/Component/VarDumper/Caster/Caster.php @@ -45,7 +45,7 @@ class Caster * * @return array The array-cast of the object, with prefixed dynamic properties */ - public static function castObject($obj, string $class, bool $hasDebugInfo = false): array + public static function castObject($obj, string $class, bool $hasDebugInfo = false, string $debugClass = null): array { if ($hasDebugInfo) { try { @@ -64,6 +64,7 @@ class Caster if ($a) { static $publicProperties = []; + $debugClass = $debugClass ?? get_debug_type($obj); $i = 0; $prefixedKeys = []; @@ -77,8 +78,8 @@ class Caster if (!isset($publicProperties[$class][$k])) { $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; } - } elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) { - $prefixedKeys[$i] = "\0".get_parent_class($class).'@anonymous'.strrchr($k, "\0"); + } elseif ($debugClass !== $class && 1 === strpos($k, $class)) { + $prefixedKeys[$i] = "\0".$debugClass.strrchr($k, "\0"); } ++$i; } @@ -94,6 +95,9 @@ class Caster if ($hasDebugInfo && \is_array($debugInfo)) { foreach ($debugInfo as $k => $v) { if (!isset($k[0]) || "\0" !== $k[0]) { + if (\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) { + continue; + } $k = self::PREFIX_VIRTUAL.$k; } diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php index 0bb773e07b..5d2227d418 100644 --- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php @@ -162,15 +162,6 @@ class SplCaster return $a; } - public static function castFixedArray(\SplFixedArray $c, array $a, Stub $stub, $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'storage' => $c->toArray(), - ]; - - return $a; - } - public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, $isNested) { $storage = []; @@ -209,14 +200,16 @@ class SplCaster private static function castSplArray($c, array $a, Stub $stub, bool $isNested): array { $prefix = Caster::PREFIX_VIRTUAL; - $class = $stub->class; $flags = $c->getFlags(); if (!($flags & \ArrayObject::STD_PROP_LIST)) { $c->setFlags(\ArrayObject::STD_PROP_LIST); - $a = Caster::castObject($c, $class); + $a = Caster::castObject($c, \get_class($c), method_exists($c, '__debugInfo'), $stub->class); $c->setFlags($flags); } + if (\PHP_VERSION_ID < 70400) { + $a[$prefix.'storage'] = $c->getArrayCopy(); + } $a += [ $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), @@ -224,7 +217,6 @@ class SplCaster if ($c instanceof \ArrayObject) { $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass()); } - $a[$prefix.'storage'] = $c->getArrayCopy(); return $a; } diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index 4bf22aff97..6ecf366955 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -114,7 +114,6 @@ abstract class AbstractCloner implements ClonerInterface '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'], 'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], @@ -291,8 +290,8 @@ abstract class AbstractCloner implements ClonerInterface $obj = $stub->value; $class = $stub->class; - if (isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00")) { - $stub->class = get_parent_class($class).'@anonymous'; + if (\PHP_VERSION_ID < 80000 ? "\0" === ($class[15] ?? null) : false !== strpos($class, "@anonymous\0")) { + $stub->class = get_debug_type($obj); } if (isset($this->classInfo[$class])) { list($i, $parents, $hasDebugInfo, $fileInfo) = $this->classInfo[$class]; @@ -321,7 +320,7 @@ abstract class AbstractCloner implements ClonerInterface } $stub->attr += $fileInfo; - $a = Caster::castObject($obj, $class, $hasDebugInfo); + $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class); try { while ($i--) { diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php index 2c2189c8b5..a150475dc6 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php @@ -168,7 +168,7 @@ EOTXT $this->assertDumpMatchesFormat( <<<'EOTXT' -@anonymous { +class@anonymous { -foo: "foo" } EOTXT diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/PdoCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/PdoCasterTest.php index 19bbe0f80c..fca242cfc6 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/PdoCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/PdoCasterTest.php @@ -30,6 +30,7 @@ class PdoCasterTest extends TestCase { $pdo = new \PDO('sqlite::memory:'); $pdo->setAttribute(\PDO::ATTR_STATEMENT_CLASS, ['PDOStatement', [$pdo]]); + $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $cast = PdoCaster::castPdo($pdo, [], new Stub(), false); @@ -45,7 +46,7 @@ array:2 [ "\x00~\x00inTransaction" => false "\x00~\x00attributes" => array:9 [ "CASE" => NATURAL - "ERRMODE" => SILENT + "ERRMODE" => EXCEPTION "PERSISTENT" => false "DRIVER_NAME" => "sqlite" "ORACLE_NULLS" => NATURAL diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index 15f0b4e61d..293afd94eb 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -49,8 +49,8 @@ ReflectionClass { %A] methods: array:%d [ %A - "export" => ReflectionMethod { - +name: "export" + "__construct" => ReflectionMethod { + +name: "__construct" +class: "ReflectionClass" %A parameters: { $%s: ReflectionParameter { diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php index e26c371d72..24701be411 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php @@ -172,14 +172,17 @@ EOTXT; $expected = << 123 + ] flag::STD_PROP_LIST: false flag::ARRAY_AS_PROPS: false iteratorClass: "ArrayIterator" - storage: array:1 [ - 0 => 123 - ] } EOTXT; + if (\PHP_VERSION_ID < 70400) { + $expected = str_replace('-storage:', 'storage:', $expected); + } $this->assertDumpEquals($expected, $var); } @@ -190,13 +193,16 @@ EOTXT; $expected = << 234 ] + flag::STD_PROP_LIST: false + flag::ARRAY_AS_PROPS: false } EOTXT; + if (\PHP_VERSION_ID < 70400) { + $expected = str_replace('-storage:', 'storage:', $expected); + } $this->assertDumpEquals($expected, $var); } diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index 4f3b73f432..7c2c058a02 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -199,6 +199,7 @@ EOTXT; /** * @requires extension xml + * @requires PHP < 8.0 */ public function testXmlResource() { diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index bee166a790..3ce7cef280 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -18,7 +18,8 @@ "require": { "php": ">=7.1.3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php72": "~1.5" + "symfony/polyfill-php72": "~1.5", + "symfony/polyfill-php80": "^1.15" }, "require-dev": { "ext-iconv": "*",