mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
FIX Fix namespace parsing under PHP 8, tweak readability of parser
$hadNamespace was ambiguously named, so the original PHP 8 support update marked it true when it was strictly meant to indicate that a namespace separator token had been encountered, resulting in bungled parsing of complex class specs like Class(["arg" => true]).
This commit is contained in:
parent
effe5c2e6f
commit
8ad4c4e024
@ -430,7 +430,7 @@ class ClassInfo
|
||||
// Keep track of the current bucket that we're putting data into
|
||||
$bucket = &$args;
|
||||
$bucketStack = [];
|
||||
$hadNamespace = false;
|
||||
$lastTokenWasNSSeparator = false;
|
||||
$currentKey = null;
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
@ -443,20 +443,20 @@ class ClassInfo
|
||||
($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED)
|
||||
) {
|
||||
// PHP 8 exposes the FQCN as a single T_NAME_QUALIFIED or T_NAME_FULLY_QUALIFIED token
|
||||
$class .= $token[1];
|
||||
$hadNamespace = true;
|
||||
$class = $token[1];
|
||||
} elseif ($class === null && is_array($token) && $token[0] === T_STRING) {
|
||||
$class = $token[1];
|
||||
} elseif (is_array($token) && $token[0] === T_NS_SEPARATOR) {
|
||||
$class .= $token[1];
|
||||
$hadNamespace = true;
|
||||
$lastTokenWasNSSeparator = true;
|
||||
} elseif ($token === '.') {
|
||||
// Treat service name separator as NS separator
|
||||
$class .= '.';
|
||||
$hadNamespace = true;
|
||||
} elseif ($hadNamespace && is_array($token) && $token[0] === T_STRING) {
|
||||
$lastTokenWasNSSeparator = true;
|
||||
} elseif ($lastTokenWasNSSeparator && is_array($token) && $token[0] === T_STRING) {
|
||||
// Found another section of a namespaced class
|
||||
$class .= $token[1];
|
||||
$hadNamespace = false;
|
||||
$lastTokenWasNSSeparator = false;
|
||||
// Get arguments
|
||||
} elseif (is_array($token)) {
|
||||
switch ($token[0]) {
|
||||
|
@ -265,4 +265,41 @@ class ClassInfoTest extends SapphireTest
|
||||
'ClassInfo::testClassesWithExtension() returns no classes after an extension being removed'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideClassSpecCases
|
||||
*/
|
||||
public function testParseClassSpec($input, $output)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$output,
|
||||
ClassInfo::parse_class_spec($input)
|
||||
);
|
||||
}
|
||||
|
||||
public function provideClassSpecCases()
|
||||
{
|
||||
return [
|
||||
'Standard class' => [
|
||||
'SimpleClass',
|
||||
['SimpleClass', []],
|
||||
],
|
||||
'Namespaced class' => [
|
||||
'Foo\\Bar\\NamespacedClass',
|
||||
['Foo\\Bar\\NamespacedClass', []],
|
||||
],
|
||||
'Namespaced class with service name' => [
|
||||
'Foo\\Bar\\NamespacedClass.withservicename',
|
||||
['Foo\\Bar\\NamespacedClass.withservicename', []],
|
||||
],
|
||||
'Namespaced class with argument' => [
|
||||
'Foo\\Bar\\NamespacedClass(["with-arg" => true])',
|
||||
['Foo\\Bar\\NamespacedClass', [["with-arg" => true]]],
|
||||
],
|
||||
'Namespaced class with service name and argument' => [
|
||||
'Foo\\Bar\\NamespacedClass.withmodifier(["and-arg" => true])',
|
||||
['Foo\\Bar\\NamespacedClass.withmodifier', [["and-arg" => true]]],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user